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 <oliver.wolff@qt.io>
This commit is contained in:
Maurice Kalinowski
2016-05-20 14:21:42 +02:00
parent 6d5f375644
commit c0319d1cfb

View File

@@ -1121,46 +1121,54 @@ bool QWinRTCameraControl::setFocus(QCameraFocus::FocusModes modes)
if (d->status == QCamera::UnloadedStatus) if (d->status == QCamera::UnloadedStatus)
return false; return false;
ComPtr<IFocusSettings> focusSettings; bool result = false;
ComPtr<IInspectable> focusSettingsObject; HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([modes, &result, d, this]() {
HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_Devices_FocusSettings).Get(), &focusSettingsObject); ComPtr<IFocusSettings> focusSettings;
Q_ASSERT_SUCCEEDED(hr); ComPtr<IInspectable> focusSettingsObject;
hr = focusSettingsObject.As(&focusSettings); HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_Devices_FocusSettings).Get(), &focusSettingsObject);
Q_ASSERT_SUCCEEDED(hr); Q_ASSERT_SUCCEEDED(hr);
FocusMode mode; hr = focusSettingsObject.As(&focusSettings);
if (modes.testFlag(QCameraFocus::ContinuousFocus)) { Q_ASSERT_SUCCEEDED(hr);
mode = FocusMode_Continuous; FocusMode mode;
} else if (modes.testFlag(QCameraFocus::AutoFocus) if (modes.testFlag(QCameraFocus::ContinuousFocus)) {
|| modes.testFlag(QCameraFocus::MacroFocus) mode = FocusMode_Continuous;
|| modes.testFlag(QCameraFocus::InfinityFocus)) { } else if (modes.testFlag(QCameraFocus::AutoFocus)
// The Macro and infinity focus modes are only supported in auto focus mode on WinRT. || modes.testFlag(QCameraFocus::MacroFocus)
// QML camera focus doesn't support combined focus flags settings. In the case of macro || modes.testFlag(QCameraFocus::InfinityFocus)) {
// and infinity Focus modes, the auto focus setting is applied. // The Macro and infinity focus modes are only supported in auto focus mode on WinRT.
mode = FocusMode_Single; // QML camera focus doesn't support combined focus flags settings. In the case of macro
} else { // and infinity Focus modes, the auto focus setting is applied.
emit error(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes.")); mode = FocusMode_Single;
return false; } else {
} emit error(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes."));
hr = focusSettings->put_Mode(mode); result = false;
Q_ASSERT_SUCCEEDED(hr); return S_OK;
AutoFocusRange range = AutoFocusRange_Normal; }
if (modes.testFlag(QCameraFocus::MacroFocus)) hr = focusSettings->put_Mode(mode);
range = AutoFocusRange_Macro; Q_ASSERT_SUCCEEDED(hr);
else if (modes.testFlag(QCameraFocus::InfinityFocus)) AutoFocusRange range = AutoFocusRange_Normal;
range = AutoFocusRange_FullRange; if (modes.testFlag(QCameraFocus::MacroFocus))
hr = focusSettings->put_AutoFocusRange(range); range = AutoFocusRange_Macro;
Q_ASSERT_SUCCEEDED(hr); else if (modes.testFlag(QCameraFocus::InfinityFocus))
hr = focusSettings->put_WaitForFocus(true); range = AutoFocusRange_FullRange;
Q_ASSERT_SUCCEEDED(hr); hr = focusSettings->put_AutoFocusRange(range);
hr = focusSettings->put_DisableDriverFallback(false); Q_ASSERT_SUCCEEDED(hr);
Q_ASSERT_SUCCEEDED(hr); hr = focusSettings->put_WaitForFocus(true);
Q_ASSERT_SUCCEEDED(hr);
hr = focusSettings->put_DisableDriverFallback(false);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IFocusControl2> focusControl2; ComPtr<IFocusControl2> focusControl2;
hr = d->focusControl.As(&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); Q_ASSERT_SUCCEEDED(hr);
hr = focusControl2->Configure(focusSettings.Get()); Q_UNUSED(hr); // Silence release build
RETURN_FALSE_IF_FAILED("Failed to configure camera focus control"); return result;
return true;
} }
bool QWinRTCameraControl::setFocusPoint(const QPointF &focusPoint) bool QWinRTCameraControl::setFocusPoint(const QPointF &focusPoint)
@@ -1224,7 +1232,11 @@ bool QWinRTCameraControl::focus()
if (!d->focusControl || status == AsyncStatus::Started) if (!d->focusControl || status == AsyncStatus::Started)
return false; 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); const long errorCode = HRESULT_CODE(hr);
if (errorCode == ERROR_OPERATION_IN_PROGRESS if (errorCode == ERROR_OPERATION_IN_PROGRESS
|| errorCode == ERROR_WRITE_PROTECT) { || errorCode == ERROR_WRITE_PROTECT) {