/****************************************************************************
**
** 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);
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); }
typedef HRESULT (__stdcall ICorePointerRedirector::*RedirectorCallbackRemover)(EventRegistrationToken);
uint qHash(RedirectorCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
typedef HRESULT (__stdcall IApplicationView2::*ApplicationView2CallbackRemover)(EventRegistrationToken);
uint 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
