qwinrtscreen.cpp 41.50 KiB
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl.html.
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or later as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included in
** the packaging of this file. Please review the following information to
** ensure the GNU General Public License version 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
** $QT_END_LICENSE$
****************************************************************************/
#include "qwinrtscreen.h"
#include "qwinrtbackingstore.h"
#include "qwinrtinputcontext.h"
#include "qwinrtcursor.h"
#include <private/qeventdispatcher_winrt_p.h>
#include <QtGui/QSurfaceFormat>
#include <QtGui/QGuiApplication>
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/qt_windows.h>
#include <QtCore/qfunctions_winrt.h>
#include <functional>
#include <wrl.h>
#include <windows.system.h>
#include <Windows.Applicationmodel.h>
#include <Windows.ApplicationModel.core.h>
#include <windows.devices.input.h>
#include <windows.ui.h>
#include <windows.ui.core.h>
#include <windows.ui.input.h>
#include <windows.ui.xaml.h>
#include <windows.ui.viewmanagement.h>
#include <windows.graphics.display.h>
#include <windows.foundation.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::ApplicationModel;
using namespace ABI::Windows::ApplicationModel::Core;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::System;
using namespace ABI::Windows::UI;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
using namespace ABI::Windows::UI::Core; using namespace ABI::Windows::UI::Input; using namespace ABI::Windows::UI::ViewManagement; using namespace ABI::Windows::Devices::Input; using namespace ABI::Windows::Graphics::Display; typedef ITypedEventHandler<CoreWindow*, WindowActivatedEventArgs*> ActivatedHandler; typedef ITypedEventHandler<CoreWindow*, CoreWindowEventArgs*> ClosedHandler; typedef ITypedEventHandler<CoreWindow*, CharacterReceivedEventArgs*> CharacterReceivedHandler; typedef ITypedEventHandler<CoreWindow*, InputEnabledEventArgs*> InputEnabledHandler; typedef ITypedEventHandler<CoreWindow*, KeyEventArgs*> KeyHandler; typedef ITypedEventHandler<CoreWindow*, PointerEventArgs*> PointerHandler; typedef ITypedEventHandler<CoreWindow*, WindowSizeChangedEventArgs*> SizeChangedHandler; typedef ITypedEventHandler<CoreWindow*, VisibilityChangedEventArgs*> VisibilityChangedHandler; typedef ITypedEventHandler<DisplayInformation*, IInspectable*> DisplayInformationHandler; #ifdef Q_OS_WINPHONE typedef ITypedEventHandler<StatusBar*, IInspectable*> StatusBarHandler; #endif QT_BEGIN_NAMESPACE struct KeyInfo { KeyInfo() : virtualKey(0) { } KeyInfo(const QString &text, quint32 virtualKey) : text(text) , virtualKey(virtualKey) { } KeyInfo(quint32 virtualKey) : virtualKey(virtualKey) { } QString text; quint32 virtualKey; }; static inline Qt::ScreenOrientations qtOrientationsFromNative(DisplayOrientations native) { Qt::ScreenOrientations orientations = Qt::PrimaryOrientation; if (native & DisplayOrientations_Portrait) orientations |= Qt::PortraitOrientation; if (native & DisplayOrientations_PortraitFlipped) orientations |= Qt::InvertedPortraitOrientation; if (native & DisplayOrientations_Landscape) orientations |= Qt::LandscapeOrientation; if (native & DisplayOrientations_LandscapeFlipped) orientations |= Qt::InvertedLandscapeOrientation; return orientations; } static inline DisplayOrientations nativeOrientationsFromQt(Qt::ScreenOrientations orientation) { DisplayOrientations native = DisplayOrientations_None; if (orientation & Qt::PortraitOrientation) native |= DisplayOrientations_Portrait; if (orientation & Qt::InvertedPortraitOrientation) native |= DisplayOrientations_PortraitFlipped; if (orientation & Qt::LandscapeOrientation) native |= DisplayOrientations_Landscape; if (orientation & Qt::InvertedLandscapeOrientation) native |= DisplayOrientations_LandscapeFlipped; return native; }
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
static inline bool qIsNonPrintable(quint32 keyCode) { switch (keyCode) { case '\b': case '\n': case '\t': case '\r': case '\v': case '\f': return true; default: return false; } } // Return Qt meta key from VirtualKey static inline Qt::Key qKeyFromVirtual(VirtualKey key) { switch (key) { default: return Qt::Key_unknown; // Non-printable characters case VirtualKey_Enter: return Qt::Key_Enter; case VirtualKey_Tab: return Qt::Key_Tab; case VirtualKey_Back: return Qt::Key_Backspace; // Modifiers case VirtualKey_Shift: case VirtualKey_LeftShift: case VirtualKey_RightShift: return Qt::Key_Shift; case VirtualKey_Control: case VirtualKey_LeftControl: case VirtualKey_RightControl: return Qt::Key_Control; case VirtualKey_Menu: case VirtualKey_LeftMenu: case VirtualKey_RightMenu: return Qt::Key_Alt; case VirtualKey_LeftWindows: case VirtualKey_RightWindows: return Qt::Key_Meta; // Toggle keys case VirtualKey_CapitalLock: return Qt::Key_CapsLock; case VirtualKey_NumberKeyLock: return Qt::Key_NumLock; case VirtualKey_Scroll: return Qt::Key_ScrollLock; // East-Asian language keys case VirtualKey_Kana: //case VirtualKey_Hangul: // Same enum as Kana return Qt::Key_Kana_Shift; case VirtualKey_Junja: return Qt::Key_Hangul_Jeonja; case VirtualKey_Kanji: //case VirtualKey_Hanja: // Same enum as Kanji return Qt::Key_Kanji; case VirtualKey_ModeChange: return Qt::Key_Mode_switch; case VirtualKey_Convert: return Qt::Key_Henkan; case VirtualKey_NonConvert:
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
return Qt::Key_Muhenkan; // Misc. keys case VirtualKey_Cancel: return Qt::Key_Cancel; case VirtualKey_Clear: return Qt::Key_Clear; case VirtualKey_Application: return Qt::Key_ApplicationLeft; case VirtualKey_Sleep: return Qt::Key_Sleep; case VirtualKey_Pause: return Qt::Key_Pause; case VirtualKey_PageUp: return Qt::Key_PageUp; case VirtualKey_PageDown: return Qt::Key_PageDown; case VirtualKey_End: return Qt::Key_End; case VirtualKey_Home: return Qt::Key_Home; case VirtualKey_Left: return Qt::Key_Left; case VirtualKey_Up: return Qt::Key_Up; case VirtualKey_Right: return Qt::Key_Right; case VirtualKey_Down: return Qt::Key_Down; case VirtualKey_Select: return Qt::Key_Select; case VirtualKey_Print: return Qt::Key_Print; case VirtualKey_Execute: return Qt::Key_Execute; case VirtualKey_Insert: return Qt::Key_Insert; case VirtualKey_Delete: return Qt::Key_Delete; case VirtualKey_Help: return Qt::Key_Help; case VirtualKey_Snapshot: return Qt::Key_Camera; case VirtualKey_Escape: return Qt::Key_Escape; // Function Keys case VirtualKey_F1: return Qt::Key_F1; case VirtualKey_F2: return Qt::Key_F2; case VirtualKey_F3: return Qt::Key_F3; case VirtualKey_F4: return Qt::Key_F4; case VirtualKey_F5: return Qt::Key_F5; case VirtualKey_F6: return Qt::Key_F6; case VirtualKey_F7: return Qt::Key_F7; case VirtualKey_F8: return Qt::Key_F8; case VirtualKey_F9: return Qt::Key_F9; case VirtualKey_F10: return Qt::Key_F10; case VirtualKey_F11: return Qt::Key_F11; case VirtualKey_F12:
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
return Qt::Key_F12; case VirtualKey_F13: return Qt::Key_F13; case VirtualKey_F14: return Qt::Key_F14; case VirtualKey_F15: return Qt::Key_F15; case VirtualKey_F16: return Qt::Key_F16; case VirtualKey_F17: return Qt::Key_F17; case VirtualKey_F18: return Qt::Key_F18; case VirtualKey_F19: return Qt::Key_F19; case VirtualKey_F20: return Qt::Key_F20; case VirtualKey_F21: return Qt::Key_F21; case VirtualKey_F22: return Qt::Key_F22; case VirtualKey_F23: return Qt::Key_F23; case VirtualKey_F24: return Qt::Key_F24; // Character keys case VirtualKey_Space: return Qt::Key_Space; case VirtualKey_Number0: case VirtualKey_NumberPad0: return Qt::Key_0; case VirtualKey_Number1: case VirtualKey_NumberPad1: return Qt::Key_1; case VirtualKey_Number2: case VirtualKey_NumberPad2: return Qt::Key_2; case VirtualKey_Number3: case VirtualKey_NumberPad3: return Qt::Key_3; case VirtualKey_Number4: case VirtualKey_NumberPad4: return Qt::Key_4; case VirtualKey_Number5: case VirtualKey_NumberPad5: return Qt::Key_5; case VirtualKey_Number6: case VirtualKey_NumberPad6: return Qt::Key_6; case VirtualKey_Number7: case VirtualKey_NumberPad7: return Qt::Key_7; case VirtualKey_Number8: case VirtualKey_NumberPad8: return Qt::Key_8; case VirtualKey_Number9: case VirtualKey_NumberPad9: return Qt::Key_9; case VirtualKey_A: return Qt::Key_A; case VirtualKey_B: return Qt::Key_B; case VirtualKey_C: return Qt::Key_C; case VirtualKey_D: return Qt::Key_D; case VirtualKey_E: return Qt::Key_E; case VirtualKey_F:
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
return Qt::Key_F; case VirtualKey_G: return Qt::Key_G; case VirtualKey_H: return Qt::Key_H; case VirtualKey_I: return Qt::Key_I; case VirtualKey_J: return Qt::Key_J; case VirtualKey_K: return Qt::Key_K; case VirtualKey_L: return Qt::Key_L; case VirtualKey_M: return Qt::Key_M; case VirtualKey_N: return Qt::Key_N; case VirtualKey_O: return Qt::Key_O; case VirtualKey_P: return Qt::Key_P; case VirtualKey_Q: return Qt::Key_Q; case VirtualKey_R: return Qt::Key_R; case VirtualKey_S: return Qt::Key_S; case VirtualKey_T: return Qt::Key_T; case VirtualKey_U: return Qt::Key_U; case VirtualKey_V: return Qt::Key_V; case VirtualKey_W: return Qt::Key_W; case VirtualKey_X: return Qt::Key_X; case VirtualKey_Y: return Qt::Key_Y; case VirtualKey_Z: return Qt::Key_Z; case VirtualKey_Multiply: return Qt::Key_9; case VirtualKey_Add: return Qt::Key_9; case VirtualKey_Separator: return Qt::Key_9; case VirtualKey_Subtract: return Qt::Key_9; case VirtualKey_Decimal: return Qt::Key_9; case VirtualKey_Divide: return Qt::Key_9; /* Keys with no matching Qt enum (?) case VirtualKey_None: case VirtualKey_LeftButton: case VirtualKey_RightButton: case VirtualKey_MiddleButton: case VirtualKey_XButton1: case VirtualKey_XButton2: case VirtualKey_Final: case VirtualKey_Accept:*/ } } static inline Qt::Key qKeyFromCode(quint32 code, int mods) { if (code >= 'a' && code <= 'z') code = toupper(code);
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
if ((mods & Qt::ControlModifier) != 0) { if (code >= 0 && code <= 31) // Ctrl+@..Ctrl+A..CTRL+Z..Ctrl+_ code += '@'; // to @..A..Z.._ } return static_cast<Qt::Key>(code & 0xff); } typedef HRESULT (__stdcall ICoreWindow::*CoreWindowCallbackRemover)(EventRegistrationToken); uint qHash(CoreWindowCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } typedef HRESULT (__stdcall IDisplayInformation::*DisplayCallbackRemover)(EventRegistrationToken); uint qHash(DisplayCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } #ifdef Q_OS_WINPHONE typedef HRESULT (__stdcall IStatusBar::*StatusBarCallbackRemover)(EventRegistrationToken); uint qHash(StatusBarCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } #endif class QWinRTScreenPrivate { public: QTouchDevice *touchDevice; ComPtr<ICoreWindow> coreWindow; ComPtr<Xaml::IDependencyObject> canvas; ComPtr<IApplicationView> view; ComPtr<IDisplayInformation> displayInformation; #ifdef Q_OS_WINPHONE ComPtr<IStatusBar> statusBar; #endif QScopedPointer<QWinRTCursor> cursor; QHash<quint32, QWindowSystemInterface::TouchPoint> touchPoints; QSizeF logicalSize; QSurfaceFormat surfaceFormat; qreal logicalDpi; QDpi physicalDpi; qreal scaleFactor; Qt::ScreenOrientation nativeOrientation; Qt::ScreenOrientation orientation; QList<QWindow *> visibleWindows; QHash<Qt::Key, KeyInfo> activeKeys; QHash<CoreWindowCallbackRemover, EventRegistrationToken> windowTokens; QHash<DisplayCallbackRemover, EventRegistrationToken> displayTokens; #ifdef Q_OS_WINPHONE QHash<StatusBarCallbackRemover, EventRegistrationToken> statusBarTokens; #endif }; // To be called from the XAML thread QWinRTScreen::QWinRTScreen() : d_ptr(new QWinRTScreenPrivate) { Q_D(QWinRTScreen); d->orientation = Qt::PrimaryOrientation; d->touchDevice = Q_NULLPTR; HRESULT hr; ComPtr<Xaml::IWindowStatics> windowStatics; hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Window).Get(), IID_PPV_ARGS(&windowStatics)); Q_ASSERT_SUCCEEDED(hr); ComPtr<Xaml::IWindow> window; hr = windowStatics->get_Current(&window); Q_ASSERT_SUCCEEDED(hr); hr = window->Activate(); Q_ASSERT_SUCCEEDED(hr); hr = window->get_CoreWindow(&d->coreWindow); Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->Activate(); Q_ASSERT_SUCCEEDED(hr);
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
Rect rect; hr = d->coreWindow->get_Bounds(&rect); Q_ASSERT_SUCCEEDED(hr); d->logicalSize = QSizeF(rect.Width, rect.Height); // Orientation handling ComPtr<IDisplayInformationStatics> displayInformationStatics; hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), IID_PPV_ARGS(&displayInformationStatics)); Q_ASSERT_SUCCEEDED(hr); hr = displayInformationStatics->GetForCurrentView(&d->displayInformation); Q_ASSERT_SUCCEEDED(hr); // Set native orientation DisplayOrientations displayOrientation; hr = d->displayInformation->get_NativeOrientation(&displayOrientation); Q_ASSERT_SUCCEEDED(hr); d->nativeOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation))); // Set initial pixel density onDpiChanged(Q_NULLPTR, Q_NULLPTR); d->orientation = d->nativeOrientation; ComPtr<IApplicationViewStatics2> applicationViewStatics; hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(), IID_PPV_ARGS(&applicationViewStatics)); RETURN_VOID_IF_FAILED("Could not get ApplicationViewStatics"); hr = applicationViewStatics->GetForCurrentView(&d->view); RETURN_VOID_IF_FAILED("Could not access currentView"); // Create a canvas and set it as the window content. Eventually, this should have its own method so multiple "screens" can be added ComPtr<Xaml::Controls::ICanvas> canvas; hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(), &canvas); Q_ASSERT_SUCCEEDED(hr); ComPtr<Xaml::IFrameworkElement> frameworkElement; hr = canvas.As(&frameworkElement); Q_ASSERT_SUCCEEDED(hr); hr = frameworkElement->put_Width(d->logicalSize.width()); Q_ASSERT_SUCCEEDED(hr); hr = frameworkElement->put_Height(d->logicalSize.height()); Q_ASSERT_SUCCEEDED(hr); ComPtr<Xaml::IUIElement> uiElement; hr = canvas.As(&uiElement); Q_ASSERT_SUCCEEDED(hr); hr = window->put_Content(uiElement.Get()); Q_ASSERT_SUCCEEDED(hr); hr = canvas.As(&d->canvas); Q_ASSERT_SUCCEEDED(hr); d->cursor.reset(new QWinRTCursor); #ifdef Q_OS_WINPHONE ComPtr<IStatusBarStatics> statusBarStatics; hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_StatusBar).Get(), IID_PPV_ARGS(&statusBarStatics)); Q_ASSERT_SUCCEEDED(hr); hr = statusBarStatics->GetForCurrentView(&d->statusBar); Q_ASSERT_SUCCEEDED(hr); #endif // Q_OS_WINPHONE } QWinRTScreen::~QWinRTScreen() { Q_D(QWinRTScreen); // Unregister callbacks HRESULT hr; hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() { HRESULT hr;
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
for (QHash<CoreWindowCallbackRemover, EventRegistrationToken>::const_iterator i = d->windowTokens.begin(); i != d->windowTokens.end(); ++i) { hr = (d->coreWindow.Get()->*i.key())(i.value()); Q_ASSERT_SUCCEEDED(hr); } for (QHash<DisplayCallbackRemover, EventRegistrationToken>::const_iterator i = d->displayTokens.begin(); i != d->displayTokens.end(); ++i) { hr = (d->displayInformation.Get()->*i.key())(i.value()); Q_ASSERT_SUCCEEDED(hr); } #ifdef Q_OS_WINPHONE for (QHash<StatusBarCallbackRemover, EventRegistrationToken>::const_iterator i = d->statusBarTokens.begin(); i != d->statusBarTokens.end(); ++i) { hr = (d->statusBar.Get()->*i.key())(i.value()); Q_ASSERT_SUCCEEDED(hr); } #endif //Q_OS_WINPHONE return hr; }); RETURN_VOID_IF_FAILED("Failed to unregister screen event callbacks"); } QRect QWinRTScreen::geometry() const { Q_D(const QWinRTScreen); return QRect(QPoint(), (d->logicalSize * d->scaleFactor).toSize()); } #ifdef Q_OS_WINPHONE QRect QWinRTScreen::availableGeometry() const { Q_D(const QWinRTScreen); QRect statusBar; QEventDispatcherWinRT::runOnXamlThread([d, &statusBar]() { HRESULT hr; Rect rect; hr = d->statusBar->get_OccludedRect(&rect); Q_ASSERT_SUCCEEDED(hr); statusBar.setRect(qRound(rect.X * d->scaleFactor), qRound(rect.Y * d->scaleFactor), qRound(rect.Width * d->scaleFactor), qRound(rect.Height * d->scaleFactor)); return S_OK; }); return geometry().adjusted( d->orientation == Qt::LandscapeOrientation ? statusBar.width() : 0, d->orientation == Qt::PortraitOrientation ? statusBar.height() : 0, d->orientation == Qt::InvertedLandscapeOrientation ? -statusBar.width() : 0, 0); } #endif //Q_OS_WINPHONE int QWinRTScreen::depth() const { return 32; } QImage::Format QWinRTScreen::format() const { return QImage::Format_ARGB32_Premultiplied; } QSizeF QWinRTScreen::physicalSize() const { Q_D(const QWinRTScreen); return QSizeF(d->logicalSize.width() * d->scaleFactor / d->physicalDpi.first * qreal(25.4), d->logicalSize.height() * d->scaleFactor / d->physicalDpi.second * qreal(25.4)); } QDpi QWinRTScreen::logicalDpi() const { Q_D(const QWinRTScreen);
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
return QDpi(d->logicalDpi, d->logicalDpi); } qreal QWinRTScreen::scaleFactor() const { Q_D(const QWinRTScreen); return d->scaleFactor; } QPlatformCursor *QWinRTScreen::cursor() const { Q_D(const QWinRTScreen); return d->cursor.data(); } Qt::KeyboardModifiers QWinRTScreen::keyboardModifiers() const { Q_D(const QWinRTScreen); Qt::KeyboardModifiers mods; CoreVirtualKeyStates mod; d->coreWindow->GetAsyncKeyState(VirtualKey_Shift, &mod); if (mod == CoreVirtualKeyStates_Down) mods |= Qt::ShiftModifier; d->coreWindow->GetAsyncKeyState(VirtualKey_Menu, &mod); if (mod == CoreVirtualKeyStates_Down) mods |= Qt::AltModifier; d->coreWindow->GetAsyncKeyState(VirtualKey_Control, &mod); if (mod == CoreVirtualKeyStates_Down) mods |= Qt::ControlModifier; d->coreWindow->GetAsyncKeyState(VirtualKey_LeftWindows, &mod); if (mod == CoreVirtualKeyStates_Down) { mods |= Qt::MetaModifier; } else { d->coreWindow->GetAsyncKeyState(VirtualKey_RightWindows, &mod); if (mod == CoreVirtualKeyStates_Down) mods |= Qt::MetaModifier; } return mods; } Qt::ScreenOrientation QWinRTScreen::nativeOrientation() const { Q_D(const QWinRTScreen); return d->nativeOrientation; } Qt::ScreenOrientation QWinRTScreen::orientation() const { Q_D(const QWinRTScreen); return d->orientation; } ICoreWindow *QWinRTScreen::coreWindow() const { Q_D(const QWinRTScreen); return d->coreWindow.Get(); } Xaml::IDependencyObject *QWinRTScreen::canvas() const { Q_D(const QWinRTScreen); return d->canvas.Get(); } #ifdef Q_OS_WINPHONE void QWinRTScreen::setStatusBarVisibility(bool visible, QWindow *window) { Q_D(QWinRTScreen); const Qt::WindowFlags windowType = window->flags() & Qt::WindowType_Mask;
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
if (!window || (windowType != Qt::Window && windowType != Qt::Dialog)) return; QEventDispatcherWinRT::runOnXamlThread([d, visible]() { HRESULT hr; ComPtr<IAsyncAction> op; if (visible) hr = d->statusBar->ShowAsync(&op); else hr = d->statusBar->HideAsync(&op); Q_ASSERT_SUCCEEDED(hr); return S_OK; }); } #endif //Q_OS_WINPHONE void QWinRTScreen::initialize() { Q_D(QWinRTScreen); HRESULT hr; hr = d->coreWindow->add_KeyDown(Callback<KeyHandler>(this, &QWinRTScreen::onKeyDown).Get(), &d->windowTokens[&ICoreWindow::remove_KeyDown]); Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_KeyUp(Callback<KeyHandler>(this, &QWinRTScreen::onKeyUp).Get(), &d->windowTokens[&ICoreWindow::remove_KeyUp]); Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_CharacterReceived(Callback<CharacterReceivedHandler>(this, &QWinRTScreen::onCharacterReceived).Get(), &d->windowTokens[&ICoreWindow::remove_CharacterReceived]); Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_PointerEntered(Callback<PointerHandler>(this, &QWinRTScreen::onPointerEntered).Get(), &d->windowTokens[&ICoreWindow::remove_PointerEntered]); Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_PointerExited(Callback<PointerHandler>(this, &QWinRTScreen::onPointerExited).Get(), &d->windowTokens[&ICoreWindow::remove_PointerExited]); Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_PointerMoved(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerMoved]); Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_PointerPressed(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerPressed]); Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_PointerReleased(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerReleased]); Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_PointerWheelChanged(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerWheelChanged]); Q_ASSERT_SUCCEEDED(hr); #ifndef Q_OS_WINPHONE hr = d->coreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &QWinRTScreen::onSizeChanged).Get(), &d->windowTokens[&ICoreWindow::remove_SizeChanged]); Q_ASSERT_SUCCEEDED(hr); #else hr = d->statusBar->add_Showing(Callback<StatusBarHandler>(this, &QWinRTScreen::onStatusBarShowing).Get(), &d->statusBarTokens[&IStatusBar::remove_Showing]); Q_ASSERT_SUCCEEDED(hr); hr = d->statusBar->add_Hiding(Callback<StatusBarHandler>(this, &QWinRTScreen::onStatusBarHiding).Get(), &d->statusBarTokens[&IStatusBar::remove_Hiding]); Q_ASSERT_SUCCEEDED(hr); #endif hr = d->coreWindow->add_Activated(Callback<ActivatedHandler>(this, &QWinRTScreen::onActivated).Get(), &d->windowTokens[&ICoreWindow::remove_Activated]); Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_Closed(Callback<ClosedHandler>(this, &QWinRTScreen::onClosed).Get(), &d->windowTokens[&ICoreWindow::remove_Closed]); Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_VisibilityChanged(Callback<VisibilityChangedHandler>(this, &QWinRTScreen::onVisibilityChanged).Get(), &d->windowTokens[&ICoreWindow::remove_VisibilityChanged]); Q_ASSERT_SUCCEEDED(hr); hr = d->displayInformation->add_OrientationChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onOrientationChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_OrientationChanged]); Q_ASSERT_SUCCEEDED(hr); hr = d->displayInformation->add_DpiChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onDpiChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_DpiChanged]); Q_ASSERT_SUCCEEDED(hr); onOrientationChanged(Q_NULLPTR, Q_NULLPTR); onVisibilityChanged(nullptr, nullptr); } QWindow *QWinRTScreen::topWindow() const { Q_D(const QWinRTScreen); return d->visibleWindows.isEmpty() ? 0 : d->visibleWindows.first(); } void QWinRTScreen::addWindow(QWindow *window) { Q_D(QWinRTScreen);
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
if (window == topWindow()) return; #ifdef Q_OS_WINPHONE if (window->visibility() != QWindow::Maximized && window->visibility() != QWindow::Windowed) setStatusBarVisibility(false, window); #endif d->visibleWindows.prepend(window); QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); handleExpose(); QWindowSystemInterface::flushWindowSystemEvents(); } void QWinRTScreen::removeWindow(QWindow *window) { Q_D(QWinRTScreen); #ifdef Q_OS_WINPHONE if (window->visibility() == QWindow::Minimized) setStatusBarVisibility(false, window); #endif const bool wasTopWindow = window == topWindow(); if (!d->visibleWindows.removeAll(window)) return; if (wasTopWindow) QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); handleExpose(); QWindowSystemInterface::flushWindowSystemEvents(); } void QWinRTScreen::raise(QWindow *window) { Q_D(QWinRTScreen); d->visibleWindows.removeAll(window); addWindow(window); } void QWinRTScreen::lower(QWindow *window) { Q_D(QWinRTScreen); const bool wasTopWindow = window == topWindow(); if (wasTopWindow && d->visibleWindows.size() == 1) return; d->visibleWindows.removeAll(window); d->visibleWindows.append(window); if (wasTopWindow) QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); handleExpose(); } void QWinRTScreen::updateWindowTitle() { Q_D(QWinRTScreen); QWindow *window = topWindow(); if (!window) return; const QString title = window->title(); HStringReference titleRef(reinterpret_cast<LPCWSTR>(title.utf16()), title.length()); HRESULT hr = d->view->put_Title(titleRef.Get()); RETURN_VOID_IF_FAILED("Unable to set window title"); } void QWinRTScreen::handleExpose() { Q_D(QWinRTScreen); if (d->visibleWindows.isEmpty())
841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
return; QList<QWindow *>::const_iterator it = d->visibleWindows.constBegin(); QWindowSystemInterface::handleExposeEvent(*it, geometry()); while (++it != d->visibleWindows.constEnd()) QWindowSystemInterface::handleExposeEvent(*it, QRegion()); } HRESULT QWinRTScreen::onKeyDown(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *args) { Q_D(QWinRTScreen); VirtualKey virtualKey; HRESULT hr = args->get_VirtualKey(&virtualKey); Q_ASSERT_SUCCEEDED(hr); CorePhysicalKeyStatus status; hr = args->get_KeyStatus(&status); Q_ASSERT_SUCCEEDED(hr); Qt::Key key = qKeyFromVirtual(virtualKey); // Defer character key presses to onCharacterReceived if (key == Qt::Key_unknown || (key >= Qt::Key_Space && key <= Qt::Key_ydiaeresis)) { d->activeKeys.insert(key, KeyInfo(virtualKey)); return S_OK; } QWindowSystemInterface::handleExtendedKeyEvent( topWindow(), QEvent::KeyPress, key, keyboardModifiers(), !status.ScanCode ? -1 : status.ScanCode, virtualKey, 0, QString(), status.RepeatCount > 1, !status.RepeatCount ? 1 : status.RepeatCount, false); return S_OK; } HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *args) { Q_D(QWinRTScreen); VirtualKey virtualKey; HRESULT hr = args->get_VirtualKey(&virtualKey); Q_ASSERT_SUCCEEDED(hr); CorePhysicalKeyStatus status; hr = args->get_KeyStatus(&status); Q_ASSERT_SUCCEEDED(hr); Qt::Key key = qKeyFromVirtual(virtualKey); const KeyInfo info = d->activeKeys.take(key); QWindowSystemInterface::handleExtendedKeyEvent( topWindow(), QEvent::KeyRelease, key, keyboardModifiers(), !status.ScanCode ? -1 : status.ScanCode, virtualKey, 0, info.text, status.RepeatCount > 1, !status.RepeatCount ? 1 : status.RepeatCount, false); return S_OK; } HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *, ICharacterReceivedEventArgs *args) { Q_D(QWinRTScreen); quint32 keyCode;
911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
HRESULT hr = args->get_KeyCode(&keyCode); Q_ASSERT_SUCCEEDED(hr); CorePhysicalKeyStatus status; hr = args->get_KeyStatus(&status); Q_ASSERT_SUCCEEDED(hr); // Don't generate character events for non-printables; the meta key stage is enough if (qIsNonPrintable(keyCode)) return S_OK; const Qt::KeyboardModifiers modifiers = keyboardModifiers(); const Qt::Key key = qKeyFromCode(keyCode, modifiers); const QString text = QChar(keyCode); const quint32 virtualKey = d->activeKeys.value(key).virtualKey; QWindowSystemInterface::handleExtendedKeyEvent( topWindow(), QEvent::KeyPress, key, modifiers, !status.ScanCode ? -1 : status.ScanCode, virtualKey, 0, text, status.RepeatCount > 1, !status.RepeatCount ? 1 : status.RepeatCount, false); d->activeKeys.insert(key, KeyInfo(text, virtualKey)); return S_OK; } HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args) { Q_D(QWinRTScreen); ComPtr<IPointerPoint> pointerPoint; if (SUCCEEDED(args->get_CurrentPoint(&pointerPoint))) { // Assumes full-screen window Point point; pointerPoint->get_Position(&point); QPoint pos(point.X * d->scaleFactor, point.Y * d->scaleFactor); QWindowSystemInterface::handleEnterEvent(topWindow(), pos, pos); } return S_OK; } HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *) { QWindowSystemInterface::handleLeaveEvent(0); return S_OK; } HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args) { Q_D(QWinRTScreen); ComPtr<IPointerPoint> pointerPoint; if (FAILED(args->get_CurrentPoint(&pointerPoint))) return E_INVALIDARG; // Common traits - point, modifiers, properties Point point; pointerPoint->get_Position(&point); QPointF pos(point.X * d->scaleFactor, point.Y * d->scaleFactor); QPointF localPos = pos; if (topWindow()) { const QPointF globalPosDelta = pos - pos.toPoint(); localPos = topWindow()->mapFromGlobal(pos.toPoint()) + globalPosDelta; } VirtualKeyModifiers modifiers;
981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
args->get_KeyModifiers(&modifiers); Qt::KeyboardModifiers mods; if (modifiers & VirtualKeyModifiers_Control) mods |= Qt::ControlModifier; if (modifiers & VirtualKeyModifiers_Menu) mods |= Qt::AltModifier; if (modifiers & VirtualKeyModifiers_Shift) mods |= Qt::ShiftModifier; if (modifiers & VirtualKeyModifiers_Windows) mods |= Qt::MetaModifier; ComPtr<IPointerPointProperties> properties; if (FAILED(pointerPoint->get_Properties(&properties))) return E_INVALIDARG; ComPtr<IPointerDevice> pointerDevice; HRESULT hr = pointerPoint->get_PointerDevice(&pointerDevice); RETURN_OK_IF_FAILED("Failed to get pointer device."); PointerDeviceType pointerDeviceType; hr = pointerDevice->get_PointerDeviceType(&pointerDeviceType); RETURN_OK_IF_FAILED("Failed to get pointer device type."); switch (pointerDeviceType) { case PointerDeviceType_Mouse: { qint32 delta; properties->get_MouseWheelDelta(&delta); if (delta) { boolean isHorizontal; properties->get_IsHorizontalMouseWheel(&isHorizontal); QPoint angleDelta(isHorizontal ? delta : 0, isHorizontal ? 0 : delta); QWindowSystemInterface::handleWheelEvent(topWindow(), localPos, pos, QPoint(), angleDelta, mods); break; } boolean isPressed; Qt::MouseButtons buttons = Qt::NoButton; properties->get_IsLeftButtonPressed(&isPressed); if (isPressed) buttons |= Qt::LeftButton; properties->get_IsMiddleButtonPressed(&isPressed); if (isPressed) buttons |= Qt::MiddleButton; properties->get_IsRightButtonPressed(&isPressed); if (isPressed) buttons |= Qt::RightButton; properties->get_IsXButton1Pressed(&isPressed); if (isPressed) buttons |= Qt::XButton1; properties->get_IsXButton2Pressed(&isPressed); if (isPressed) buttons |= Qt::XButton2; QWindowSystemInterface::handleMouseEvent(topWindow(), localPos, pos, buttons, mods); break; } case PointerDeviceType_Touch: { if (!d->touchDevice) { d->touchDevice = new QTouchDevice; d->touchDevice->setName(QStringLiteral("WinRTTouchScreen")); d->touchDevice->setType(QTouchDevice::TouchScreen); d->touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure | QTouchDevice::NormalizedPosition); QWindowSystemInterface::registerTouchDevice(d->touchDevice); }
1051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
quint32 id; pointerPoint->get_PointerId(&id); Rect area; properties->get_ContactRect(&area); float pressure; properties->get_Pressure(&pressure); QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator it = d->touchPoints.find(id); if (it != d->touchPoints.end()) { boolean isPressed; #ifndef Q_OS_WINPHONE pointerPoint->get_IsInContact(&isPressed); #else properties->get_IsLeftButtonPressed(&isPressed); // IsInContact not reliable on phone #endif it.value().state = isPressed ? Qt::TouchPointMoved : Qt::TouchPointReleased; } else { it = d->touchPoints.insert(id, QWindowSystemInterface::TouchPoint()); it.value().state = Qt::TouchPointPressed; it.value().id = id; } it.value().area = QRectF(area.X * d->scaleFactor, area.Y * d->scaleFactor, area.Width * d->scaleFactor, area.Height * d->scaleFactor); it.value().normalPosition = QPointF(point.X/d->logicalSize.width(), point.Y/d->logicalSize.height()); it.value().pressure = pressure; QWindowSystemInterface::handleTouchEvent(topWindow(), d->touchDevice, d->touchPoints.values(), mods); // Remove released points, station others for (QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator i = d->touchPoints.begin(); i != d->touchPoints.end();) { if (i.value().state == Qt::TouchPointReleased) i = d->touchPoints.erase(i); else (i++).value().state = Qt::TouchPointStationary; } break; } case PointerDeviceType_Pen: { quint32 id; pointerPoint->get_PointerId(&id); boolean isPressed; pointerPoint->get_IsInContact(&isPressed); boolean isEraser; properties->get_IsEraser(&isEraser); int pointerType = isEraser ? 3 : 1; float pressure; properties->get_Pressure(&pressure); float xTilt; properties->get_XTilt(&xTilt); float yTilt; properties->get_YTilt(&yTilt); float rotation; properties->get_Twist(&rotation); QWindowSystemInterface::handleTabletEvent(topWindow(), isPressed, pos, pos, 0, pointerType, pressure, xTilt, yTilt, 0, rotation, 0, id, mods); break; } }
1121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
return S_OK; } HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *) { Q_D(QWinRTScreen); Rect size; HRESULT hr; hr = d->coreWindow->get_Bounds(&size); RETURN_OK_IF_FAILED("Failed to get window bounds"); d->logicalSize = QSizeF(size.Width, size.Height); QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry()); QPlatformScreen::resizeMaximizedWindows(); handleExpose(); return S_OK; } HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args) { Q_D(QWinRTScreen); CoreWindowActivationState activationState; args->get_WindowActivationState(&activationState); if (activationState == CoreWindowActivationState_Deactivated) { QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive); return S_OK; } // Activate topWindow if (!d->visibleWindows.isEmpty()) { Qt::FocusReason focusReason = activationState == CoreWindowActivationState_PointerActivated ? Qt::MouseFocusReason : Qt::ActiveWindowFocusReason; QWindowSystemInterface::handleWindowActivated(topWindow(), focusReason); } return S_OK; } HRESULT QWinRTScreen::onClosed(ICoreWindow *, ICoreWindowEventArgs *) { foreach (QWindow *w, QGuiApplication::topLevelWindows()) QWindowSystemInterface::handleCloseEvent(w); return S_OK; } HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *, IVisibilityChangedEventArgs *args) { Q_D(QWinRTScreen); boolean visible; HRESULT hr = args ? args->get_Visible(&visible) : d->coreWindow->get_Visible(&visible); RETURN_OK_IF_FAILED("Failed to get visbile."); QWindowSystemInterface::handleApplicationStateChanged(visible ? Qt::ApplicationActive : Qt::ApplicationHidden); if (visible) handleExpose(); return S_OK; } HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable *) { Q_D(QWinRTScreen); DisplayOrientations displayOrientation; HRESULT hr = d->displayInformation->get_CurrentOrientation(&displayOrientation); RETURN_OK_IF_FAILED("Failed to get current orientations."); Qt::ScreenOrientation newOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation))); if (d->orientation != newOrientation) { d->orientation = newOrientation; #ifdef Q_OS_WINPHONE
119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247
onSizeChanged(nullptr, nullptr); #endif QWindowSystemInterface::handleScreenOrientationChange(screen(), d->orientation); handleExpose(); // Clean broken frames caused by race between Qt and ANGLE } return S_OK; } HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *) { Q_D(QWinRTScreen); HRESULT hr; #ifdef Q_OS_WINPHONE ComPtr<IDisplayInformation2> displayInformation; hr = d->displayInformation.As(&displayInformation); RETURN_OK_IF_FAILED("Failed to cast display information."); hr = displayInformation->get_RawPixelsPerViewPixel(&d->scaleFactor); #else ResolutionScale resolutionScale; hr = d->displayInformation->get_ResolutionScale(&resolutionScale); d->scaleFactor = qreal(resolutionScale) / 100; #endif RETURN_OK_IF_FAILED("Failed to get scale factor"); FLOAT dpi; hr = d->displayInformation->get_LogicalDpi(&dpi); RETURN_OK_IF_FAILED("Failed to get logical DPI."); d->logicalDpi = dpi; hr = d->displayInformation->get_RawDpiX(&dpi); RETURN_OK_IF_FAILED("Failed to get x raw DPI."); d->physicalDpi.first = dpi ? dpi : 96.0; hr = d->displayInformation->get_RawDpiY(&dpi); RETURN_OK_IF_FAILED("Failed to get y raw DPI."); d->physicalDpi.second = dpi ? dpi : 96.0; return S_OK; } #ifdef Q_OS_WINPHONE HRESULT QWinRTScreen::onStatusBarShowing(IStatusBar *, IInspectable *) { onSizeChanged(nullptr, nullptr); return S_OK; } HRESULT QWinRTScreen::onStatusBarHiding(IStatusBar *, IInspectable *) { onSizeChanged(nullptr, nullptr); return S_OK; } #endif //Q_OS_WINPHONE QT_END_NAMESPACE