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("/winrt");
incDirs << kitDir + QStringLiteral("Extension SDKs/WindowsMobile/")
+ crtVersion + QStringLiteral("/Include/WinRT");
libDirs << vcInstallDir + QStringLiteral("lib/store/") + compilerArch;
libDirs << vcInstallDir + QStringLiteral("atlmfc/lib") + compilerArch;

View File

@ -59,10 +59,16 @@
#include <windows.ui.core.h>
#include <windows.ui.viewmanagement.h>
#include <windows.graphics.display.h>
#ifdef Q_OS_WINPHONE
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
# include <windows.phone.ui.input.h>
# if _MSC_VER >= 1900
# include <windows.foundation.metadata.h>
using namespace ABI::Windows::Foundation::Metadata;
# endif
#endif
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
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::Graphics::Display;
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;
#endif
typedef IEventHandler<IInspectable *> ResumeHandler;
typedef IEventHandler<SuspendingEventArgs *> SuspendHandler;
#ifdef Q_OS_WINPHONE
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler;
typedef IEventHandler<CameraEventArgs*> CameraButtonHandler;
#endif
@ -88,7 +94,7 @@ QT_BEGIN_NAMESPACE
typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken);
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);
uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
typedef HRESULT (__stdcall IHardwareButtonsStatics2::*HardwareButtons2CallbackRemover)(EventRegistrationToken);
@ -105,11 +111,12 @@ public:
ComPtr<ICoreApplication> application;
QHash<CoreApplicationCallbackRemover, EventRegistrationToken> applicationTokens;
#ifdef Q_OS_WINPHONE
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
ComPtr<IHardwareButtonsStatics> hardwareButtons;
QHash<HardwareButtonsCallbackRemover, EventRegistrationToken> buttonsTokens;
ComPtr<IHardwareButtonsStatics2> cameraButtons;
QHash<HardwareButtons2CallbackRemover, EventRegistrationToken> cameraTokens;
boolean hasHardwareButtons;
bool cameraHalfPressed : 1;
bool cameraPressed : 1;
#endif
@ -132,31 +139,48 @@ QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate)
&d->applicationTokens[&ICoreApplication::remove_Resuming]);
Q_ASSERT_SUCCEEDED(hr);
#ifdef Q_OS_WINPHONE
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);
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
#if _MSC_VER >= 1900
d->hasHardwareButtons = false;
ComPtr<IApiInformationStatics> apiInformationStatics;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation).Get(),
IID_PPV_ARGS(&apiInformationStatics));
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);
if (SUCCEEDED(hr)) {
const HStringReference valueRef(L"Windows.Phone.UI.Input.HardwareButtons");
hr = apiInformationStatics->IsTypePresent(valueRef.Get(), &d->hasHardwareButtons);
}
d->cameraPressed = false;
d->cameraHalfPressed = false;
#endif // Q_OS_WINPHONE
#else
d->hasHardwareButtons = true;
#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]() {
d->mainScreen = new QWinRTScreen;
@ -172,14 +196,17 @@ QWinRTIntegration::~QWinRTIntegration()
{
Q_D(QWinRTIntegration);
HRESULT hr;
#ifdef Q_OS_WINPHONE
for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i) {
hr = (d->hardwareButtons.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);
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
if (d->hasHardwareButtons) {
for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i) {
hr = (d->hardwareButtons.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
// 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
#ifdef Q_OS_WINPHONE
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
HRESULT QWinRTIntegration::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args)
{
Q_D(QWinRTIntegration);
@ -339,7 +366,7 @@ HRESULT QWinRTIntegration::onCameraReleased(IInspectable *, ICameraEventArgs *)
d->cameraPressed = false;
return S_OK;
}
#endif // Q_OS_WINPHONE
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
HRESULT QWinRTIntegration::onSuspended(IInspectable *, ISuspendingEventArgs *)
{

View File

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