Windows Phone: Handle back-button press

When the back button is pressed, send an immediate key event to the
topmost window (or the application if there is no window). If it is
accepted, mark the native event as accepted and send a key release event.
This way, the application may call accept() on the KeyPress event for
Qt::Key_Back in order to create backstepping behaviors within the app.

This is in line with Android, which quits the app when the event is
ignored. On Windows Phone, the default behavior occurs when the event is
ignored, which is to back out of the application and leave it running
in the background.

Task-number: QTBUG-35951
Change-Id: I46d15478f441f73d3660370370689b2f9fa11f25
Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
This commit is contained in:
Andrew Knight 2014-03-07 12:39:47 +02:00 committed by The Qt Project
parent 3a1c223a0a
commit 7625c51ef4
2 changed files with 50 additions and 0 deletions

View File

@ -63,6 +63,9 @@
#include <windows.ui.viewmanagement.h>
#include <windows.graphics.display.h>
#include <windows.foundation.h>
#ifdef Q_OS_WINPHONE
#include <windows.phone.ui.input.h>
#endif
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
@ -75,6 +78,9 @@ using namespace ABI::Windows::UI::Input;
using namespace ABI::Windows::UI::ViewManagement;
using namespace ABI::Windows::Devices::Input;
using namespace ABI::Windows::Graphics::Display;
#ifdef Q_OS_WINPHONE
using namespace ABI::Windows::Phone::UI::Input;
#endif
typedef IEventHandler<IInspectable*> ResumeHandler;
typedef IEventHandler<SuspendingEventArgs*> SuspendHandler;
@ -87,6 +93,9 @@ typedef ITypedEventHandler<CoreWindow*, PointerEventArgs*> PointerHandler;
typedef ITypedEventHandler<CoreWindow*, WindowSizeChangedEventArgs*> SizeChangedHandler;
typedef ITypedEventHandler<CoreWindow*, VisibilityChangedEventArgs*> VisibilityChangedHandler;
typedef ITypedEventHandler<CoreWindow*, AutomationProviderRequestedEventArgs*> AutomationProviderRequestedHandler;
#ifdef Q_OS_WINPHONE
typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler;
#endif
QT_BEGIN_NAMESPACE
@ -465,6 +474,11 @@ QWinRTScreen::QWinRTScreen(ICoreWindow *window)
m_coreWindow->add_PointerReleased(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::MouseButtonRelease]);
m_coreWindow->add_PointerWheelChanged(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::Wheel]);
m_coreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &QWinRTScreen::onSizeChanged).Get(), &m_tokens[QEvent::Resize]);
#ifdef Q_OS_WINPHONE
ComPtr<IHardwareButtonsStatics> hardwareButtons;
if (SUCCEEDED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), &hardwareButtons)))
hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTScreen::onBackButtonPressed).Get(), &m_tokens[QEvent::User]);
#endif // Q_OS_WINPHONE
// Window event handlers
m_coreWindow->add_Activated(Callback<ActivatedHandler>(this, &QWinRTScreen::onActivated).Get(), &m_tokens[QEvent::WindowActivate]);
@ -1002,4 +1016,27 @@ HRESULT QWinRTScreen::onOrientationChanged(IInspectable *)
return S_OK;
}
#ifdef Q_OS_WINPHONE
HRESULT QWinRTScreen::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args)
{
QKeyEvent backPress(QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier);
backPress.setAccepted(false);
QObject *receiver = m_visibleWindows.isEmpty()
? static_cast<QObject *>(QGuiApplication::instance())
: static_cast<QObject *>(m_visibleWindows.first());
// If the event is ignored, the app will suspend
QGuiApplication::sendEvent(receiver, &backPress);
if (backPress.isAccepted()) {
args->put_Handled(true);
// If the app accepts the event, send the release for symmetry
QKeyEvent backRelease(QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier);
QGuiApplication::sendEvent(receiver, &backRelease);
}
return S_OK;
}
#endif // Q_OS_WINPHONE
QT_END_NAMESPACE

View File

@ -80,6 +80,15 @@ namespace ABI {
struct IDisplayPropertiesStatics;
}
}
#ifdef Q_OS_WINPHONE
namespace Phone {
namespace UI {
namespace Input {
struct IBackPressedEventArgs;
}
}
}
#endif
}
}
struct IInspectable;
@ -149,6 +158,10 @@ private:
HRESULT onOrientationChanged(IInspectable *);
#ifdef Q_OS_WINPHONE
HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args);
#endif
ABI::Windows::UI::Core::ICoreWindow *m_coreWindow;
ABI::Windows::UI::ViewManagement::IApplicationViewStatics *m_applicationView;
ABI::Windows::ApplicationModel::Core::ICoreApplication *m_application;