winrt: enable hardware buttons for Windows 10

Previously the hardware and camera button handler were guarded inside a
Q_OS_WINPHONE which does not apply to Windows 10.

Instead use WINAPI_PARTITION_FAMILY like on other places, this covers
Windows Phone 8.1 as well as Windows 10.

To find windows.phone.ui.input.h at build time the Mobile Extension
directory needs to be added to the include paths inside qmake. On
runtime we need to check whether we have hardware buttons or not. In
case they exist, register the handlers, otherwise skip registration.
Skipping also helps to keep WACK succeeding.

Task-number: QTBUG-50427
Change-Id: Ibeae15dbde12553cebd2b73b1a40b754c014f426
Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com>
This commit is contained in:
Maurice Kalinowski 2016-01-13 12:57:18 +01:00
parent f831c97a08
commit c3376ed3f9
3 changed files with 70 additions and 40 deletions

View File

@ -193,6 +193,9 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
incDirs << crtInclude + QStringLiteral("/shared"); incDirs << crtInclude + QStringLiteral("/shared");
incDirs << crtInclude + QStringLiteral("/winrt"); incDirs << crtInclude + QStringLiteral("/winrt");
incDirs << kitDir + QStringLiteral("Extension SDKs/WindowsMobile/")
+ crtVersion + QStringLiteral("/Include/WinRT");
libDirs << vcInstallDir + QStringLiteral("lib/store/") + compilerArch; libDirs << vcInstallDir + QStringLiteral("lib/store/") + compilerArch;
libDirs << vcInstallDir + QStringLiteral("atlmfc/lib") + compilerArch; libDirs << vcInstallDir + QStringLiteral("atlmfc/lib") + compilerArch;

View File

