diff options
Diffstat (limited to 'src/plugins/platforms/winrt/qwinrtscreen.cpp')
-rw-r--r-- | src/plugins/platforms/winrt/qwinrtscreen.cpp | 1543 |
1 files changed, 0 insertions, 1543 deletions
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp deleted file mode 100644 index 5db1459213..0000000000 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ /dev/null @@ -1,1543 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 https://www.qt.io/terms-conditions. For further -** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwinrtscreen.h" - -#include "qwinrtbackingstore.h" -#include "qwinrtinputcontext.h" -#include "qwinrtcursor.h" -#if QT_CONFIG(draganddrop) -#include "qwinrtdrag.h" -#endif -#include "qwinrtwindow.h" -#include "qwinrtcanvas.h" -#include <private/qeventdispatcher_winrt_p.h> -#include <private/qhighdpiscaling_p.h> - -#include <QtCore/qdebug.h> -#include <QtCore/QLoggingCategory> -#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; -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*, VisibilityChangedEventArgs*> VisibilityChangedHandler; -typedef ITypedEventHandler<DisplayInformation*, IInspectable*> DisplayInformationHandler; -typedef ITypedEventHandler<ICorePointerRedirector*, PointerEventArgs*> RedirectHandler; -typedef ITypedEventHandler<ApplicationView*, IInspectable*> VisibleBoundsChangedHandler; - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events") - -#if !defined(QT_NO_DEBUG_STREAM) -QDebug operator<<(QDebug dbg, QWinRTScreen::MousePositionTransition transition) -{ - QDebugStateSaver saver(dbg); - dbg.nospace() << "QWinRTScreen::MousePositionTransition::"; - switch (transition) { - case QWinRTScreen::MousePositionTransition::MovedOut: - dbg << "MovedOut"; - break; - case QWinRTScreen::MousePositionTransition::MovedIn: - dbg << "MovedIn"; - break; - case QWinRTScreen::MousePositionTransition::StayedOut: - dbg << "StayedOut"; - break; - case QWinRTScreen::MousePositionTransition::StayedIn: - dbg << "StayedIn"; - break; - } - return dbg; -} -#endif - -struct KeyInfo { - KeyInfo() - { - } - - KeyInfo(quint32 virtualKey) - : virtualKey(virtualKey) - { - } - - QString text; - quint32 virtualKey{0}; - bool isAutoRepeat{false}; -}; - -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; -} - -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: - 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: - 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: - 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:*/ - } -} - -// Some keys like modifiers, caps lock etc. should not be automatically repeated if the key is held down -static inline bool shouldAutoRepeat(Qt::Key key) -{ - switch (key) { - case Qt::Key_Shift: - case Qt::Key_Control: - case Qt::Key_Alt: - case Qt::Key_Meta: - case Qt::Key_CapsLock: - case Qt::Key_NumLock: - case Qt::Key_ScrollLock: - return false; - default: - return true; - } -} - -static inline Qt::Key qKeyFromCode(quint32 code, int mods) -{ - if (code >= 'a' && code <= 'z') - code = toupper(code); - 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); -size_t qHash(CoreWindowCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } -typedef HRESULT (__stdcall IDisplayInformation::*DisplayCallbackRemover)(EventRegistrationToken); -size_t qHash(DisplayCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } -typedef HRESULT (__stdcall ICorePointerRedirector::*RedirectorCallbackRemover)(EventRegistrationToken); -size_t qHash(RedirectorCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } -typedef HRESULT (__stdcall IApplicationView2::*ApplicationView2CallbackRemover)(EventRegistrationToken); -size_t qHash(ApplicationView2CallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } - -class QWinRTScreenPrivate -{ -public: - QTouchDevice *touchDevice; - ComPtr<ICoreWindow> coreWindow; - ComPtr<ICorePointerRedirector> redirect; - ComPtr<QWinRTCanvas> canvas; - ComPtr<IApplicationView> view; - ComPtr<IDisplayInformation> displayInformation; - - QScopedPointer<QWinRTCursor> cursor; - QHash<quint32, QWindowSystemInterface::TouchPoint> touchPoints; - QRectF logicalRect; - QRectF visibleRect; - 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; - QHash<RedirectorCallbackRemover, EventRegistrationToken> redirectTokens; - QHash<ApplicationView2CallbackRemover, EventRegistrationToken> view2Tokens; - ComPtr<IApplicationView2> view2; - QAtomicPointer<QWinRTWindow> mouseGrabWindow; - QAtomicPointer<QWinRTWindow> keyboardGrabWindow; - QWindow *currentPressWindow = nullptr; - QWindow *currentTargetWindow = nullptr; - bool firstMouseMove = true; - bool resizePending = false; -}; - -// To be called from the XAML thread -QWinRTScreen::QWinRTScreen() - : d_ptr(new QWinRTScreenPrivate) -{ - Q_D(QWinRTScreen); - qCDebug(lcQpaWindows) << __FUNCTION__; - d->orientation = Qt::PrimaryOrientation; - d->touchDevice = 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.As(&d->redirect); - Q_ASSERT_SUCCEEDED(hr); - - hr = d->coreWindow->Activate(); - Q_ASSERT_SUCCEEDED(hr); - - Rect rect; - hr = d->coreWindow->get_Bounds(&rect); - Q_ASSERT_SUCCEEDED(hr); - d->logicalRect = QRectF(0.0f, 0.0f, rect.Width, rect.Height); - d->visibleRect = QRectF(0.0f, 0.0f, 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(nullptr, 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"); - - d->canvas = Make<QWinRTCanvas>([this]() { return topWindow(); }); - - ComPtr<Xaml::IFrameworkElement> frameworkElement; - hr = d->canvas.As(&frameworkElement); - Q_ASSERT_SUCCEEDED(hr); - hr = frameworkElement->put_Width(d->logicalRect.width()); - Q_ASSERT_SUCCEEDED(hr); - hr = frameworkElement->put_Height(d->logicalRect.height()); - Q_ASSERT_SUCCEEDED(hr); - - ComPtr<Xaml::IUIElement> uiElement; - hr = d->canvas.As(&uiElement); - Q_ASSERT_SUCCEEDED(hr); - -#if QT_CONFIG(draganddrop) - QWinRTDrag::instance()->setUiElement(uiElement); -#endif - hr = window->put_Content(uiElement.Get()); - Q_ASSERT_SUCCEEDED(hr); - - d->cursor.reset(new QWinRTCursor); - - hr = d->view.As(&d->view2); - Q_ASSERT_SUCCEEDED(hr); -} - -QWinRTScreen::~QWinRTScreen() -{ - Q_D(QWinRTScreen); - qCDebug(lcQpaWindows) << __FUNCTION__ << this; - - // Unregister callbacks - HRESULT hr; - hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() { - HRESULT hr; - 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); - } - for (QHash<RedirectorCallbackRemover, EventRegistrationToken>::const_iterator i = d->redirectTokens.begin(); i != d->redirectTokens.end(); ++i) { - hr = (d->redirect.Get()->*i.key())(i.value()); - Q_ASSERT_SUCCEEDED(hr); - } - for (QHash<ApplicationView2CallbackRemover, EventRegistrationToken>::const_iterator i = d->view2Tokens.begin(); i != d->view2Tokens.end(); ++i) { - hr = (d->view2.Get()->*i.key())(i.value()); - Q_ASSERT_SUCCEEDED(hr); - } - return hr; - }); - RETURN_VOID_IF_FAILED("Failed to unregister screen event callbacks"); -} - -QRect QWinRTScreen::geometry() const -{ - Q_D(const QWinRTScreen); - return QRect(QPoint(), QSizeF(d->logicalRect.size() * d->scaleFactor).toSize()); -} - -QRect QWinRTScreen::availableGeometry() const -{ - Q_D(const QWinRTScreen); - return QRectF((d->visibleRect.x() - d->logicalRect.x())* d->scaleFactor, - (d->visibleRect.y() - d->logicalRect.y()) * d->scaleFactor, - d->visibleRect.width() * d->scaleFactor, - d->visibleRect.height() * d->scaleFactor).toRect(); -} - -int QWinRTScreen::depth() const -{ - return 32; -} - -QImage::Format QWinRTScreen::format() const -{ - return QImage::Format_RGB32; -} - -QSizeF QWinRTScreen::physicalSize() const -{ - Q_D(const QWinRTScreen); - return QSizeF(d->logicalRect.width() * d->scaleFactor / d->physicalDpi.first * qreal(25.4), - d->logicalRect.height() * d->scaleFactor / d->physicalDpi.second * qreal(25.4)); -} - -QDpi QWinRTScreen::logicalDpi() const -{ - Q_D(const QWinRTScreen); - 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; - HRESULT hr = d->coreWindow->GetAsyncKeyState(VirtualKey_Shift, &mod); - Q_ASSERT_SUCCEEDED(hr); - if (mod & CoreVirtualKeyStates_Down) - mods |= Qt::ShiftModifier; - hr = d->coreWindow->GetAsyncKeyState(VirtualKey_Menu, &mod); - Q_ASSERT_SUCCEEDED(hr); - if (mod & CoreVirtualKeyStates_Down) - mods |= Qt::AltModifier; - hr = d->coreWindow->GetAsyncKeyState(VirtualKey_Control, &mod); - Q_ASSERT_SUCCEEDED(hr); - if (mod & CoreVirtualKeyStates_Down) - mods |= Qt::ControlModifier; - hr = d->coreWindow->GetAsyncKeyState(VirtualKey_LeftWindows, &mod); - Q_ASSERT_SUCCEEDED(hr); - if (mod & CoreVirtualKeyStates_Down) { - mods |= Qt::MetaModifier; - } else { - hr = d->coreWindow->GetAsyncKeyState(VirtualKey_RightWindows, &mod); - Q_ASSERT_SUCCEEDED(hr); - 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); - Xaml::IDependencyObject *depCanvas; - if (SUCCEEDED(d->canvas.CopyTo(&depCanvas))) - return depCanvas; - return nullptr; -} - -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); - hr = d->view2->add_VisibleBoundsChanged(Callback<VisibleBoundsChangedHandler>(this, &QWinRTScreen::onWindowSizeChanged).Get(), &d->view2Tokens[&IApplicationView2::remove_VisibleBoundsChanged]); - Q_ASSERT_SUCCEEDED(hr); - 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(nullptr, nullptr); - onVisibilityChanged(nullptr, nullptr); - - hr = d->redirect->add_PointerRoutedReleased(Callback<RedirectHandler>(this, &QWinRTScreen::onRedirectReleased).Get(), &d->redirectTokens[&ICorePointerRedirector::remove_PointerRoutedReleased]); - Q_ASSERT_SUCCEEDED(hr); -} - -void QWinRTScreen::setCursorRect(const QRectF &cursorRect) -{ - mCursorRect = cursorRect; -} - -void QWinRTScreen::setKeyboardRect(const QRectF &keyboardRect) -{ - Q_D(QWinRTScreen); - QRectF visibleRectF; - HRESULT hr; - Rect windowSize; - - hr = d->coreWindow->get_Bounds(&windowSize); - if (FAILED(hr)) { - qErrnoWarning(hr, "Failed to get window bounds"); - return; - } - d->logicalRect = QRectF(windowSize.X, windowSize.Y, windowSize.Width, windowSize.Height); - Rect visibleRect; - hr = d->view2->get_VisibleBounds(&visibleRect); - if (FAILED(hr)) { - qErrnoWarning(hr, "Failed to get window visible bounds"); - return; - } - visibleRectF = QRectF(visibleRect.X, visibleRect.Y, visibleRect.Width, visibleRect.Height); - // if keyboard is snapped to the bottom of the screen and would cover the cursor the content is - // moved up to make it visible - if (keyboardRect.intersects(mCursorRect) - && qFuzzyCompare(geometry().height(), keyboardRect.y() + keyboardRect.height())) { - visibleRectF.moveTop(visibleRectF.top() - keyboardRect.height() / d->scaleFactor); - } - d->visibleRect = visibleRectF; - - qCDebug(lcQpaWindows) << __FUNCTION__ << d->visibleRect; - QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry()); - QPlatformScreen::resizeMaximizedWindows(); - handleExpose(); -} - -QWindow *QWinRTScreen::topWindow() const -{ - Q_D(const QWinRTScreen); - return d->visibleWindows.isEmpty() ? 0 : d->visibleWindows.first(); -} - -QWindow *QWinRTScreen::windowAt(const QPoint &pos) -{ - Q_D(const QWinRTScreen); - for (auto w : qAsConst(d->visibleWindows)) { - if (w->geometry().contains(pos)) - return w; - } - qCDebug(lcQpaWindows) << __FUNCTION__ << ": No window found at:" << pos; - return nullptr; -} - -void QWinRTScreen::addWindow(QWindow *window) -{ - Q_D(QWinRTScreen); - qCDebug(lcQpaWindows) << __FUNCTION__ << window; - if (window == topWindow() || window->surfaceClass() == QSurface::Offscreen) - return; - - d->visibleWindows.prepend(window); - const Qt::WindowType type = window->type(); - if (type != Qt::Popup && type != Qt::ToolTip && type != Qt::Tool) { - updateWindowTitle(window->title()); - QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); - } - - handleExpose(); - d->firstMouseMove = true; - QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); - -#if QT_CONFIG(draganddrop) - QWinRTDrag::instance()->setDropTarget(window); -#endif -} - -void QWinRTScreen::removeWindow(QWindow *window) -{ - Q_D(QWinRTScreen); - qCDebug(lcQpaWindows) << __FUNCTION__ << window; - - handleExpose(); - - const bool wasTopWindow = window == topWindow(); - if (!d->visibleWindows.removeAll(window)) - return; - - const Qt::WindowType type = window->type(); - if (wasTopWindow && type != Qt::Popup && type != Qt::ToolTip && type != Qt::Tool) - QWindowSystemInterface::handleWindowActivated(nullptr, Qt::OtherFocusReason); - QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); -#if QT_CONFIG(draganddrop) - if (wasTopWindow) - QWinRTDrag::instance()->setDropTarget(topWindow()); -#endif -} - -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; - if (window->surfaceClass() == QSurface::Offscreen) - return; - d->visibleWindows.removeAll(window); - d->visibleWindows.append(window); - if (wasTopWindow) - QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); - handleExpose(); -} - -bool QWinRTScreen::setMouseGrabWindow(QWinRTWindow *window, bool grab) -{ - Q_D(QWinRTScreen); - qCDebug(lcQpaWindows) << __FUNCTION__ << window - << "(" << window->window()->objectName() << "):" << grab; - - if (!grab || window == nullptr) - d->mouseGrabWindow = nullptr; - else if (d->mouseGrabWindow != window) - d->mouseGrabWindow = window; - return grab; -} - -QWinRTWindow *QWinRTScreen::mouseGrabWindow() const -{ - Q_D(const QWinRTScreen); - return d->mouseGrabWindow; -} - -bool QWinRTScreen::setKeyboardGrabWindow(QWinRTWindow *window, bool grab) -{ - Q_D(QWinRTScreen); - qCDebug(lcQpaWindows) << __FUNCTION__ << window - << "(" << window->window()->objectName() << "):" << grab; - - if (!grab || window == nullptr) - d->keyboardGrabWindow = nullptr; - else if (d->keyboardGrabWindow != window) - d->keyboardGrabWindow = window; - return grab; -} - -QWinRTWindow *QWinRTScreen::keyboardGrabWindow() const -{ - Q_D(const QWinRTScreen); - return d->keyboardGrabWindow; -} - -void QWinRTScreen::updateWindowTitle(const QString &title) -{ - Q_D(QWinRTScreen); - - 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()) - 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); - - const bool wasPressed = d->activeKeys.contains(key); - if (wasPressed) { - if (!shouldAutoRepeat(key)) - return S_OK; - - d->activeKeys[key].isAutoRepeat = true; - // If the key was pressed before trigger a key release before the next key press - QWindowSystemInterface::handleExtendedKeyEvent( - topWindow(), - QEvent::KeyRelease, - key, - keyboardModifiers(), - !status.ScanCode ? -1 : status.ScanCode, - virtualKey, - 0, - QString(), - d->activeKeys.value(key).isAutoRepeat); - } else { - d->activeKeys.insert(key, KeyInfo(virtualKey)); - } - - // Defer character key presses to onCharacterReceived - if (key == Qt::Key_unknown || (key >= Qt::Key_Space && key <= Qt::Key_ydiaeresis)) - return S_OK; - - Qt::KeyboardModifiers modifiers = keyboardModifiers(); - // If the key actually pressed is a modifier key, then we remove its modifier key from the - // state, since a modifier-key can't have itself as a modifier (see qwindowskeymapper.cpp) - if (key == Qt::Key_Control) - modifiers = modifiers ^ Qt::ControlModifier; - else if (key == Qt::Key_Shift) - modifiers = modifiers ^ Qt::ShiftModifier; - else if (key == Qt::Key_Alt) - modifiers = modifiers ^ Qt::AltModifier; - - QWindowSystemInterface::handleExtendedKeyEvent( - topWindow(), - QEvent::KeyPress, - key, - modifiers, - !status.ScanCode ? -1 : status.ScanCode, - virtualKey, - 0, - QString(), - d->activeKeys.value(key).isAutoRepeat); - 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, - false); // The final key release does not have autoRepeat set on Windows - return S_OK; -} - -HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *, ICharacterReceivedEventArgs *args) -{ - Q_D(QWinRTScreen); - quint32 keyCode; - 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); - KeyInfo &info = d->activeKeys[key]; - info.text = text; - QWindowSystemInterface::handleExtendedKeyEvent( - topWindow(), - QEvent::KeyPress, - key, - modifiers, - !status.ScanCode ? -1 : status.ScanCode, - info.virtualKey, - 0, - text, - info.isAutoRepeat); - return S_OK; -} - -HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args) -{ - Q_D(QWinRTScreen); - qCDebug(lcQpaEvents) << __FUNCTION__; - - 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); - - d->currentTargetWindow = topWindow(); - if (d->mouseGrabWindow) - d->currentTargetWindow = d->mouseGrabWindow.loadRelaxed()->window(); - - qCDebug(lcQpaEvents) << __FUNCTION__ << "handleEnterEvent" << d->currentTargetWindow << pos; - QWindowSystemInterface::handleEnterEvent(d->currentTargetWindow, pos, pos); - d->firstMouseMove = false; - } - return S_OK; -} - -HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *args) -{ - Q_D(QWinRTScreen); - qCDebug(lcQpaEvents) << __FUNCTION__; - ComPtr<IPointerPoint> pointerPoint; - if (FAILED(args->get_CurrentPoint(&pointerPoint))) - return E_INVALIDARG; - - quint32 id; - if (FAILED(pointerPoint->get_PointerId(&id))) - return E_INVALIDARG; - - d->touchPoints.remove(id); - - if (d->mouseGrabWindow) - d->currentTargetWindow = d->mouseGrabWindow.loadRelaxed()->window(); - - qCDebug(lcQpaEvents) << __FUNCTION__ << "handleLeaveEvent" << d->currentTargetWindow; - QWindowSystemInterface::handleLeaveEvent(d->currentTargetWindow); - d->currentTargetWindow = nullptr; - return S_OK; -} - -// Required for qwinrtdrag.cpp -ComPtr<IPointerPoint> qt_winrt_lastPointerPoint; - -HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args) -{ - Q_D(QWinRTScreen); - qCDebug(lcQpaEvents) << __FUNCTION__; - ComPtr<IPointerPoint> pointerPoint; - if (FAILED(args->get_CurrentPoint(&pointerPoint))) - return E_INVALIDARG; - - qt_winrt_lastPointerPoint = pointerPoint; - // Common traits - point, modifiers, properties - Point point; - pointerPoint->get_Position(&point); - const QPointF pos(point.X * d->scaleFactor, point.Y * d->scaleFactor); - QPointF localPos = pos; - - const QPoint posPoint = pos.toPoint(); - QWindow *windowUnderPointer = windowAt(QHighDpiScaling::mapPositionFromNative(posPoint, this)); - d->currentTargetWindow = windowUnderPointer; - - if (d->mouseGrabWindow) - d->currentTargetWindow = d->mouseGrabWindow.loadRelaxed()->window(); - - if (d->currentTargetWindow) { - const QPointF globalPosDelta = pos - posPoint; - localPos = d->currentTargetWindow->mapFromGlobal(posPoint) + globalPosDelta; - } - - VirtualKeyModifiers modifiers; - 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); - qCDebug(lcQpaEvents) << __FUNCTION__ << "handleWheelEvent" << d->currentTargetWindow - << localPos << pos << angleDelta << mods; - QWindowSystemInterface::handleWheelEvent(d->currentTargetWindow, 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; - - // In case of a mouse grab we have to store the target of a press event - // to be able to send one additional release event to this target when the mouse - // button is released. This is a similar approach to AutoMouseCapture in the - // windows qpa backend. Otherwise the release might not be propagated and the original - // press event receiver considers a button to still be pressed, as in Qt Quick Controls 1 - // menus. - if (buttons != Qt::NoButton && d->currentPressWindow == nullptr && !d->mouseGrabWindow) - d->currentPressWindow = windowUnderPointer; - if (buttons == Qt::NoButton && d->currentPressWindow && d->mouseGrabWindow) { - const QPointF globalPosDelta = pos - posPoint; - const QPointF localPressPos = d->currentPressWindow->mapFromGlobal(posPoint) + globalPosDelta; - - qCDebug(lcQpaEvents) << __FUNCTION__ << "handleMouseEvent" << d->currentPressWindow - << localPressPos << pos << buttons << mods; - QWindowSystemInterface::handleMouseEvent(d->currentPressWindow, localPressPos, pos, buttons, mods); - d->currentPressWindow = nullptr; - } - // If the mouse button is released outside of a window, targetWindow is 0, but the event - // has to be delivered to the window, that initially received the mouse press. Do not reset - // d->currentTargetWindow though, as it is used (and reset) in onPointerExited. - if (buttons == Qt::NoButton && d->currentPressWindow && !d->currentTargetWindow) { - d->currentTargetWindow = d->currentPressWindow; - d->currentPressWindow = nullptr; - } - - qCDebug(lcQpaEvents) << __FUNCTION__ << "handleMouseEvent" << d->currentTargetWindow - << localPos << pos << buttons << mods; - QWindowSystemInterface::handleMouseEvent(d->currentTargetWindow, localPos, pos, buttons, mods); - - break; - } - case PointerDeviceType_Pen: - 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); - } - - quint32 id; - pointerPoint->get_PointerId(&id); - - Rect area; - properties->get_ContactRect(&area); - - float pressure; - properties->get_Pressure(&pressure); - - boolean isPressed; - pointerPoint->get_IsInContact(&isPressed); - - // Devices like the Hololens set a static pressure of 0.0 or 0.5 - // (depending on the image) independent of the pressed state. - // In those cases we need to synthesize the pressure value. To our - // knowledge this does not apply to pens - if (pointerDeviceType == PointerDeviceType_Touch && (pressure == 0.0f || pressure == 0.5f)) - pressure = isPressed ? 1. : 0.; - - const QRectF areaRect(area.X * d->scaleFactor, area.Y * d->scaleFactor, - area.Width * d->scaleFactor, area.Height * d->scaleFactor); - - QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator it = d->touchPoints.find(id); - if (it == d->touchPoints.end()) { - it = d->touchPoints.insert(id, QWindowSystemInterface::TouchPoint()); - it.value().id = id; - } - - const bool wasPressEvent = isPressed && it.value().pressure == 0.; - if (wasPressEvent) - it.value().state = Qt::TouchPointPressed; - else if (!isPressed && it.value().pressure > 0.) - it.value().state = Qt::TouchPointReleased; - else if (it.value().area == areaRect) - it.value().state = Qt::TouchPointStationary; - else - it.value().state = Qt::TouchPointMoved; - - it.value().area = areaRect; - it.value().normalPosition = QPointF(point.X/d->logicalRect.width(), point.Y/d->logicalRect.height()); - it.value().pressure = pressure; - - qCDebug(lcQpaEvents) << __FUNCTION__ << "handleTouchEvent" << d->currentTargetWindow - << d->touchDevice << d->touchPoints.values() << mods; - QWindowSystemInterface::handleTouchEvent(d->currentTargetWindow, d->touchDevice, d->touchPoints.values(), mods); - if (wasPressEvent) - it.value().state = Qt::TouchPointStationary; - - // Fall-through for pen to generate tablet event - if (pointerDeviceType != PointerDeviceType_Pen) - break; - - boolean isEraser; - properties->get_IsEraser(&isEraser); - int pointerType = isEraser ? 3 : 1; - - float xTilt; - properties->get_XTilt(&xTilt); - - float yTilt; - properties->get_YTilt(&yTilt); - - float rotation; - properties->get_Twist(&rotation); - - qCDebug(lcQpaEvents) << __FUNCTION__ << "handleTabletEvent" << d->currentTargetWindow - << isPressed << pos << pointerType << pressure << xTilt << yTilt - << rotation << id << mods; - QWindowSystemInterface::handleTabletEvent(d->currentTargetWindow, isPressed, pos, pos, 0, - pointerType, pressure, xTilt, yTilt, - 0, rotation, 0, id, mods); - - break; - } - } - - return S_OK; -} - -void QWinRTScreen::emulateMouseMove(const QPointF &point, MousePositionTransition transition) -{ - Q_D(QWinRTScreen); - qCDebug(lcQpaEvents) << __FUNCTION__ << point << transition; - if (transition == MousePositionTransition::StayedOut) - return; - qt_winrt_lastPointerPoint = nullptr; - const QPointF pos(point.x() * d->scaleFactor, point.y() * d->scaleFactor); - QPointF localPos = pos; - - const QPoint posPoint = pos.toPoint(); - QWindow *windowUnderPointer = windowAt(QHighDpiScaling::mapPositionFromNative(posPoint, this)); - d->currentTargetWindow = windowUnderPointer; - - if (d->mouseGrabWindow) - d->currentTargetWindow = d->mouseGrabWindow.loadRelaxed()->window(); - - if (d->currentTargetWindow) { - const QPointF globalPosDelta = pos - posPoint; - localPos = d->currentTargetWindow->mapFromGlobal(posPoint) + globalPosDelta; - } - - // In case of a mouse grab we have to store the target of a press event - // to be able to send one additional release event to this target when the mouse - // button is released. This is a similar approach to AutoMouseCapture in the - // windows qpa backend. Otherwise the release might not be propagated and the original - // press event receiver considers a button to still be pressed, as in Qt Quick Controls 1 - // menus. - if (d->currentPressWindow && d->mouseGrabWindow) { - const QPointF globalPosDelta = pos - posPoint; - const QPointF localPressPos = d->currentPressWindow->mapFromGlobal(posPoint) + globalPosDelta; - - qCDebug(lcQpaEvents) << __FUNCTION__ << "handleMouseEvent" << d->currentPressWindow - << localPressPos << pos << Qt::NoButton << Qt::NoModifier; - QWindowSystemInterface::handleMouseEvent(d->currentPressWindow, localPressPos, pos, - Qt::NoButton, Qt::NoModifier); - d->currentPressWindow = nullptr; - } - // If the mouse button is released outside of a window, targetWindow is 0, but the event - // has to be delivered to the window, that initially received the mouse press. Do not reset - // d->currentTargetWindow though, as it is used (and reset) in onPointerExited. - if (d->currentPressWindow && !d->currentTargetWindow) { - d->currentTargetWindow = d->currentPressWindow; - d->currentPressWindow = nullptr; - } - - if (transition == MousePositionTransition::MovedOut) { - qCDebug(lcQpaEvents) << __FUNCTION__ << "handleLeaveEvent" << d->currentTargetWindow; - QWindowSystemInterface::handleLeaveEvent(d->currentTargetWindow); - return; - } - - if (transition == MousePositionTransition::MovedIn || d->firstMouseMove) { - qCDebug(lcQpaEvents) << __FUNCTION__ << "handleEnterEvent" << d->currentTargetWindow - << localPos << pos; - QWindowSystemInterface::handleEnterEvent(d->currentTargetWindow, localPos, pos); - d->firstMouseMove = false; - } - qCDebug(lcQpaEvents) << __FUNCTION__ << "handleMouseEvent" << d->currentTargetWindow - << localPos << pos << Qt::NoButton << Qt::NoModifier; - QWindowSystemInterface::handleMouseEvent(d->currentTargetWindow, localPos, pos, Qt::NoButton, - Qt::NoModifier); -} - -void QWinRTScreen::setResizePending() -{ - Q_D(QWinRTScreen); - d->resizePending = true; -} - -bool QWinRTScreen::resizePending() const -{ - Q_D(const QWinRTScreen); - return d->resizePending; -} - -HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args) -{ - Q_D(QWinRTScreen); - qCDebug(lcQpaWindows) << __FUNCTION__; - - CoreWindowActivationState activationState; - args->get_WindowActivationState(&activationState); - if (activationState == CoreWindowActivationState_Deactivated) { - QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive); - return S_OK; - } - - QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive); - - // 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 *) -{ - qCDebug(lcQpaWindows) << __FUNCTION__; - - 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 visibility."); - qCDebug(lcQpaWindows) << __FUNCTION__ << visible; - QWindowSystemInterface::handleApplicationStateChanged(visible ? Qt::ApplicationActive : Qt::ApplicationHidden); - if (visible) { - handleExpose(); - onWindowSizeChanged(nullptr, nullptr); - } - return S_OK; -} - -HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable *) -{ - Q_D(QWinRTScreen); - qCDebug(lcQpaWindows) << __FUNCTION__; - 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; - qCDebug(lcQpaWindows) << " New orientation:" << newOrientation; - onWindowSizeChanged(nullptr, nullptr); - 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; - ResolutionScale resolutionScale; - hr = d->displayInformation->get_ResolutionScale(&resolutionScale); - d->scaleFactor = qreal(resolutionScale) / 100; - - qCDebug(lcQpaWindows) << __FUNCTION__ << "Scale Factor:" << d->scaleFactor; - - 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; - qCDebug(lcQpaWindows) << __FUNCTION__ << "Logical DPI:" << d->logicalDpi - << "Physical DPI:" << d->physicalDpi; - - return S_OK; -} - -HRESULT QWinRTScreen::onRedirectReleased(ICorePointerRedirector *, IPointerEventArgs *args) -{ - // When dragging ends with a non-mouse input device then onRedirectRelease is invoked. - // QTBUG-58781 - qCDebug(lcQpaEvents) << __FUNCTION__; - return onPointerUpdated(nullptr, args); -} - -HRESULT QWinRTScreen::onWindowSizeChanged(IApplicationView *w, IInspectable *) -{ - Q_D(QWinRTScreen); - - HRESULT hr; - Rect windowSize; - - hr = d->coreWindow->get_Bounds(&windowSize); - RETURN_OK_IF_FAILED("Failed to get window bounds"); - d->logicalRect = QRectF(windowSize.X, windowSize.Y, windowSize.Width, windowSize.Height); - - Rect visibleRect; - hr = d->view2->get_VisibleBounds(&visibleRect); - RETURN_OK_IF_FAILED("Failed to get window visible bounds"); - d->visibleRect = QRectF(visibleRect.X, visibleRect.Y, visibleRect.Width, visibleRect.Height); - - qCDebug(lcQpaWindows) << __FUNCTION__ << d->logicalRect; - QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry()); - QPlatformScreen::resizeMaximizedWindows(); - handleExpose(); - // If we "emulate" a resize, w will be nullptr.Checking w shows whether it's a real resize - if (w) - d->resizePending = false; - return S_OK; -} - -QT_END_NAMESPACE |