From c0319d1cfb056c2e26f436357cdfdb3bdecd10f0 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Fri, 20 May 2016 14:21:42 +0200 Subject: winrt: focus action has to happen in the xaml thread Otherwise it will cause asserts and/or crashes. Change-Id: If8af4202395ae573b280744343dd853346a8c160 Reviewed-by: Oliver Wolff --- src/plugins/winrt/qwinrtcameracontrol.cpp | 90 +++++++++++++++++-------------- 1 file changed, 51 insertions(+), 39 deletions(-) diff --git a/src/plugins/winrt/qwinrtcameracontrol.cpp b/src/plugins/winrt/qwinrtcameracontrol.cpp index 5c41987a0..cc80c0e7d 100644 --- a/src/plugins/winrt/qwinrtcameracontrol.cpp +++ b/src/plugins/winrt/qwinrtcameracontrol.cpp @@ -1121,46 +1121,54 @@ bool QWinRTCameraControl::setFocus(QCameraFocus::FocusModes modes) if (d->status == QCamera::UnloadedStatus) return false; - ComPtr focusSettings; - ComPtr focusSettingsObject; - HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_Devices_FocusSettings).Get(), &focusSettingsObject); - Q_ASSERT_SUCCEEDED(hr); - hr = focusSettingsObject.As(&focusSettings); - Q_ASSERT_SUCCEEDED(hr); - FocusMode mode; - if (modes.testFlag(QCameraFocus::ContinuousFocus)) { - mode = FocusMode_Continuous; - } else if (modes.testFlag(QCameraFocus::AutoFocus) - || modes.testFlag(QCameraFocus::MacroFocus) - || modes.testFlag(QCameraFocus::InfinityFocus)) { - // The Macro and infinity focus modes are only supported in auto focus mode on WinRT. - // QML camera focus doesn't support combined focus flags settings. In the case of macro - // and infinity Focus modes, the auto focus setting is applied. - mode = FocusMode_Single; - } else { - emit error(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes.")); - return false; - } - hr = focusSettings->put_Mode(mode); - Q_ASSERT_SUCCEEDED(hr); - AutoFocusRange range = AutoFocusRange_Normal; - if (modes.testFlag(QCameraFocus::MacroFocus)) - range = AutoFocusRange_Macro; - else if (modes.testFlag(QCameraFocus::InfinityFocus)) - range = AutoFocusRange_FullRange; - hr = focusSettings->put_AutoFocusRange(range); - Q_ASSERT_SUCCEEDED(hr); - hr = focusSettings->put_WaitForFocus(true); - Q_ASSERT_SUCCEEDED(hr); - hr = focusSettings->put_DisableDriverFallback(false); - Q_ASSERT_SUCCEEDED(hr); + bool result = false; + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([modes, &result, d, this]() { + ComPtr focusSettings; + ComPtr focusSettingsObject; + HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_Devices_FocusSettings).Get(), &focusSettingsObject); + Q_ASSERT_SUCCEEDED(hr); + hr = focusSettingsObject.As(&focusSettings); + Q_ASSERT_SUCCEEDED(hr); + FocusMode mode; + if (modes.testFlag(QCameraFocus::ContinuousFocus)) { + mode = FocusMode_Continuous; + } else if (modes.testFlag(QCameraFocus::AutoFocus) + || modes.testFlag(QCameraFocus::MacroFocus) + || modes.testFlag(QCameraFocus::InfinityFocus)) { + // The Macro and infinity focus modes are only supported in auto focus mode on WinRT. + // QML camera focus doesn't support combined focus flags settings. In the case of macro + // and infinity Focus modes, the auto focus setting is applied. + mode = FocusMode_Single; + } else { + emit error(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes.")); + result = false; + return S_OK; + } + hr = focusSettings->put_Mode(mode); + Q_ASSERT_SUCCEEDED(hr); + AutoFocusRange range = AutoFocusRange_Normal; + if (modes.testFlag(QCameraFocus::MacroFocus)) + range = AutoFocusRange_Macro; + else if (modes.testFlag(QCameraFocus::InfinityFocus)) + range = AutoFocusRange_FullRange; + hr = focusSettings->put_AutoFocusRange(range); + Q_ASSERT_SUCCEEDED(hr); + hr = focusSettings->put_WaitForFocus(true); + Q_ASSERT_SUCCEEDED(hr); + hr = focusSettings->put_DisableDriverFallback(false); + Q_ASSERT_SUCCEEDED(hr); - ComPtr focusControl2; - hr = d->focusControl.As(&focusControl2); + ComPtr focusControl2; + hr = d->focusControl.As(&focusControl2); + Q_ASSERT_SUCCEEDED(hr); + hr = focusControl2->Configure(focusSettings.Get()); + result = SUCCEEDED(hr); + RETURN_OK_IF_FAILED("Failed to configure camera focus control"); + return S_OK; + }); Q_ASSERT_SUCCEEDED(hr); - hr = focusControl2->Configure(focusSettings.Get()); - RETURN_FALSE_IF_FAILED("Failed to configure camera focus control"); - return true; + Q_UNUSED(hr); // Silence release build + return result; } bool QWinRTCameraControl::setFocusPoint(const QPointF &focusPoint) @@ -1224,7 +1232,11 @@ bool QWinRTCameraControl::focus() if (!d->focusControl || status == AsyncStatus::Started) return false; - hr = d->focusControl->FocusAsync(&d->focusOperation); + QEventDispatcherWinRT::runOnXamlThread([&d, &hr]() { + hr = d->focusControl->FocusAsync(&d->focusOperation); + Q_ASSERT_SUCCEEDED(hr); + return S_OK; + }); const long errorCode = HRESULT_CODE(hr); if (errorCode == ERROR_OPERATION_IN_PROGRESS || errorCode == ERROR_WRITE_PROTECT) { -- cgit v1.2.3