@ -59,10 +59,16 @@
#include <windows.ui.core.h> #include <windows.ui.core.h>
#include <windows.ui.viewmanagement.h> #include <windows.ui.viewmanagement.h>
#include <windows.graphics.display.h> #include <windows.graphics.display.h>
#ifdef Q_OS_WINPHONE
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
# include <windows.phone.ui.input.h> # include <windows.phone.ui.input.h>
# if _MSC_VER >= 1900
# include <windows.foundation.metadata.h>
using namespace ABI::Windows::Foundation::Metadata;
# endif
#endif #endif
using namespace Microsoft::WRL; using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers; using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation; using namespace ABI::Windows::Foundation;
@ -73,13 +79,13 @@ using namespace ABI::Windows::UI::Core;
using namespace ABI::Windows::UI::ViewManagement; using namespace ABI::Windows::UI::ViewManagement;
using namespace ABI::Windows::Graphics::Display; using namespace ABI::Windows::Graphics::Display;
using namespace ABI::Windows::ApplicationModel::Core; using namespace ABI::Windows::ApplicationModel::Core;
#ifdef Q_OS_WINPHONE #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
using namespace ABI::Windows::Phone::UI::Input; using namespace ABI::Windows::Phone::UI::Input;
#endif #endif
typedef IEventHandler<IInspectable *> ResumeHandler; typedef IEventHandler<IInspectable *> ResumeHandler;
typedef IEventHandler<SuspendingEventArgs *> SuspendHandler; typedef IEventHandler<SuspendingEventArgs *> SuspendHandler;
#ifdef Q_OS_WINPHONE #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler; typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler;
typedef IEventHandler<CameraEventArgs*> CameraButtonHandler; typedef IEventHandler<CameraEventArgs*> CameraButtonHandler;
#endif #endif
@ -88,7 +94,7 @@ QT_BEGIN_NAMESPACE
typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken); typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken);
uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
#ifdef Q_OS_WINPHONE #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
typedef HRESULT (__stdcall IHardwareButtonsStatics::*HardwareButtonsCallbackRemover)(EventRegistrationToken); typedef HRESULT (__stdcall IHardwareButtonsStatics::*HardwareButtonsCallbackRemover)(EventRegistrationToken);
uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
typedef HRESULT (__stdcall IHardwareButtonsStatics2::*HardwareButtons2CallbackRemover)(EventRegistrationToken); typedef HRESULT (__stdcall IHardwareButtonsStatics2::*HardwareButtons2CallbackRemover)(EventRegistrationToken);
@ -105,11 +111,12 @@ public:
ComPtr<ICoreApplication> application; ComPtr<ICoreApplication> application;
QHash<CoreApplicationCallbackRemover, EventRegistrationToken> applicationTokens; QHash<CoreApplicationCallbackRemover, EventRegistrationToken> applicationTokens;
#ifdef Q_OS_WINPHONE #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
ComPtr<IHardwareButtonsStatics> hardwareButtons; ComPtr<IHardwareButtonsStatics> hardwareButtons;
QHash<HardwareButtonsCallbackRemover, EventRegistrationToken> buttonsTokens; QHash<HardwareButtonsCallbackRemover, EventRegistrationToken> buttonsTokens;
ComPtr<IHardwareButtonsStatics2> cameraButtons; ComPtr<IHardwareButtonsStatics2> cameraButtons;
QHash<HardwareButtons2CallbackRemover, EventRegistrationToken> cameraTokens; QHash<HardwareButtons2CallbackRemover, EventRegistrationToken> cameraTokens;
boolean hasHardwareButtons;
bool cameraHalfPressed : 1; bool cameraHalfPressed : 1;
bool cameraPressed : 1; bool cameraPressed : 1;
#endif #endif
@ -132,31 +139,48 @@ QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate)
&d->applicationTokens[&ICoreApplication::remove_Resuming]); &d->applicationTokens[&ICoreApplication::remove_Resuming]);
Q_ASSERT_SUCCEEDED(hr); Q_ASSERT_SUCCEEDED(hr);
#ifdef Q_OS_WINPHONE #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), #if _MSC_VER >= 1900
IID_PPV_ARGS(&d->hardwareButtons)); d->hasHardwareButtons = false;
Q_ASSERT_SUCCEEDED(hr); ComPtr<IApiInformationStatics> apiInformationStatics;
hr = d->hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTIntegration::onBackButtonPressed).Get(), hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation).Get(),
&d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]); IID_PPV_ARGS(&apiInformationStatics));
Q_ASSERT_SUCCEEDED(hr);
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), if (SUCCEEDED(hr)) {
IID_PPV_ARGS(&d->cameraButtons)); const HStringReference valueRef(L"Windows.Phone.UI.Input.HardwareButtons");
Q_ASSERT_SUCCEEDED(hr); hr = apiInformationStatics->IsTypePresent(valueRef.Get(), &d->hasHardwareButtons);
if (qEnvironmentVariableIntValue("QT_QPA_ENABLE_CAMERA_KEYS")) {
hr = d->cameraButtons->add_CameraPressed(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraPressed).Get(),
&d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraPressed]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->cameraButtons->add_CameraHalfPressed(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraHalfPressed).Get(),
&d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraHalfPressed]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->cameraButtons->add_CameraReleased(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraReleased).Get(),
&d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraReleased]);
Q_ASSERT_SUCCEEDED(hr);
} }
d->cameraPressed = false; #else
d->cameraHalfPressed = false; d->hasHardwareButtons = true;
#endif // Q_OS_WINPHONE #endif // _MSC_VER >= 1900
if (d->hasHardwareButtons) {
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(),
IID_PPV_ARGS(&d->hardwareButtons));
Q_ASSERT_SUCCEEDED(hr);
hr = d->hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTIntegration::onBackButtonPressed).Get(),
&d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]);
Q_ASSERT_SUCCEEDED(hr);
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(),
IID_PPV_ARGS(&d->cameraButtons));
Q_ASSERT_SUCCEEDED(hr);
if (qEnvironmentVariableIntValue("QT_QPA_ENABLE_CAMERA_KEYS")) {
hr = d->cameraButtons->add_CameraPressed(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraPressed).Get(),
&d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraPressed]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->cameraButtons->add_CameraHalfPressed(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraHalfPressed).Get(),
&d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraHalfPressed]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->cameraButtons->add_CameraReleased(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraReleased).Get(),
&d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraReleased]);
Q_ASSERT_SUCCEEDED(hr);
}
d->cameraPressed = false;
d->cameraHalfPressed = false;
}
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
QEventDispatcherWinRT::runOnXamlThread([d]() { QEventDispatcherWinRT::runOnXamlThread([d]() {
d->mainScreen = new QWinRTScreen; d->mainScreen = new QWinRTScreen;
@ -172,14 +196,17 @@ QWinRTIntegration::~QWinRTIntegration()
{ {
Q_D(QWinRTIntegration); Q_D(QWinRTIntegration);
HRESULT hr; HRESULT hr;
#ifdef Q_OS_WINPHONE
for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i) { #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
hr = (d->hardwareButtons.Get()->*i.key())(i.value()); if (d->hasHardwareButtons) {
Q_ASSERT_SUCCEEDED(hr); for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i) {
} hr = (d->hardwareButtons.Get()->*i.key())(i.value());
for (QHash<HardwareButtons2CallbackRemover, EventRegistrationToken>::const_iterator i = d->cameraTokens.begin(); i != d->cameraTokens.end(); ++i) { Q_ASSERT_SUCCEEDED(hr);
hr = (d->cameraButtons.Get()->*i.key())(i.value()); }
Q_ASSERT_SUCCEEDED(hr); for (QHash<HardwareButtons2CallbackRemover, EventRegistrationToken>::const_iterator i = d->cameraTokens.begin(); i != d->cameraTokens.end(); ++i) {
hr = (d->cameraButtons.Get()->*i.key())(i.value());
Q_ASSERT_SUCCEEDED(hr);
}
} }
#endif #endif
// Do not execute this on Windows Phone as the application is already // Do not execute this on Windows Phone as the application is already
@ -289,7 +316,7 @@ QPlatformTheme *QWinRTIntegration::createPlatformTheme(const QString &name) cons
// System-level integration points // System-level integration points
#ifdef Q_OS_WINPHONE #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
HRESULT QWinRTIntegration::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args) HRESULT QWinRTIntegration::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args)
{ {
Q_D(QWinRTIntegration); Q_D(QWinRTIntegration);
@ -339,7 +366,7 @@ HRESULT QWinRTIntegration::onCameraReleased(IInspectable *, ICameraEventArgs *)
d->cameraPressed = false; d->cameraPressed = false;
return S_OK; return S_OK;
} }
#endif // Q_OS_WINPHONE #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
HRESULT QWinRTIntegration::onSuspended(IInspectable *, ISuspendingEventArgs *) HRESULT QWinRTIntegration::onSuspended(IInspectable *, ISuspendingEventArgs *)
{ {

View File

@ -47,7 +47,7 @@ namespace ABI {
namespace Foundation { namespace Foundation {
struct IAsyncAction; struct IAsyncAction;
} }
#ifdef Q_OS_WINPHONE #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
namespace Phone { namespace Phone {
namespace UI { namespace UI {
namespace Input { namespace Input {
@ -100,7 +100,7 @@ public:
QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
private: private:
#ifdef Q_OS_WINPHONE #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args); HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args);
HRESULT onCameraPressed(IInspectable *, ABI::Windows::Phone::UI::Input::ICameraEventArgs *); HRESULT onCameraPressed(IInspectable *, ABI::Windows::Phone::UI::Input::ICameraEventArgs *);
HRESULT onCameraHalfPressed(IInspectable *, ABI::Windows::Phone::UI::Input::ICameraEventArgs *); HRESULT onCameraHalfPressed(IInspectable *, ABI::Windows::Phone::UI::Input::ICameraEventArgs *);