summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows')
-rw-r--r--src/plugins/platforms/windows/CMakeLists.txt213
-rw-r--r--src/plugins/platforms/windows/cursors.qrc25
-rw-r--r--src/plugins/platforms/windows/main.cpp54
-rw-r--r--src/plugins/platforms/windows/openglblacklists.qrc5
-rw-r--r--src/plugins/platforms/windows/openglblacklists/default.json2
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h117
-rw-r--r--src/plugins/platforms/windows/qwin10helpers.cpp83
-rw-r--r--src/plugins/platforms/windows/qwin10helpers.h40
-rw-r--r--src/plugins/platforms/windows/qwindowsapplication.cpp146
-rw-r--r--src/plugins/platforms/windows/qwindowsapplication.h55
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp54
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.h40
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.cpp65
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.h40
-rw-r--r--src/plugins/platforms/windows/qwindowscombase.h112
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp699
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h153
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp120
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h46
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp377
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.h44
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp171
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.h56
-rw-r--r--src/plugins/platforms/windows/qwindowsdropdataobject.cpp51
-rw-r--r--src/plugins/platforms/windows/qwindowsdropdataobject.h44
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp920
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.h176
-rw-r--r--src/plugins/platforms/windows/qwindowsgdiintegration.cpp40
-rw-r--r--src/plugins/platforms/windows/qwindowsgdiintegration.h40
-rw-r--r--src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp40
-rw-r--r--src/plugins/platforms/windows/qwindowsgdinativeinterface.h40
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp191
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h66
-rw-r--r--src/plugins/platforms/windows/qwindowsiconengine.cpp394
-rw-r--r--src/plugins/platforms/windows/qwindowsiconengine.h47
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp63
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.h40
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp465
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h70
-rw-r--r--src/plugins/platforms/windows/qwindowsinternalmimedata.cpp66
-rw-r--r--src/plugins/platforms/windows/qwindowsinternalmimedata.h42
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp212
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.h48
-rw-r--r--src/plugins/platforms/windows/qwindowsmenu.cpp73
-rw-r--r--src/plugins/platforms/windows/qwindowsmenu.h47
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.h108
-rw-r--r--src/plugins/platforms/windows/qwindowsmimeregistry.cpp (renamed from src/plugins/platforms/windows/qwindowsmime.cpp)606
-rw-r--r--src/plugins/platforms/windows/qwindowsmimeregistry.h58
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp159
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.h53
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp192
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.h78
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp58
-rw-r--r--src/plugins/platforms/windows/qwindowsole.h84
-rw-r--r--src/plugins/platforms/windows/qwindowsopenglcontext.h44
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp152
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.h51
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp359
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.h66
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp537
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h71
-rw-r--r--src/plugins/platforms/windows/qwindowsservices.cpp165
-rw-r--r--src/plugins/platforms/windows/qwindowsservices.h40
-rw-r--r--src/plugins/platforms/windows/qwindowssessionmanager.cpp42
-rw-r--r--src/plugins/platforms/windows/qwindowssessionmanager.h42
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.cpp146
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.h42
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp361
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.h99
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp710
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h60
-rw-r--r--src/plugins/platforms/windows/qwindowsthreadpoolrunner.h41
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.cpp40
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.h42
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp1275
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h117
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp116
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h43
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp40
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h44
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp90
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.h33
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp40
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h42
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp40
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h43
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp40
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h43
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp246
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h52
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp42
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h40
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp40
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h42
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp97
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h42
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp218
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h61
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp40
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h42
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp40
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h43
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp61
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h59
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp101
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h44
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp40
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h43
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp62
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h42
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp74
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h70
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp42
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h43
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.cpp40
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.h43
-rw-r--r--src/plugins/platforms/windows/uiautomation/uiautomation.pri44
-rw-r--r--src/plugins/platforms/windows/windows.pri130
-rw-r--r--src/plugins/platforms/windows/windows.pro32
119 files changed, 5940 insertions, 8479 deletions
diff --git a/src/plugins/platforms/windows/CMakeLists.txt b/src/plugins/platforms/windows/CMakeLists.txt
new file mode 100644
index 0000000000..4b92317978
--- /dev/null
+++ b/src/plugins/platforms/windows/CMakeLists.txt
@@ -0,0 +1,213 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## QWindowsIntegrationPlugin Plugin:
+#####################################################################
+
+qt_internal_add_plugin(QWindowsIntegrationPlugin
+ OUTPUT_NAME qwindows
+ PLUGIN_TYPE platforms
+ DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES windows
+ SOURCES
+ main.cpp
+ qtwindowsglobal.h
+ qwin10helpers.cpp qwin10helpers.h
+ qwindowsapplication.cpp qwindowsapplication.h
+ qwindowsbackingstore.cpp qwindowsbackingstore.h
+ qwindowscontext.cpp qwindowscontext.h
+ qwindowscursor.cpp qwindowscursor.h
+ qwindowsdialoghelpers.cpp qwindowsdialoghelpers.h
+ qwindowsdropdataobject.cpp qwindowsdropdataobject.h
+ qwindowsgdiintegration.cpp qwindowsgdiintegration.h
+ qwindowsgdinativeinterface.cpp qwindowsgdinativeinterface.h
+ qwindowsiconengine.cpp qwindowsiconengine.h
+ qwindowsinputcontext.cpp qwindowsinputcontext.h
+ qwindowsintegration.cpp qwindowsintegration.h
+ qwindowsinternalmimedata.cpp qwindowsinternalmimedata.h
+ qwindowskeymapper.cpp qwindowskeymapper.h
+ qwindowsmenu.cpp qwindowsmenu.h
+ qwindowsmimeregistry.cpp qwindowsmimeregistry.h
+ qwindowsmousehandler.cpp qwindowsmousehandler.h
+ qwindowsnativeinterface.cpp qwindowsnativeinterface.h
+ qwindowsole.cpp qwindowsole.h
+ qwindowsopengltester.cpp qwindowsopengltester.h
+ qwindowspointerhandler.cpp qwindowspointerhandler.h
+ qwindowsscreen.cpp qwindowsscreen.h
+ qwindowsservices.cpp qwindowsservices.h
+ qwindowstheme.cpp qwindowstheme.h
+ qwindowsthreadpoolrunner.h
+ qwindowswindow.cpp qwindowswindow.h
+ NO_UNITY_BUILD_SOURCES
+ qwindowspointerhandler.cpp
+ DEFINES
+ QT_NO_CAST_FROM_ASCII
+ QT_NO_FOREACH
+ INCLUDE_DIRECTORIES
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ LIBRARIES
+ Qt::Core
+ Qt::CorePrivate
+ Qt::Gui
+ Qt::GuiPrivate
+ advapi32
+ dwmapi
+ gdi32
+ imm32
+ ole32
+ oleaut32
+ setupapi
+ shell32
+ shlwapi
+ user32
+ winmm
+ winspool
+ wtsapi32
+ shcore
+ comdlg32
+ d3d9
+ runtimeobject
+)
+
+# Resources:
+set_source_files_properties("openglblacklists/default.json"
+ PROPERTIES QT_RESOURCE_ALIAS "default.json"
+)
+set(openglblacklists_resource_files
+ "openglblacklists/default.json"
+)
+
+qt_internal_add_resource(QWindowsIntegrationPlugin "openglblacklists"
+ PREFIX
+ "/qt-project.org/windows/openglblacklists"
+ FILES
+ ${openglblacklists_resource_files}
+)
+
+## Scopes:
+#####################################################################
+
+qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_opengl
+ SOURCES
+ qwindowsglcontext.cpp qwindowsglcontext.h
+ qwindowsopenglcontext.h
+ LIBRARIES
+ Qt::OpenGLPrivate
+)
+
+qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_opengl AND NOT QT_FEATURE_dynamicgl
+ LIBRARIES
+ opengl32
+)
+
+qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION MINGW
+ LIBRARIES
+ uuid
+ NO_PCH_SOURCES
+ qwindowspointerhandler.cpp
+)
+
+qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_systemtrayicon
+ SOURCES
+ qwindowssystemtrayicon.cpp qwindowssystemtrayicon.h
+)
+
+qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_vulkan
+ SOURCES
+ qwindowsvulkaninstance.cpp qwindowsvulkaninstance.h
+)
+
+qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_clipboard
+ SOURCES
+ qwindowsclipboard.cpp qwindowsclipboard.h
+)
+
+qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_clipboard AND QT_FEATURE_draganddrop
+ SOURCES
+ qwindowsdrag.cpp qwindowsdrag.h
+)
+
+qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_tabletevent
+ SOURCES
+ qwindowstabletsupport.cpp qwindowstabletsupport.h
+ INCLUDE_DIRECTORIES
+ ${QtBase_SOURCE_DIR}/src/3rdparty/wintab
+)
+
+qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_sessionmanager
+ SOURCES
+ qwindowssessionmanager.cpp qwindowssessionmanager.h
+)
+
+if(QT_FEATURE_imageformat_png)
+ # Resources:
+ set(cursors_resource_files
+ "images/closedhandcursor_32.png"
+ "images/closedhandcursor_48.png"
+ "images/closedhandcursor_64.png"
+ "images/dragcopycursor_32.png"
+ "images/dragcopycursor_48.png"
+ "images/dragcopycursor_64.png"
+ "images/draglinkcursor_32.png"
+ "images/draglinkcursor_48.png"
+ "images/draglinkcursor_64.png"
+ "images/dragmovecursor_32.png"
+ "images/dragmovecursor_48.png"
+ "images/dragmovecursor_64.png"
+ "images/openhandcursor_32.png"
+ "images/openhandcursor_48.png"
+ "images/openhandcursor_64.png"
+ "images/splithcursor_32.png"
+ "images/splithcursor_48.png"
+ "images/splithcursor_64.png"
+ "images/splitvcursor_32.png"
+ "images/splitvcursor_48.png"
+ "images/splitvcursor_64.png"
+ )
+
+ qt_internal_add_resource(QWindowsIntegrationPlugin "cursors"
+ PREFIX
+ "/qt-project.org/windows/cursors"
+ FILES
+ ${cursors_resource_files}
+ )
+endif()
+
+qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_accessibility
+ SOURCES
+ uiautomation/qwindowsuiautomation.cpp uiautomation/qwindowsuiautomation.h
+ uiautomation/qwindowsuiaaccessibility.cpp uiautomation/qwindowsuiaaccessibility.h
+ uiautomation/qwindowsuiabaseprovider.cpp uiautomation/qwindowsuiabaseprovider.h
+ uiautomation/qwindowsuiaexpandcollapseprovider.cpp uiautomation/qwindowsuiaexpandcollapseprovider.h
+ uiautomation/qwindowsuiagriditemprovider.cpp uiautomation/qwindowsuiagriditemprovider.h
+ uiautomation/qwindowsuiagridprovider.cpp uiautomation/qwindowsuiagridprovider.h
+ uiautomation/qwindowsuiainvokeprovider.cpp uiautomation/qwindowsuiainvokeprovider.h
+ uiautomation/qwindowsuiamainprovider.cpp uiautomation/qwindowsuiamainprovider.h
+ uiautomation/qwindowsuiaprovidercache.cpp uiautomation/qwindowsuiaprovidercache.h
+ uiautomation/qwindowsuiarangevalueprovider.cpp uiautomation/qwindowsuiarangevalueprovider.h
+ uiautomation/qwindowsuiaselectionitemprovider.cpp uiautomation/qwindowsuiaselectionitemprovider.h
+ uiautomation/qwindowsuiaselectionprovider.cpp uiautomation/qwindowsuiaselectionprovider.h
+ uiautomation/qwindowsuiatableitemprovider.cpp uiautomation/qwindowsuiatableitemprovider.h
+ uiautomation/qwindowsuiatableprovider.cpp uiautomation/qwindowsuiatableprovider.h
+ uiautomation/qwindowsuiatextprovider.cpp uiautomation/qwindowsuiatextprovider.h
+ uiautomation/qwindowsuiatextrangeprovider.cpp uiautomation/qwindowsuiatextrangeprovider.h
+ uiautomation/qwindowsuiatoggleprovider.cpp uiautomation/qwindowsuiatoggleprovider.h
+ uiautomation/qwindowsuiautils.cpp uiautomation/qwindowsuiautils.h
+ uiautomation/qwindowsuiavalueprovider.cpp uiautomation/qwindowsuiavalueprovider.h
+ uiautomation/qwindowsuiawindowprovider.cpp uiautomation/qwindowsuiawindowprovider.h
+)
+
+if(QT_FEATURE_accessibility)
+ find_library(UI_AUTOMATION_LIBRARY uiautomationcore)
+ if(UI_AUTOMATION_LIBRARY)
+ qt_internal_extend_target(QWindowsIntegrationPlugin
+ LIBRARIES
+ ${UI_AUTOMATION_LIBRARY}
+ )
+ endif()
+endif()
+
+qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION MINGW AND QT_FEATURE_accessibility
+ LIBRARIES
+ uuid
+)
diff --git a/src/plugins/platforms/windows/cursors.qrc b/src/plugins/platforms/windows/cursors.qrc
deleted file mode 100644
index fded527aac..0000000000
--- a/src/plugins/platforms/windows/cursors.qrc
+++ /dev/null
@@ -1,25 +0,0 @@
-<RCC>
- <qresource prefix="/qt-project.org/windows/cursors">
- <file>images/closedhandcursor_32.png</file>
- <file>images/closedhandcursor_48.png</file>
- <file>images/closedhandcursor_64.png</file>
- <file>images/dragcopycursor_32.png</file>
- <file>images/dragcopycursor_48.png</file>
- <file>images/dragcopycursor_64.png</file>
- <file>images/draglinkcursor_32.png</file>
- <file>images/draglinkcursor_48.png</file>
- <file>images/draglinkcursor_64.png</file>
- <file>images/dragmovecursor_32.png</file>
- <file>images/dragmovecursor_48.png</file>
- <file>images/dragmovecursor_64.png</file>
- <file>images/openhandcursor_32.png</file>
- <file>images/openhandcursor_48.png</file>
- <file>images/openhandcursor_64.png</file>
- <file>images/splithcursor_32.png</file>
- <file>images/splithcursor_48.png</file>
- <file>images/splithcursor_64.png</file>
- <file>images/splitvcursor_32.png</file>
- <file>images/splitvcursor_48.png</file>
- <file>images/splitvcursor_64.png</file>
- </qresource>
-</RCC>
diff --git a/src/plugins/platforms/windows/main.cpp b/src/plugins/platforms/windows/main.cpp
index 1929f800a4..51c1fb4a45 100644
--- a/src/plugins/platforms/windows/main.cpp
+++ b/src/plugins/platforms/windows/main.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qpa/qplatformintegrationplugin.h>
@@ -45,11 +9,12 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
- \group qt-lighthouse-win
- \title Qt Lighthouse plugin for Windows
+ \title Qt platform plugin for Windows
- \brief Class documentation of the Qt Lighthouse plugin for Windows.
+ \brief Class documentation of the Qt platform plugin for Windows.
\section1 Supported Parameters
@@ -78,7 +43,6 @@ QT_BEGIN_NAMESPACE
\class QWindowsIntegrationPlugin
\brief Plugin.
\internal
- \ingroup qt-lighthouse-win
*/
/*!
@@ -86,7 +50,6 @@ QT_BEGIN_NAMESPACE
\brief Namespace for enumerations, etc.
\internal
- \ingroup qt-lighthouse-win
*/
/*!
@@ -97,7 +60,6 @@ QT_BEGIN_NAMESPACE
With flags that should help to structure the code.
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsIntegrationPlugin : public QPlatformIntegrationPlugin
@@ -105,12 +67,12 @@ class QWindowsIntegrationPlugin : public QPlatformIntegrationPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "windows.json")
public:
- QPlatformIntegration *create(const QString&, const QStringList&, int &, char **);
+ QPlatformIntegration *create(const QString &, const QStringList &, int &, char **) override;
};
QPlatformIntegration *QWindowsIntegrationPlugin::create(const QString& system, const QStringList& paramList, int &, char **)
{
- if (system.compare(system, QLatin1String("windows"), Qt::CaseInsensitive) == 0)
+ if (system.compare(system, "windows"_L1, Qt::CaseInsensitive) == 0)
return new QWindowsGdiIntegration(paramList);
return nullptr;
}
diff --git a/src/plugins/platforms/windows/openglblacklists.qrc b/src/plugins/platforms/windows/openglblacklists.qrc
deleted file mode 100644
index 9f0c186c21..0000000000
--- a/src/plugins/platforms/windows/openglblacklists.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<RCC>
- <qresource prefix="/qt-project.org/windows/openglblacklists">
- <file alias="default.json">openglblacklists/default.json</file>
- </qresource>
-</RCC>
diff --git a/src/plugins/platforms/windows/openglblacklists/default.json b/src/plugins/platforms/windows/openglblacklists/default.json
index e37351f9e0..072acdd115 100644
--- a/src/plugins/platforms/windows/openglblacklists/default.json
+++ b/src/plugins/platforms/windows/openglblacklists/default.json
@@ -93,7 +93,7 @@
},
{
"id": 8,
- "description": "Standard VGA: Insufficent support for OpenGL, D3D9 and D3D11",
+ "description": "Standard VGA: Insufficient support for OpenGL, D3D9 and D3D11",
"vendor_id": "0x0000",
"device_id": ["0x0000"],
"os": {
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index 985f13bdc5..96a72600eb 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTWINDOWSGLOBAL_H
#define QTWINDOWSGLOBAL_H
@@ -44,8 +8,16 @@
#include <QtCore/qt_windows.h>
#include <QtCore/qnamespace.h>
-#ifndef WM_DWMCOMPOSITIONCHANGED // MinGW.
-# define WM_DWMCOMPOSITIONCHANGED 0x31E
+#ifndef WM_DWMCOMPOSITIONCHANGED
+# define WM_DWMCOMPOSITIONCHANGED 0x31E
+#endif
+
+#ifndef WM_DWMCOLORIZATIONCOLORCHANGED
+# define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320
+#endif
+
+#ifndef WM_SYSCOLORCHANGE
+# define WM_SYSCOLORCHANGE 0x0015
#endif
#ifndef WM_TOUCH
@@ -60,6 +32,10 @@
# define WM_DPICHANGED 0x02E0
#endif
+#ifndef WM_GETDPISCALEDSIZE
+# define WM_GETDPISCALEDSIZE 0x02E4
+#endif
+
// WM_POINTER support from Windows 8 onwards (WINVER >= 0x0602)
#ifndef WM_POINTERUPDATE
# define WM_NCPOINTERUPDATE 0x0241
@@ -76,12 +52,20 @@
# define WM_POINTERHWHEEL 0x024F
#endif // WM_POINTERUPDATE
+#if !defined(_DPI_AWARENESS_CONTEXTS_)
+# define DPI_AWARENESS_CONTEXT_UNAWARE ((HANDLE)-1)
+# define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((HANDLE)-2)
+# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((HANDLE)-3)
+# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE)-4)
+# define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED ((HANDLE)-5)
+#endif
+
QT_BEGIN_NAMESPACE
namespace QtWindows
{
-enum
+enum WindowsEventTypeFlags
{
WindowEventFlag = 0x10000,
MouseEventFlag = 0x20000,
@@ -121,6 +105,9 @@ enum WindowsEventType // Simplify event types
EnterSizeMoveEvent = WindowEventFlag + 22,
ExitSizeMoveEvent = WindowEventFlag + 23,
PointerActivateWindowEvent = WindowEventFlag + 24,
+ DpiScaledSizeEvent = WindowEventFlag + 25,
+ DpiChangedAfterParentEvent = WindowEventFlag + 27,
+ TaskbarButtonCreated = WindowEventFlag + 28,
MouseEvent = MouseEventFlag + 1,
MouseWheelEvent = MouseEventFlag + 2,
CursorEvent = MouseEventFlag + 3,
@@ -132,7 +119,7 @@ enum WindowsEventType // Simplify event types
NonClientPointerEvent = NonClientEventFlag + PointerEventFlag + 4,
KeyEvent = KeyEventFlag + 1,
KeyDownEvent = KeyEventFlag + KeyDownEventFlag + 1,
- KeyboardLayoutChangeEvent = KeyEventFlag + 2,
+ InputLanguageChangeEvent = KeyEventFlag + 2,
InputMethodKeyEvent = InputMethodEventFlag + KeyEventFlag + 1,
InputMethodKeyDownEvent = InputMethodEventFlag + KeyEventFlag + KeyDownEventFlag + 1,
ClipboardEvent = ClipboardEventFlag + 1,
@@ -154,26 +141,37 @@ enum WindowsEventType // Simplify event types
InputMethodRequest = InputMethodEventFlag + 6,
ThemeChanged = ThemingEventFlag + 1,
CompositionSettingsChanged = ThemingEventFlag + 2,
- DisplayChangedEvent = 437,
- SettingChangedEvent = DisplayChangedEvent + 1,
+ SettingChangedEvent = 438,
ScrollEvent = GenericEventFlag + 1,
ContextMenu = 123,
GestureEvent = 124,
UnknownEvent = 542
};
+Q_DECLARE_MIXED_ENUM_OPERATORS(bool, WindowsEventTypeFlags, WindowsEventType);
+Q_DECLARE_MIXED_ENUM_OPERATORS(bool, WindowsEventType, WindowsEventTypeFlags);
-// Matches Process_DPI_Awareness (Windows 8.1 onwards), used for SetProcessDpiAwareness()
-enum ProcessDpiAwareness
+enum class DpiAwareness
{
- ProcessDpiUnaware,
- ProcessSystemDpiAware,
- ProcessPerMonitorDpiAware
+ Invalid = -1,
+ Unaware,
+ System,
+ PerMonitor,
+ PerMonitorVersion2,
+ Unaware_GdiScaled
};
} // namespace QtWindows
inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamIn, LPARAM lParamIn)
{
+ static const UINT WM_TASKBAR_BUTTON_CREATED = []{
+ UINT message = RegisterWindowMessage(L"TaskbarButtonCreated");
+ // In case the application is run elevated, allow the
+ // TaskbarButtonCreated message through.
+ ChangeWindowMessageFilter(message, MSGFLT_ADD);
+ return message;
+ }();
+
switch (message) {
case WM_PAINT:
case WM_ERASEBKGND:
@@ -232,7 +230,7 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
return QtWindows::InputMethodKeyDownEvent;
#ifdef WM_INPUTLANGCHANGE
case WM_INPUTLANGCHANGE:
- return QtWindows::KeyboardLayoutChangeEvent;
+ return QtWindows::InputLanguageChangeEvent;
#endif // WM_INPUTLANGCHANGE
case WM_TOUCH:
return QtWindows::TouchEvent;
@@ -271,12 +269,9 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
// http://msdn.microsoft.com/en-us/library/ms695534(v=vs.85).aspx
case WM_SETTINGCHANGE:
return QtWindows::SettingChangedEvent;
- case WM_DISPLAYCHANGE:
- return QtWindows::DisplayChangedEvent;
case WM_THEMECHANGED:
-#ifdef WM_SYSCOLORCHANGE // Windows 7: Handle color change as theme change (QTBUG-34170).
- case WM_SYSCOLORCHANGE:
-#endif
+ case WM_SYSCOLORCHANGE: // Handle color change as theme change (QTBUG-34170).
+ case WM_DWMCOLORIZATIONCOLORCHANGED:
return QtWindows::ThemeChanged;
case WM_DWMCOMPOSITIONCHANGED:
return QtWindows::CompositionSettingsChanged;
@@ -307,6 +302,10 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
return HIWORD(wParamIn) ? QtWindows::AcceleratorCommandEvent : QtWindows::MenuCommandEvent;
case WM_DPICHANGED:
return QtWindows::DpiChangedEvent;
+ case WM_DPICHANGED_AFTERPARENT:
+ return QtWindows::DpiChangedAfterParentEvent;
+ case WM_GETDPISCALEDSIZE:
+ return QtWindows::DpiScaledSizeEvent;
case WM_ENTERSIZEMOVE:
return QtWindows::EnterSizeMoveEvent;
case WM_EXITSIZEMOVE:
@@ -323,9 +322,15 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
return QtWindows::NonClientPointerEvent;
if (message >= WM_POINTERUPDATE && message <= WM_POINTERHWHEEL)
return QtWindows::PointerEvent;
+ if (message == WM_TASKBAR_BUTTON_CREATED)
+ return QtWindows::TaskbarButtonCreated;
return QtWindows::UnknownEvent;
}
+#ifndef QT_NO_DEBUG_STREAM
+extern QDebug operator<<(QDebug, QtWindows::DpiAwareness);
+#endif
+
QT_END_NAMESPACE
#endif // QTWINDOWSGLOBAL_H
diff --git a/src/plugins/platforms/windows/qwin10helpers.cpp b/src/plugins/platforms/windows/qwin10helpers.cpp
index 9a7fce9cd5..026e81cb0c 100644
--- a/src/plugins/platforms/windows/qwin10helpers.cpp
+++ b/src/plugins/platforms/windows/qwin10helpers.cpp
@@ -1,52 +1,16 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwin10helpers.h"
#include <QtCore/qdebug.h>
-#include <QtCore/qoperatingsystemversion.h>
-#include <QtCore/private/qsystemlibrary_p.h>
+#include <winstring.h>
+#include <roapi.h>
#if defined(Q_CC_MINGW) || defined(Q_CC_CLANG)
# define HAS_UI_VIEW_SETTINGS_INTEROP
// Present from MSVC2015 + SDK 10 onwards
-#elif (!defined(Q_CC_MSVC) || _MSC_VER >= 1900) && NTDDI_VERSION >= 0xa000000
+#elif (!defined(Q_CC_MSVC) || _MSC_VER >= 1900) && WINVER >= 0x0A00
# define HAS_UI_VIEW_SETTINGS_INTEROP
# define HAS_UI_VIEW_SETTINGS
#endif
@@ -96,56 +60,23 @@ public:
QT_BEGIN_NAMESPACE
-// Starting from Windows 10
-struct QWindowsComBaseDLL
-{
- bool init();
- bool isValid() const
- {
- return roGetActivationFactory != nullptr && windowsCreateStringReference != nullptr;
- }
-
- typedef HRESULT (WINAPI *RoGetActivationFactory)(HSTRING, REFIID, void **);
- typedef HRESULT (WINAPI *WindowsCreateStringReference)(PCWSTR, UINT32, HSTRING_HEADER *, HSTRING *);
-
- RoGetActivationFactory roGetActivationFactory = nullptr;
- WindowsCreateStringReference windowsCreateStringReference = nullptr;
-};
-
-static QWindowsComBaseDLL baseComDll;
-
-bool QWindowsComBaseDLL::init()
-{
- if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10 && !isValid()) {
- QSystemLibrary library(QStringLiteral("combase"));
- roGetActivationFactory =
- reinterpret_cast<RoGetActivationFactory>(library.resolve("RoGetActivationFactory"));
- windowsCreateStringReference =
- reinterpret_cast<WindowsCreateStringReference>(library.resolve("WindowsCreateStringReference"));
- }
- return isValid();
-}
-
// Return tablet mode, note: Does not work for GetDesktopWindow().
bool qt_windowsIsTabletMode(HWND hwnd)
{
bool result = false;
- if (!baseComDll.init())
- return false;
-
const wchar_t uiViewSettingsId[] = L"Windows.UI.ViewManagement.UIViewSettings";
HSTRING_HEADER uiViewSettingsIdRefHeader;
HSTRING uiViewSettingsIdHs = nullptr;
const auto uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
- if (FAILED(baseComDll.windowsCreateStringReference(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader, &uiViewSettingsIdHs)))
+ if (FAILED(WindowsCreateStringReference(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader, &uiViewSettingsIdHs)))
return false;
IUIViewSettingsInterop *uiViewSettingsInterop = nullptr;
// __uuidof(IUIViewSettingsInterop);
const GUID uiViewSettingsInteropRefId = {0x3694dbf9, 0x8f68, 0x44be,{0x8f, 0xf5, 0x19, 0x5c, 0x98, 0xed, 0xe8, 0xa6}};
- HRESULT hr = baseComDll.roGetActivationFactory(uiViewSettingsIdHs, uiViewSettingsInteropRefId,
+ HRESULT hr = RoGetActivationFactory(uiViewSettingsIdHs, uiViewSettingsInteropRefId,
reinterpret_cast<void **>(&uiViewSettingsInterop));
if (FAILED(hr))
return false;
diff --git a/src/plugins/platforms/windows/qwin10helpers.h b/src/plugins/platforms/windows/qwin10helpers.h
index 4f364dfc59..e601947267 100644
--- a/src/plugins/platforms/windows/qwin10helpers.h
+++ b/src/plugins/platforms/windows/qwin10helpers.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWIN10HELPERS_H
#define QWIN10HELPERS_H
diff --git a/src/plugins/platforms/windows/qwindowsapplication.cpp b/src/plugins/platforms/windows/qwindowsapplication.cpp
new file mode 100644
index 0000000000..42e34ac99f
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsapplication.cpp
@@ -0,0 +1,146 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwindowsapplication.h"
+#include "qwindowsclipboard.h"
+#include "qwindowscontext.h"
+#include "qwindowsmimeregistry.h"
+#include "qwin10helpers.h"
+#include "qwindowsopengltester.h"
+#include "qwindowswindow.h"
+#include "qwindowsintegration.h"
+#include "qwindowstheme.h"
+
+#include <QtCore/qvariant.h>
+#include <QtCore/private/qfunctions_win_p.h>
+
+#include <QtGui/qpalette.h>
+
+QT_BEGIN_NAMESPACE
+
+void QWindowsApplication::setTouchWindowTouchType(QWindowsApplication::TouchWindowTouchTypes type)
+{
+ if (m_touchWindowTouchTypes == type)
+ return;
+ m_touchWindowTouchTypes = type;
+ if (auto ctx = QWindowsContext::instance())
+ ctx->registerTouchWindows();
+}
+
+QWindowsApplication::TouchWindowTouchTypes QWindowsApplication::touchWindowTouchType() const
+{
+ return m_touchWindowTouchTypes;
+}
+
+QWindowsApplication::WindowActivationBehavior QWindowsApplication::windowActivationBehavior() const
+{
+ return m_windowActivationBehavior;
+}
+
+void QWindowsApplication::setWindowActivationBehavior(WindowActivationBehavior behavior)
+{
+ m_windowActivationBehavior = behavior;
+}
+
+void QWindowsApplication::setHasBorderInFullScreenDefault(bool border)
+{
+ QWindowsWindow::setHasBorderInFullScreenDefault(border);
+}
+
+bool QWindowsApplication::isTabletMode() const
+{
+#if QT_CONFIG(clipboard)
+ if (const QWindowsClipboard *clipboard = QWindowsClipboard::instance())
+ return qt_windowsIsTabletMode(clipboard->clipboardViewer());
+#endif
+ return false;
+}
+
+bool QWindowsApplication::isWinTabEnabled() const
+{
+ auto ctx = QWindowsContext::instance();
+ return ctx != nullptr && ctx->tabletSupport() != nullptr;
+}
+
+bool QWindowsApplication::setWinTabEnabled(bool enabled)
+{
+ if (enabled == isWinTabEnabled())
+ return true;
+ auto ctx = QWindowsContext::instance();
+ if (!ctx)
+ return false;
+ return enabled ? ctx->initTablet() : ctx->disposeTablet();
+}
+
+QWindowsApplication::DarkModeHandling QWindowsApplication::darkModeHandling() const
+{
+ return m_darkModeHandling;
+}
+
+void QWindowsApplication::setDarkModeHandling(QWindowsApplication::DarkModeHandling handling)
+{
+ m_darkModeHandling = handling;
+}
+
+void QWindowsApplication::registerMime(QWindowsMimeConverter *mime)
+{
+ if (auto ctx = QWindowsContext::instance())
+ ctx->mimeConverter().registerMime(mime);
+}
+
+void QWindowsApplication::unregisterMime(QWindowsMimeConverter *mime)
+{
+ if (auto ctx = QWindowsContext::instance())
+ ctx->mimeConverter().unregisterMime(mime);
+}
+
+int QWindowsApplication::registerMimeType(const QString &mime)
+{
+ return QWindowsMimeRegistry::registerMimeType(mime);
+}
+
+HWND QWindowsApplication::createMessageWindow(const QString &classNameTemplate,
+ const QString &windowName,
+ QFunctionPointer eventProc) const
+{
+ QWindowsContext *ctx = QWindowsContext::instance();
+ if (!ctx)
+ return nullptr;
+ auto wndProc = eventProc ? reinterpret_cast<WNDPROC>(eventProc) : DefWindowProc;
+ return ctx->createDummyWindow(classNameTemplate,
+ reinterpret_cast<const wchar_t*>(windowName.utf16()),
+ wndProc);
+}
+
+bool QWindowsApplication::asyncExpose() const
+{
+ QWindowsContext *ctx = QWindowsContext::instance();
+ return ctx && ctx->asyncExpose();
+}
+
+void QWindowsApplication::setAsyncExpose(bool value)
+{
+ if (QWindowsContext *ctx = QWindowsContext::instance())
+ ctx->setAsyncExpose(value);
+}
+
+QVariant QWindowsApplication::gpu() const
+{
+ return GpuDescription::detect().toVariant();
+}
+
+QVariant QWindowsApplication::gpuList() const
+{
+ QVariantList result;
+ const auto gpus = GpuDescription::detectAll();
+ for (const auto &gpu : gpus)
+ result.append(gpu.toVariant());
+ return result;
+}
+
+void QWindowsApplication::populateLightSystemPalette(QPalette &result) const
+{
+ result = QWindowsTheme::systemPalette(Qt::ColorScheme::Light);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsapplication.h b/src/plugins/platforms/windows/qwindowsapplication.h
new file mode 100644
index 0000000000..0918df91af
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsapplication.h
@@ -0,0 +1,55 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWINDOWSAPPLICATION_H
+#define QWINDOWSAPPLICATION_H
+
+#include <QtGui/private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsApplication : public QNativeInterface::Private::QWindowsApplication
+{
+public:
+ void setTouchWindowTouchType(TouchWindowTouchTypes type) override;
+ TouchWindowTouchTypes touchWindowTouchType() const override;
+
+ WindowActivationBehavior windowActivationBehavior() const override;
+ void setWindowActivationBehavior(WindowActivationBehavior behavior) override;
+
+ void setHasBorderInFullScreenDefault(bool border) override;
+
+ bool isTabletMode() const override;
+
+ bool isWinTabEnabled() const override;
+ bool setWinTabEnabled(bool enabled) override;
+
+ DarkModeHandling darkModeHandling() const override;
+ void setDarkModeHandling(DarkModeHandling handling) override;
+
+ void registerMime(QWindowsMimeConverter *mime) override;
+ void unregisterMime(QWindowsMimeConverter *mime) override;
+
+ int registerMimeType(const QString &mime) override;
+
+ HWND createMessageWindow(const QString &classNameTemplate,
+ const QString &windowName,
+ QFunctionPointer eventProc = nullptr) const override;
+
+ bool asyncExpose() const override;
+ void setAsyncExpose(bool value) override;
+
+ QVariant gpu() const override;
+ QVariant gpuList() const override;
+
+ void populateLightSystemPalette(QPalette &palette) const override;
+
+private:
+ WindowActivationBehavior m_windowActivationBehavior = DefaultActivateWindow;
+ TouchWindowTouchTypes m_touchWindowTouchTypes = NormalTouch;
+ DarkModeHandling m_darkModeHandling;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSAPPLICATION_H
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
index bd7bdc55d1..07918f6094 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsbackingstore.h"
#include "qwindowswindow.h"
@@ -43,7 +7,7 @@
#include <QtGui/qwindow.h>
#include <QtGui/qpainter.h>
-#include <QtFontDatabaseSupport/private/qwindowsnativeimage_p.h>
+#include <QtGui/private/qwindowsnativeimage_p.h>
#include <private/qhighdpiscaling_p.h>
#include <private/qimage_p.h>
@@ -55,7 +19,6 @@ QT_BEGIN_NAMESPACE
\class QWindowsBackingStore
\brief Backing store for windows.
\internal
- \ingroup qt-lighthouse-win
*/
QWindowsBackingStore::QWindowsBackingStore(QWindow *window) :
@@ -92,9 +55,8 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion &region,
if ((flags & Qt::FramelessWindowHint) && QWindowsWindow::setWindowLayered(rw->handle(), flags, hasAlpha, rw->opacity()) && hasAlpha) {
// Windows with alpha: Use blend function to update.
QRect r = QHighDpi::toNativePixels(window->frameGeometry(), window);
- QPoint frameOffset(QHighDpi::toNativePixels(QPoint(window->frameMargins().left(), window->frameMargins().top()),
- static_cast<const QWindow *>(nullptr)));
- QRect dirtyRect = br.translated(offset + frameOffset);
+ QMargins frameMargins = rw->frameMargins();
+ QRect dirtyRect = br.translated(offset + QPoint(frameMargins.left(), frameMargins.top()));
SIZE size = {r.width(), r.height()};
POINT ptDst = {r.x(), r.y()};
@@ -155,7 +117,7 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion &region)
if (QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha)
m_alphaNeedsFill = true;
else // upgrade but here we know app painting does not rely on alpha hence no need to fill
- format = qt_maybeAlphaVersionWithSameDepth(format);
+ format = qt_maybeDataCompatibleAlphaVersion(format);
QWindowsNativeImage *oldwni = m_image.data();
auto *newwni = new QWindowsNativeImage(size.width(), size.height(), format);
@@ -184,8 +146,8 @@ bool QWindowsBackingStore::scroll(const QRegion &area, int dx, int dy)
return false;
const QPoint offset(dx, dy);
- for (const QRect &rect : area)
- qt_scrollRectInImage(m_image->image(), rect, offset);
+ const QRect rect = area.boundingRect();
+ qt_scrollRectInImage(m_image->image(), rect, offset);
return true;
}
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.h b/src/plugins/platforms/windows/qwindowsbackingstore.h
index b96c8f0e61..186123b38e 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.h
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSBACKINGSTORE_H
#define QWINDOWSBACKINGSTORE_H
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp
index 4e6d3306e1..7a6d41e0b3 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.cpp
+++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp
@@ -1,46 +1,9 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsclipboard.h"
#include "qwindowscontext.h"
#include "qwindowsole.h"
-#include "qwindowsmime.h"
#include <QtGui/qguiapplication.h>
#include <QtGui/qclipboard.h>
@@ -53,8 +16,9 @@
#include <QtCore/qthread.h>
#include <QtCore/qvariant.h>
#include <QtCore/qurl.h>
+#include <QtCore/private/qsystemerror_p.h>
-#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
+#include <QtGui/private/qwindowsguieventdispatcher_p.h>
QT_BEGIN_NAMESPACE
@@ -71,7 +35,6 @@ QT_BEGIN_NAMESPACE
\note The OLE-functions used in this class require OleInitialize().
\internal
- \ingroup qt-lighthouse-win
*/
#ifndef QT_NO_DEBUG_STREAM
@@ -82,7 +45,7 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData)
d << "QMimeData(";
if (mimeData) {
const QStringList formats = mimeData->formats();
- d << "formats=" << formats.join(QLatin1String(", "));
+ d << "formats=" << formats.join(u", ");
if (mimeData->hasText())
d << ", text=" << mimeData->text();
if (mimeData->hasHtml())
@@ -110,7 +73,6 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData)
\sa QWindowsInternalMimeDataBase, QWindowsClipboard
\internal
- \ingroup qt-lighthouse-win
*/
IDataObject *QWindowsClipboardRetrievalMimeData::retrieveDataObject() const
@@ -190,15 +152,12 @@ void QWindowsClipboard::releaseIData()
void QWindowsClipboard::registerViewer()
{
m_clipboardViewer = QWindowsContext::instance()->
- createDummyWindow(QStringLiteral("Qt5ClipboardView"), L"Qt5ClipboardView",
+ createDummyWindow(QStringLiteral("ClipboardView"), L"QtClipboardView",
qClipboardViewerWndProc, WS_OVERLAPPED);
- // Try format listener API (Vista onwards) first.
- if (QWindowsContext::user32dll.addClipboardFormatListener && QWindowsContext::user32dll.removeClipboardFormatListener) {
- m_formatListenerRegistered = QWindowsContext::user32dll.addClipboardFormatListener(m_clipboardViewer);
- if (!m_formatListenerRegistered)
- qErrnoWarning("AddClipboardFormatListener() failed.");
- }
+ m_formatListenerRegistered = AddClipboardFormatListener(m_clipboardViewer);
+ if (!m_formatListenerRegistered)
+ qErrnoWarning("AddClipboardFormatListener() failed.");
if (!m_formatListenerRegistered)
m_nextClipboardViewer = SetClipboardViewer(m_clipboardViewer);
@@ -212,7 +171,7 @@ void QWindowsClipboard::unregisterViewer()
{
if (m_clipboardViewer) {
if (m_formatListenerRegistered) {
- QWindowsContext::user32dll.removeClipboardFormatListener(m_clipboardViewer);
+ RemoveClipboardFormatListener(m_clipboardViewer);
m_formatListenerRegistered = false;
} else {
ChangeClipboardChain(m_clipboardViewer, m_nextClipboardViewer);
@@ -339,10 +298,10 @@ void QWindowsClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode)
if (src != S_OK) {
QString mimeDataFormats = mimeData ?
- mimeData->formats().join(QLatin1String(", ")) : QString(QStringLiteral("NULL"));
+ mimeData->formats().join(u", ") : QString(QStringLiteral("NULL"));
qErrnoWarning("OleSetClipboard: Failed to set mime data (%s) on clipboard: %s",
qPrintable(mimeDataFormats),
- QWindowsContext::comErrorString(src).constData());
+ qPrintable(QSystemError::windowsComString(src)));
releaseIData();
return;
}
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.h b/src/plugins/platforms/windows/qwindowsclipboard.h
index 24a6bc908d..9713dccf9b 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.h
+++ b/src/plugins/platforms/windows/qwindowsclipboard.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSCLIPBOARD_H
#define QWINDOWSCLIPBOARD_H
diff --git a/src/plugins/platforms/windows/qwindowscombase.h b/src/plugins/platforms/windows/qwindowscombase.h
deleted file mode 100644
index 45cba9c68b..0000000000
--- a/src/plugins/platforms/windows/qwindowscombase.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
-
-#ifndef QWINDOWSCOMBASE_H
-#define QWINDOWSCOMBASE_H
-
-#include <QtCore/qglobal.h>
-
-#include <unknwn.h>
-
-QT_BEGIN_NAMESPACE
-
-// The __uuidof operator of MinGW does not work for all interfaces (for example,
-// IAccessible2). Specializations of this function can be provides to work
-// around this.
-template <class DesiredInterface>
-static IID qUuidOf() { return __uuidof(DesiredInterface); }
-
-// Helper for implementing IUnknown::QueryInterface.
-template <class DesiredInterface, class Derived>
-bool qWindowsComQueryInterface(Derived *d, REFIID id, LPVOID *iface)
-{
- if (id == qUuidOf<DesiredInterface>()) {
- *iface = static_cast<DesiredInterface *>(d);
- d->AddRef();
- return true;
- }
- return false;
-}
-
-// Helper for implementing IUnknown::QueryInterface for IUnknown
-// in the case of multiple inheritance via the first inherited class.
-template <class FirstInheritedInterface, class Derived>
-bool qWindowsComQueryUnknownInterfaceMulti(Derived *d, REFIID id, LPVOID *iface)
-{
- if (id == __uuidof(IUnknown)) {
- *iface = static_cast<FirstInheritedInterface *>(d);
- d->AddRef();
- return true;
- }
- return false;
-}
-
-// Helper base class to provide IUnknown methods for COM classes (single inheritance)
-template <class ComInterface> class QWindowsComBase : public ComInterface
-{
- Q_DISABLE_COPY_MOVE(QWindowsComBase)
-public:
- explicit QWindowsComBase(ULONG initialRefCount = 1) : m_ref(initialRefCount) {}
- virtual ~QWindowsComBase() = default;
-
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface)
- {
- *iface = nullptr;
- return qWindowsComQueryInterface<IUnknown>(this, id, iface) || qWindowsComQueryInterface<ComInterface>(this, id, iface)
- ? S_OK : E_NOINTERFACE;
- }
-
- ULONG STDMETHODCALLTYPE AddRef() { return ++m_ref; }
-
- ULONG STDMETHODCALLTYPE Release()
- {
- if (!--m_ref) {
- delete this;
- return 0;
- }
- return m_ref;
- }
-
-private:
- ULONG m_ref;
-};
-
-QT_END_NAMESPACE
-
-#endif // QWINDOWSCOMBASE_H
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index a2dd25f8cc..de65a2171d 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -1,52 +1,17 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowscontext.h"
#include "qwindowsintegration.h"
#include "qwindowswindow.h"
#include "qwindowskeymapper.h"
+#include "qwindowsnativeinterface.h"
#include "qwindowsmousehandler.h"
#include "qwindowspointerhandler.h"
#include "qtwindowsglobal.h"
#include "qwindowsmenu.h"
-#include "qwindowsmime.h"
+#include "qwindowsmimeregistry.h"
#include "qwindowsinputcontext.h"
#if QT_CONFIG(tabletevent)
# include "qwindowstabletsupport.h"
@@ -69,30 +34,37 @@
#include <qpa/qplatformnativeinterface.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qopenglcontext.h>
+#include <QtGui/qpointingdevice.h>
#include <QtCore/qset.h>
#include <QtCore/qhash.h>
+#include <QtCore/qlibraryinfo.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdebug.h>
-#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/qsysinfo.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/quuid.h>
-#include <QtCore/private/qsystemlibrary_p.h>
#include <QtCore/private/qwinregistry_p.h>
+#if QT_CONFIG(cpp_winrt)
+# include <QtCore/private/qfactorycacheregistration_p.h>
+#endif
+#include <QtCore/private/qsystemerror_p.h>
-#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
+#include <QtGui/private/qwindowsguieventdispatcher_p.h>
+#include <QtGui/private/qwindowsthemecache_p.h>
#include <stdlib.h>
#include <stdio.h>
#include <windowsx.h>
-#include <comdef.h>
#include <dbt.h>
#include <wtsapi32.h>
+#include <shellscalingapi.h>
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(lcQpaWindows, "qt.qpa.windows")
+using namespace Qt::StringLiterals;
+
+Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window")
Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events")
Q_LOGGING_CATEGORY(lcQpaGl, "qt.qpa.gl")
Q_LOGGING_CATEGORY(lcQpaMime, "qt.qpa.mime")
@@ -103,6 +75,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
Q_LOGGING_CATEGORY(lcQpaAccessibility, "qt.qpa.accessibility")
Q_LOGGING_CATEGORY(lcQpaUiAutomation, "qt.qpa.uiautomation")
Q_LOGGING_CATEGORY(lcQpaTrayIcon, "qt.qpa.trayicon")
+Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen")
int QWindowsContext::verbose = 0;
@@ -148,98 +121,6 @@ static inline bool sessionManagerInteractionBlocked()
static inline bool sessionManagerInteractionBlocked() { return false; }
#endif
-static inline int windowDpiAwareness(HWND hwnd)
-{
- return QWindowsContext::user32dll.getWindowDpiAwarenessContext && QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext
- ? QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext(QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd))
- : -1;
-}
-
-// Note: This only works within WM_NCCREATE
-static bool enableNonClientDpiScaling(HWND hwnd)
-{
- bool result = false;
- if (QWindowsContext::user32dll.enableNonClientDpiScaling && windowDpiAwareness(hwnd) == 2) {
- result = QWindowsContext::user32dll.enableNonClientDpiScaling(hwnd) != FALSE;
- if (!result) {
- const DWORD errorCode = GetLastError();
- qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
- hwnd, errorCode);
- }
- }
- return result;
-}
-
-/*!
- \class QWindowsUser32DLL
- \brief Struct that contains dynamically resolved symbols of User32.dll.
-
- The stub libraries shipped with the MinGW compiler miss some of the
- functions. They need to be retrieved dynamically.
-
- In addition, touch-related functions are available only from Windows onwards.
- These need to resolved dynamically for Q_CC_MSVC as well.
-
- \sa QWindowsShell32DLL
-
- \internal
- \ingroup qt-lighthouse-win
-*/
-
-void QWindowsUser32DLL::init()
-{
- QSystemLibrary library(QStringLiteral("user32"));
- setProcessDPIAware = (SetProcessDPIAware)library.resolve("SetProcessDPIAware");
-
- addClipboardFormatListener = (AddClipboardFormatListener)library.resolve("AddClipboardFormatListener");
- removeClipboardFormatListener = (RemoveClipboardFormatListener)library.resolve("RemoveClipboardFormatListener");
-
- getDisplayAutoRotationPreferences = (GetDisplayAutoRotationPreferences)library.resolve("GetDisplayAutoRotationPreferences");
- setDisplayAutoRotationPreferences = (SetDisplayAutoRotationPreferences)library.resolve("SetDisplayAutoRotationPreferences");
-
- if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8) {
- enableMouseInPointer = (EnableMouseInPointer)library.resolve("EnableMouseInPointer");
- getPointerType = (GetPointerType)library.resolve("GetPointerType");
- getPointerInfo = (GetPointerInfo)library.resolve("GetPointerInfo");
- getPointerDeviceRects = (GetPointerDeviceRects)library.resolve("GetPointerDeviceRects");
- getPointerTouchInfo = (GetPointerTouchInfo)library.resolve("GetPointerTouchInfo");
- getPointerFrameTouchInfo = (GetPointerFrameTouchInfo)library.resolve("GetPointerFrameTouchInfo");
- getPointerFrameTouchInfoHistory = (GetPointerFrameTouchInfoHistory)library.resolve("GetPointerFrameTouchInfoHistory");
- getPointerPenInfo = (GetPointerPenInfo)library.resolve("GetPointerPenInfo");
- getPointerPenInfoHistory = (GetPointerPenInfoHistory)library.resolve("GetPointerPenInfoHistory");
- skipPointerFrameMessages = (SkipPointerFrameMessages)library.resolve("SkipPointerFrameMessages");
- }
-
- if (QOperatingSystemVersion::current()
- >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 14393)) {
- adjustWindowRectExForDpi = (AdjustWindowRectExForDpi)library.resolve("AdjustWindowRectExForDpi");
- enableNonClientDpiScaling = (EnableNonClientDpiScaling)library.resolve("EnableNonClientDpiScaling");
- getWindowDpiAwarenessContext = (GetWindowDpiAwarenessContext)library.resolve("GetWindowDpiAwarenessContext");
- getAwarenessFromDpiAwarenessContext = (GetAwarenessFromDpiAwarenessContext)library.resolve("GetAwarenessFromDpiAwarenessContext");
- systemParametersInfoForDpi = (SystemParametersInfoForDpi)library.resolve("SystemParametersInfoForDpi");
- }
-}
-
-bool QWindowsUser32DLL::supportsPointerApi()
-{
- return enableMouseInPointer && getPointerType && getPointerInfo && getPointerDeviceRects
- && getPointerTouchInfo && getPointerFrameTouchInfo && getPointerFrameTouchInfoHistory
- && getPointerPenInfo && getPointerPenInfoHistory && skipPointerFrameMessages;
-}
-
-void QWindowsShcoreDLL::init()
-{
- if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1)
- return;
- QSystemLibrary library(QStringLiteral("SHCore"));
- getProcessDpiAwareness = (GetProcessDpiAwareness)library.resolve("GetProcessDpiAwareness");
- setProcessDpiAwareness = (SetProcessDpiAwareness)library.resolve("SetProcessDpiAwareness");
- getDpiForMonitor = (GetDpiForMonitor)library.resolve("GetDpiForMonitor");
-}
-
-QWindowsUser32DLL QWindowsContext::user32dll;
-QWindowsShcoreDLL QWindowsContext::shcoredll;
-
QWindowsContext *QWindowsContext::m_instance = nullptr;
/*!
@@ -249,23 +130,20 @@ QWindowsContext *QWindowsContext::m_instance = nullptr;
Holds state information formerly stored in \c qapplication_win.cpp.
\internal
- \ingroup qt-lighthouse-win
*/
-typedef QHash<HWND, QWindowsWindow *> HandleBaseWindowHash;
-
struct QWindowsContextPrivate {
QWindowsContextPrivate();
unsigned m_systemInfo = 0;
QSet<QString> m_registeredWindowClassNames;
- HandleBaseWindowHash m_windows;
+ QWindowsContext::HandleBaseWindowHash m_windows;
HDC m_displayContext = nullptr;
int m_defaultDPI = 96;
QWindowsKeyMapper m_keyMapper;
QWindowsMouseHandler m_mouseHandler;
QWindowsPointerHandler m_pointerHandler;
- QWindowsMimeConverter m_mimeConverter;
+ QWindowsMimeRegistry m_mimeConverter;
QWindowsScreenManager m_screenManager;
QSharedPointer<QWindowCreationContext> m_creationContext;
#if QT_CONFIG(tabletevent)
@@ -276,14 +154,14 @@ struct QWindowsContextPrivate {
bool m_asyncExpose = false;
HPOWERNOTIFY m_powerNotification = nullptr;
HWND m_powerDummyWindow = nullptr;
+ static bool m_v2DpiAware;
};
+bool QWindowsContextPrivate::m_v2DpiAware = false;
+
QWindowsContextPrivate::QWindowsContextPrivate()
: m_oleInitializeResult(OleInitialize(nullptr))
{
- QWindowsContext::user32dll.init();
- QWindowsContext::shcoredll.init();
-
if (m_pointerHandler.touchDevice() || m_mouseHandler.touchDevice())
m_systemInfo |= QWindowsContext::SI_SupportsTouch;
m_displayContext = GetDC(nullptr);
@@ -294,7 +172,7 @@ QWindowsContextPrivate::QWindowsContextPrivate()
}
if (FAILED(m_oleInitializeResult)) {
qWarning() << "QWindowsContext: OleInitialize() failed: "
- << QWindowsContext::comErrorString(m_oleInitializeResult);
+ << QSystemError::windowsComString(m_oleInitializeResult);
}
}
@@ -324,8 +202,12 @@ QWindowsContext::~QWindowsContext()
DestroyWindow(d->m_powerDummyWindow);
unregisterWindowClasses();
- if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE)
+ if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE) {
+#ifdef QT_USE_FACTORY_CACHE_REGISTRATION
+ detail::QWinRTFactoryCacheRegistration::clearAllCaches();
+#endif
OleUninitialize();
+ }
d->m_screenManager.clearScreens(); // Order: Potentially calls back to the windows.
if (d->m_displayContext)
@@ -342,33 +224,50 @@ bool QWindowsContext::initTouch(unsigned integrationOptions)
{
if (d->m_systemInfo & QWindowsContext::SI_SupportsTouch)
return true;
-
- QTouchDevice *touchDevice = (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) ?
- d->m_pointerHandler.ensureTouchDevice() : d->m_mouseHandler.ensureTouchDevice();
- if (!touchDevice)
+ const bool usePointerHandler = (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) != 0;
+ auto touchDevice = usePointerHandler ? d->m_pointerHandler.touchDevice() : d->m_mouseHandler.touchDevice();
+ if (touchDevice.isNull()) {
+ const bool mouseEmulation =
+ (integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch) == 0;
+ touchDevice = QWindowsPointerHandler::createTouchDevice(mouseEmulation);
+ }
+ if (touchDevice.isNull())
return false;
-
- if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch))
- touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation);
-
- QWindowSystemInterface::registerTouchDevice(touchDevice);
+ d->m_pointerHandler.setTouchDevice(touchDevice);
+ d->m_mouseHandler.setTouchDevice(touchDevice);
+ QWindowSystemInterface::registerInputDevice(touchDevice.data());
d->m_systemInfo |= QWindowsContext::SI_SupportsTouch;
// A touch device was plugged while the app is running. Register all windows for touch.
- if (QGuiApplicationPrivate::is_app_running) {
- for (QWindowsWindow *w : qAsConst(d->m_windows))
+ registerTouchWindows();
+
+ return true;
+}
+
+void QWindowsContext::registerTouchWindows()
+{
+ if (QGuiApplicationPrivate::is_app_running
+ && (d->m_systemInfo & QWindowsContext::SI_SupportsTouch) != 0) {
+ for (QWindowsWindow *w : std::as_const(d->m_windows))
w->registerTouchWindow();
}
+}
+bool QWindowsContext::initTablet()
+{
+#if QT_CONFIG(tabletevent)
+ d->m_tabletSupport.reset(QWindowsTabletSupport::create());
return true;
+#else
+ return false;
+#endif
}
-bool QWindowsContext::initTablet(unsigned integrationOptions)
+bool QWindowsContext::disposeTablet()
{
- Q_UNUSED(integrationOptions);
#if QT_CONFIG(tabletevent)
- d->m_tabletSupport.reset(QWindowsTabletSupport::create());
+ d->m_tabletSupport.reset();
return true;
#else
return false;
@@ -380,12 +279,6 @@ bool QWindowsContext::initPointer(unsigned integrationOptions)
if (integrationOptions & QWindowsIntegration::DontUseWMPointer)
return false;
- if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8)
- return false;
-
- if (!QWindowsContext::user32dll.supportsPointerApi())
- return false;
-
d->m_systemInfo |= QWindowsContext::SI_SupportsPointer;
return true;
}
@@ -426,7 +319,7 @@ bool QWindowsContext::initPowerNotificationHandler()
if (d->m_powerNotification)
return false;
- d->m_powerDummyWindow = createDummyWindow(QStringLiteral("QtPowerDummyWindow"), L"QtPowerDummyWindow", qWindowsPowerWindowProc);
+ d->m_powerDummyWindow = createDummyWindow(QStringLiteral("PowerDummyWindow"), L"QtPowerDummyWindow", qWindowsPowerWindowProc);
if (!d->m_powerDummyWindow)
return false;
@@ -442,10 +335,9 @@ bool QWindowsContext::initPowerNotificationHandler()
void QWindowsContext::setTabletAbsoluteRange(int a)
{
#if QT_CONFIG(tabletevent)
- if (!d->m_tabletSupport.isNull())
- d->m_tabletSupport->setAbsoluteRange(a);
+ QWindowsTabletSupport::setAbsoluteRange(a);
#else
- Q_UNUSED(a)
+ Q_UNUSED(a);
#endif
}
@@ -454,34 +346,119 @@ void QWindowsContext::setDetectAltGrModifier(bool a)
d->m_keyMapper.setDetectAltGrModifier(a);
}
-int QWindowsContext::processDpiAwareness()
+[[nodiscard]] static inline QtWindows::DpiAwareness
+ dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT context)
+{
+ // IsValidDpiAwarenessContext() will handle the NULL pointer case.
+ if (!IsValidDpiAwarenessContext(context))
+ return QtWindows::DpiAwareness::Invalid;
+ if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
+ return QtWindows::DpiAwareness::Unaware_GdiScaled;
+ if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
+ return QtWindows::DpiAwareness::PerMonitorVersion2;
+ if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
+ return QtWindows::DpiAwareness::PerMonitor;
+ if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
+ return QtWindows::DpiAwareness::System;
+ if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
+ return QtWindows::DpiAwareness::Unaware;
+ return QtWindows::DpiAwareness::Invalid;
+}
+
+QtWindows::DpiAwareness QWindowsContext::windowDpiAwareness(HWND hwnd)
+{
+ if (!hwnd)
+ return QtWindows::DpiAwareness::Invalid;
+ const auto context = GetWindowDpiAwarenessContext(hwnd);
+ return dpiAwarenessContextToQtDpiAwareness(context);
+}
+
+QtWindows::DpiAwareness QWindowsContext::processDpiAwareness()
+{
+ // Although we have GetDpiAwarenessContextForProcess(), however,
+ // it's only available on Win10 1903+, which is a little higher
+ // than Qt's minimum supported version (1809), so we can't use it.
+ // Luckily, MS docs said GetThreadDpiAwarenessContext() will also
+ // return the default DPI_AWARENESS_CONTEXT for the process if
+ // SetThreadDpiAwarenessContext() was never called. So we can use
+ // it as an equivalent.
+ const auto context = GetThreadDpiAwarenessContext();
+ return dpiAwarenessContextToQtDpiAwareness(context);
+}
+
+[[nodiscard]] static inline DPI_AWARENESS_CONTEXT
+ qtDpiAwarenessToDpiAwarenessContext(QtWindows::DpiAwareness dpiAwareness)
+{
+ switch (dpiAwareness) {
+ case QtWindows::DpiAwareness::Invalid:
+ return nullptr;
+ case QtWindows::DpiAwareness::Unaware:
+ return DPI_AWARENESS_CONTEXT_UNAWARE;
+ case QtWindows::DpiAwareness::System:
+ return DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
+ case QtWindows::DpiAwareness::PerMonitor:
+ return DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE;
+ case QtWindows::DpiAwareness::PerMonitorVersion2:
+ return DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
+ case QtWindows::DpiAwareness::Unaware_GdiScaled:
+ return DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED;
+ }
+ return nullptr;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, QtWindows::DpiAwareness dpiAwareness)
{
- int result;
- if (QWindowsContext::shcoredll.getProcessDpiAwareness
- && SUCCEEDED(QWindowsContext::shcoredll.getProcessDpiAwareness(nullptr, &result))) {
- return result;
+ const QDebugStateSaver saver(d);
+ QString message = u"QtWindows::DpiAwareness::"_s;
+ switch (dpiAwareness) {
+ case QtWindows::DpiAwareness::Invalid:
+ message += u"Invalid"_s;
+ break;
+ case QtWindows::DpiAwareness::Unaware:
+ message += u"Unaware"_s;
+ break;
+ case QtWindows::DpiAwareness::System:
+ message += u"System"_s;
+ break;
+ case QtWindows::DpiAwareness::PerMonitor:
+ message += u"PerMonitor"_s;
+ break;
+ case QtWindows::DpiAwareness::PerMonitorVersion2:
+ message += u"PerMonitorVersion2"_s;
+ break;
+ case QtWindows::DpiAwareness::Unaware_GdiScaled:
+ message += u"Unaware_GdiScaled"_s;
+ break;
}
- return -1;
+ d.nospace().noquote() << message;
+ return d;
}
+#endif
-void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness)
+bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwareness)
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << dpiAwareness;
- if (QWindowsContext::shcoredll.isValid()) {
- const HRESULT hr = QWindowsContext::shcoredll.setProcessDpiAwareness(dpiAwareness);
- // E_ACCESSDENIED means set externally (MSVC manifest or external app loading Qt plugin).
- // Silence warning in that case unless debug is enabled.
- if (FAILED(hr) && (hr != E_ACCESSDENIED || lcQpaWindows().isDebugEnabled())) {
- qWarning().noquote().nospace() << "SetProcessDpiAwareness("
- << dpiAwareness << ") failed: " << QWindowsContext::comErrorString(hr)
- << ", using " << QWindowsContext::processDpiAwareness();
- }
- } else {
- if (dpiAwareness != QtWindows::ProcessDpiUnaware && QWindowsContext::user32dll.setProcessDPIAware) {
- if (!QWindowsContext::user32dll.setProcessDPIAware())
- qErrnoWarning("SetProcessDPIAware() failed");
- }
+ qCDebug(lcQpaWindow) << __FUNCTION__ << dpiAwareness;
+ if (processDpiAwareness() == dpiAwareness)
+ return true;
+ const auto context = qtDpiAwarenessToDpiAwarenessContext(dpiAwareness);
+ if (!IsValidDpiAwarenessContext(context)) {
+ qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
+ return false;
+ }
+ if (!SetProcessDpiAwarenessContext(context)) {
+ qCWarning(lcQpaWindow).noquote().nospace()
+ << "SetProcessDpiAwarenessContext() failed: "
+ << QSystemError::windowsString()
+ << "\nQt's default DPI awareness context is "
+ << "DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2. If you know what you "
+ << "are doing, you can overwrite this default using qt.conf "
+ << "(https://doc.qt.io/qt-6/highdpi.html#configuring-windows).";
+ return false;
}
+ QWindowsContextPrivate::m_v2DpiAware
+ = processDpiAwareness() == QtWindows::DpiAwareness::PerMonitorVersion2;
+ return true;
}
QWindowsContext *QWindowsContext::instance()
@@ -499,9 +476,14 @@ bool QWindowsContext::useRTLExtensions() const
return d->m_keyMapper.useRTLExtensions();
}
-QList<int> QWindowsContext::possibleKeys(const QKeyEvent *e) const
+QPlatformKeyMapper *QWindowsContext::keyMapper() const
+{
+ return &d->m_keyMapper;
+}
+
+QWindowsContext::HandleBaseWindowHash &QWindowsContext::windows()
{
- return d->m_keyMapper.possibleKeys(e);
+ return d->m_windows;
}
QSharedPointer<QWindowCreationContext> QWindowsContext::setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx)
@@ -536,6 +518,25 @@ void QWindowsContext::setKeyGrabber(QWindow *w)
d->m_keyMapper.setKeyGrabber(w);
}
+QString QWindowsContext::classNamePrefix()
+{
+ static QString result;
+ if (result.isEmpty()) {
+ QTextStream str(&result);
+ str << "Qt" << QT_VERSION_MAJOR << QT_VERSION_MINOR << QT_VERSION_PATCH;
+ if (QLibraryInfo::isDebugBuild())
+ str << 'd';
+#ifdef QT_NAMESPACE
+# define xstr(s) str(s)
+# define str(s) #s
+ str << xstr(QT_NAMESPACE);
+# undef str
+# undef xstr
+#endif
+ }
+ return result;
+}
+
// Window class registering code (from qapplication_win.cpp)
QString QWindowsContext::registerWindowClass(const QWindow *w)
@@ -567,31 +568,31 @@ QString QWindowsContext::registerWindowClass(const QWindow *w)
break;
}
// Create a unique name for the flag combination
- QString cname;
- cname += QLatin1String("Qt5QWindow");
+ QString cname = classNamePrefix();
+ cname += "QWindow"_L1;
switch (type) {
case Qt::Tool:
- cname += QLatin1String("Tool");
+ cname += "Tool"_L1;
break;
case Qt::ToolTip:
- cname += QLatin1String("ToolTip");
+ cname += "ToolTip"_L1;
break;
case Qt::Popup:
- cname += QLatin1String("Popup");
+ cname += "Popup"_L1;
break;
default:
break;
}
if (style & CS_DROPSHADOW)
- cname += QLatin1String("DropShadow");
+ cname += "DropShadow"_L1;
if (style & CS_SAVEBITS)
- cname += QLatin1String("SaveBits");
+ cname += "SaveBits"_L1;
if (style & CS_OWNDC)
- cname += QLatin1String("OwnDC");
+ cname += "OwnDC"_L1;
if (icon)
- cname += QLatin1String("Icon");
+ cname += "Icon"_L1;
- return registerWindowClass(cname, qWindowsWndProc, style, GetSysColorBrush(COLOR_WINDOW), icon);
+ return registerWindowClass(cname, qWindowsWndProc, style, nullptr, icon);
}
QString QWindowsContext::registerWindowClass(QString cname,
@@ -604,15 +605,13 @@ QString QWindowsContext::registerWindowClass(QString cname,
// each one has to have window class names with a unique name
// The first instance gets the unmodified name; if the class
// has already been registered by another instance of Qt then
- // add a UUID.
- static int classExists = -1;
-
+ // add a UUID. The check needs to be performed for each name
+ // in case new message windows are added (QTBUG-81347).
+ // Note: GetClassInfo() returns != 0 when a class exists.
const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
- if (classExists == -1) {
- WNDCLASS wcinfo;
- classExists = GetClassInfo(appInstance, reinterpret_cast<LPCWSTR>(cname.utf16()), &wcinfo);
- classExists = classExists && wcinfo.lpfnWndProc != proc;
- }
+ WNDCLASS wcinfo;
+ const bool classExists = GetClassInfo(appInstance, reinterpret_cast<LPCWSTR>(cname.utf16()), &wcinfo) != FALSE
+ && wcinfo.lpfnWndProc != proc;
if (classExists)
cname += QUuid::createUuid().toString();
@@ -652,7 +651,7 @@ QString QWindowsContext::registerWindowClass(QString cname,
qPrintable(cname));
d->m_registeredWindowClassNames.insert(cname);
- qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << ' ' << cname
+ qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << ' ' << cname
<< " style=0x" << Qt::hex << style << Qt::dec
<< " brush=" << brush << " icon=" << icon << " atom=" << atom;
return cname;
@@ -662,7 +661,7 @@ void QWindowsContext::unregisterWindowClasses()
{
const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
- for (const QString &name : qAsConst(d->m_registeredWindowClassNames)) {
+ for (const QString &name : std::as_const(d->m_registeredWindowClassNames)) {
if (!UnregisterClass(reinterpret_cast<LPCWSTR>(name.utf16()), appInstance) && QWindowsContext::verbose)
qErrnoWarning("UnregisterClass failed for '%s'", qPrintable(name));
}
@@ -674,23 +673,6 @@ int QWindowsContext::screenDepth() const
return GetDeviceCaps(d->m_displayContext, BITSPIXEL);
}
-QString QWindowsContext::windowsErrorMessage(unsigned long errorCode)
-{
- QString rc = QString::fromLatin1("#%1: ").arg(errorCode);
- ushort *lpMsgBuf;
-
- const DWORD len = FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- nullptr, errorCode, 0, reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, nullptr);
- if (len) {
- rc = QString::fromUtf16(lpMsgBuf, int(len));
- LocalFree(lpMsgBuf);
- } else {
- rc += QString::fromLatin1("<unknown error>");
- }
- return rc;
-}
-
void QWindowsContext::addWindow(HWND hwnd, QWindowsWindow *w)
{
d->m_windows.insert(hwnd, w);
@@ -794,6 +776,8 @@ static inline bool findPlatformWindowHelper(const POINT &screenPoint, unsigned c
if (!(cwexFlags & CWP_SKIPTRANSPARENT)
&& (GetWindowLongPtr(child, GWL_EXSTYLE) & WS_EX_TRANSPARENT)) {
const HWND nonTransparentChild = ChildWindowFromPointEx(*hwnd, point, cwexFlags | CWP_SKIPTRANSPARENT);
+ if (!nonTransparentChild || nonTransparentChild == *hwnd)
+ return false;
if (QWindowsWindow *nonTransparentWindow = context->findPlatformWindow(nonTransparentChild)) {
*result = nonTransparentWindow;
*hwnd = nonTransparentChild;
@@ -851,7 +835,7 @@ bool QWindowsContext::isSessionLocked()
return result;
}
-QWindowsMimeConverter &QWindowsContext::mimeConverter() const
+QWindowsMimeRegistry &QWindowsContext::mimeConverter() const
{
return d->m_mimeConverter;
}
@@ -881,7 +865,7 @@ HWND QWindowsContext::createDummyWindow(const QString &classNameIn,
{
if (!wndProc)
wndProc = DefWindowProc;
- QString className = registerWindowClass(classNameIn, wndProc);
+ QString className = registerWindowClass(classNamePrefix() + classNameIn, wndProc);
return CreateWindowEx(0, reinterpret_cast<LPCWSTR>(className.utf16()),
windowName, style,
CW_USEDEFAULT, CW_USEDEFAULT,
@@ -889,103 +873,18 @@ HWND QWindowsContext::createDummyWindow(const QString &classNameIn,
HWND_MESSAGE, nullptr, static_cast<HINSTANCE>(GetModuleHandle(nullptr)), nullptr);
}
-// Re-engineered from the inline function _com_error::ErrorMessage().
-// We cannot use it directly since it uses swprintf_s(), which is not
-// present in the MSVCRT.DLL found on Windows XP (QTBUG-35617).
-static inline QString errorMessageFromComError(const _com_error &comError)
+void QWindowsContext::forceNcCalcSize(HWND hwnd)
{
- TCHAR *message = nullptr;
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- nullptr, DWORD(comError.Error()), MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
- message, 0, nullptr);
- if (message) {
- const QString result = QString::fromWCharArray(message).trimmed();
- LocalFree(static_cast<HLOCAL>(message));
- return result;
- }
- if (const WORD wCode = comError.WCode())
- return QString::asprintf("IDispatch error #%u", uint(wCode));
- return QString::asprintf("Unknown error 0x0%x", uint(comError.Error()));
-}
-
-/*!
- \brief Common COM error strings.
-*/
-
-QByteArray QWindowsContext::comErrorString(HRESULT hr)
-{
- QByteArray result = QByteArrayLiteral("COM error 0x")
- + QByteArray::number(quintptr(hr), 16) + ' ';
- switch (hr) {
- case S_OK:
- result += QByteArrayLiteral("S_OK");
- break;
- case S_FALSE:
- result += QByteArrayLiteral("S_FALSE");
- break;
- case E_UNEXPECTED:
- result += QByteArrayLiteral("E_UNEXPECTED");
- break;
- case E_ACCESSDENIED:
- result += QByteArrayLiteral("E_ACCESSDENIED");
- break;
- case CO_E_ALREADYINITIALIZED:
- result += QByteArrayLiteral("CO_E_ALREADYINITIALIZED");
- break;
- case CO_E_NOTINITIALIZED:
- result += QByteArrayLiteral("CO_E_NOTINITIALIZED");
- break;
- case RPC_E_CHANGED_MODE:
- result += QByteArrayLiteral("RPC_E_CHANGED_MODE");
- break;
- case OLE_E_WRONGCOMPOBJ:
- result += QByteArrayLiteral("OLE_E_WRONGCOMPOBJ");
- break;
- case CO_E_NOT_SUPPORTED:
- result += QByteArrayLiteral("CO_E_NOT_SUPPORTED");
- break;
- case E_NOTIMPL:
- result += QByteArrayLiteral("E_NOTIMPL");
- break;
- case E_INVALIDARG:
- result += QByteArrayLiteral("E_INVALIDARG");
- break;
- case E_NOINTERFACE:
- result += QByteArrayLiteral("E_NOINTERFACE");
- break;
- case E_POINTER:
- result += QByteArrayLiteral("E_POINTER");
- break;
- case E_HANDLE:
- result += QByteArrayLiteral("E_HANDLE");
- break;
- case E_ABORT:
- result += QByteArrayLiteral("E_ABORT");
- break;
- case E_FAIL:
- result += QByteArrayLiteral("E_FAIL");
- break;
- case RPC_E_WRONG_THREAD:
- result += QByteArrayLiteral("RPC_E_WRONG_THREAD");
- break;
- case RPC_E_THREAD_NOT_INIT:
- result += QByteArrayLiteral("RPC_E_THREAD_NOT_INIT");
- break;
- default:
- break;
- }
- _com_error error(hr);
- result += QByteArrayLiteral(" (");
- result += errorMessageFromComError(error);
- result += ')';
- return result;
+ // Force WM_NCCALCSIZE to adjust margin
+ SetWindowPos(hwnd, nullptr, 0, 0, 0, 0,
+ SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
}
bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out,
unsigned dpi)
{
- const BOOL result = QWindowsContext::user32dll.systemParametersInfoForDpi != nullptr && dpi != 0
- ? QWindowsContext::user32dll.systemParametersInfoForDpi(action, param, out, 0, dpi)
+ const BOOL result = dpi != 0
+ ? SystemParametersInfoForDpi(action, param, out, 0, dpi)
: SystemParametersInfo(action, param, out, 0);
return result == TRUE;
}
@@ -1026,31 +925,13 @@ static inline QWindowsInputContext *windowsInputContext()
return qobject_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
}
-
-// Child windows, fixed-size windows or pop-ups and similar should not be resized
-static inline bool resizeOnDpiChanged(const QWindow *w)
-{
- bool result = false;
- if (w->isTopLevel()) {
- switch (w->type()) {
- case Qt::Window:
- case Qt::Dialog:
- case Qt::Sheet:
- case Qt::Drawer:
- case Qt::Tool:
- result = !w->flags().testFlag(Qt::MSWindowsFixedSizeDialogHint);
- break;
- default:
- break;
- }
- }
- return result;
-}
-
bool QWindowsContext::shouldHaveNonClientDpiScaling(const QWindow *window)
{
- return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10
- && window->isTopLevel()
+ // DPI aware V2 processes always have NonClientDpiScaling enabled.
+ if (QWindowsContextPrivate::m_v2DpiAware)
+ return true;
+
+ return window->isTopLevel()
&& !window->property(QWindowsWindow::embeddedNativeParentHandleProperty).isValid()
#if QT_CONFIG(opengl) // /QTBUG-62901, EnableNonClientDpiScaling has problems with GL
&& (window->surfaceType() != QSurface::OpenGLSurface
@@ -1086,6 +967,21 @@ static inline bool isInputMessage(UINT m)
|| (m >= WM_KEYFIRST && m <= WM_KEYLAST);
}
+// Note: This only works within WM_NCCREATE
+static bool enableNonClientDpiScaling(HWND hwnd)
+{
+ bool result = false;
+ if (QWindowsContext::windowDpiAwareness(hwnd) == QtWindows::DpiAwareness::PerMonitor) {
+ result = EnableNonClientDpiScaling(hwnd) != FALSE;
+ if (!result) {
+ const DWORD errorCode = GetLastError();
+ qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
+ hwnd, errorCode);
+ }
+ }
+ return result;
+}
+
/*!
\brief Main windows procedure registered for windows.
@@ -1102,9 +998,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
MSG msg;
msg.hwnd = hwnd; // re-create MSG structure
- msg.message = message; // time and pt fields ignored
+ msg.message = message;
msg.wParam = wParam;
msg.lParam = lParam;
+ msg.time = GetMessageTime();
msg.pt.x = msg.pt.y = 0;
if (et != QtWindows::CursorEvent && (et & (QtWindows::MouseEventFlag | QtWindows::NonClientEventFlag))) {
msg.pt.x = GET_X_LPARAM(lParam);
@@ -1183,14 +1080,15 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
#else
return false;
#endif
- case QtWindows::DisplayChangedEvent:
- if (QWindowsTheme *t = QWindowsTheme::instance())
- t->displayChanged();
- QWindowsWindow::displayChanged();
- return d->m_screenManager.handleDisplayChange(wParam, lParam);
- case QtWindows::SettingChangedEvent:
+ case QtWindows::SettingChangedEvent: {
QWindowsWindow::settingsChanged();
+ // Only refresh the window theme if the user changes the personalize settings.
+ if ((wParam == 0) && (lParam != 0) // lParam sometimes may be NULL.
+ && (wcscmp(reinterpret_cast<LPCWSTR>(lParam), L"ImmersiveColorSet") == 0)) {
+ QWindowsTheme::handleSettingsChanged();
+ }
return d->m_screenManager.handleScreenChanges();
+ }
default:
break;
}
@@ -1204,14 +1102,18 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam));
return true;
case QtWindows::ResizeEvent:
- d->m_creationContext->obtainedSize = QSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ d->m_creationContext->obtainedSize = QSize(LOWORD(lParam), HIWORD(lParam));
return true;
case QtWindows::MoveEvent:
d->m_creationContext->obtainedPos = QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return true;
case QtWindows::NonClientCreate:
- if (shouldHaveNonClientDpiScaling(d->m_creationContext->window))
- enableNonClientDpiScaling(msg.hwnd);
+ if (shouldHaveNonClientDpiScaling(d->m_creationContext->window) &&
+ // DPI aware V2 processes always have NonClientDpiScaling enabled
+ // and there is no need to make an API call to manually enable.
+ !QWindowsContextPrivate::m_v2DpiAware) {
+ enableNonClientDpiScaling(msg.hwnd);
+ }
return false;
case QtWindows::CalculateSize:
return QWindowsGeometryHint::handleCalculateSize(d->m_creationContext->customMargins, msg, result);
@@ -1243,7 +1145,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
if (wParam == DBT_DEVNODES_CHANGED)
initTouch();
break;
- case QtWindows::KeyboardLayoutChangeEvent:
+ case QtWindows::InputLanguageChangeEvent:
if (QWindowsInputContext *wic = windowsInputContext())
wic->handleInputLanguageChanged(wParam, lParam);
Q_FALLTHROUGH();
@@ -1273,7 +1175,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
platformWindow->handleMoved();
return true;
case QtWindows::ResizeEvent:
- platformWindow->handleResized(static_cast<int>(wParam));
+ platformWindow->handleResized(static_cast<int>(wParam), lParam);
return true;
case QtWindows::QuerySizeHints:
platformWindow->getSizeHints(reinterpret_cast<MINMAXINFO *>(lParam));
@@ -1283,25 +1185,33 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::NonClientHitTest:
return platformWindow->handleNonClientHitTest(QPoint(msg.pt.x, msg.pt.y), result);
case QtWindows::GeometryChangingEvent:
- return platformWindow->QWindowsWindow::handleGeometryChanging(&msg);
+ return platformWindow->handleGeometryChanging(&msg);
case QtWindows::ExposeEvent:
- return platformWindow->handleWmPaint(hwnd, message, wParam, lParam);
+ return platformWindow->handleWmPaint(hwnd, message, wParam, lParam, result);
case QtWindows::NonClientMouseEvent:
- if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
+ if (!platformWindow->frameStrutEventsEnabled())
+ break;
+ if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
else
return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
case QtWindows::NonClientPointerEvent:
- if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
+ if (!platformWindow->frameStrutEventsEnabled())
+ break;
+ if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
break;
case QtWindows::EnterSizeMoveEvent:
platformWindow->setFlag(QWindowsWindow::ResizeMoveActive);
+ if (!IsZoomed(hwnd))
+ platformWindow->updateRestoreGeometry();
return true;
case QtWindows::ExitSizeMoveEvent:
platformWindow->clearFlag(QWindowsWindow::ResizeMoveActive);
platformWindow->checkForScreenChanged();
handleExitSizeMove(platformWindow->window());
+ if (!IsZoomed(hwnd))
+ platformWindow->updateRestoreGeometry();
return true;
case QtWindows::ScrollEvent:
if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
@@ -1347,6 +1257,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
QWindowSystemInterface::handleCloseEvent(platformWindow->window());
return true;
case QtWindows::ThemeChanged: {
+ QWindowsThemeCache::clearThemeCache(platformWindow->handle());
// Switch from Aero to Classic changes margins.
if (QWindowsTheme *theme = QWindowsTheme::instance())
theme->windowsThemeChanged(platformWindow->window());
@@ -1388,26 +1299,15 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return true;
#endif
} break;
- case QtWindows::DpiChangedEvent: {
- // Try to apply the suggested size first and then notify ScreenChanged
- // so that the resize event sent from QGuiApplication incorporates it
- // WM_DPICHANGED is sent with a size that avoids resize loops (by
- // snapping back to the previous screen, see QTBUG-65580).
- const bool doResize = resizeOnDpiChanged(platformWindow->window());
- if (doResize) {
- platformWindow->setFlag(QWindowsWindow::WithinDpiChanged);
- platformWindow->updateFullFrameMargins();
- const auto prcNewWindow = reinterpret_cast<RECT *>(lParam);
- qCDebug(lcQpaWindows) << __FUNCTION__ << "WM_DPICHANGED"
- << platformWindow->window() << *prcNewWindow;
- SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top,
- prcNewWindow->right - prcNewWindow->left,
- prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
- platformWindow->clearFlag(QWindowsWindow::WithinDpiChanged);
- }
- platformWindow->checkForScreenChanged(QWindowsWindow::FromDpiChange);
- return doResize;
- }
+ case QtWindows::DpiScaledSizeEvent:
+ platformWindow->handleDpiScaledSize(wParam, lParam, result);
+ return true;
+ case QtWindows::DpiChangedEvent:
+ platformWindow->handleDpiChanged(hwnd, wParam, lParam);
+ return true;
+ case QtWindows::DpiChangedAfterParentEvent:
+ platformWindow->handleDpiChangedAfterParent(hwnd);
+ return true;
#if QT_CONFIG(sessionmanager)
case QtWindows::QueryEndSessionApplicationEvent: {
QWindowsSessionManager *sessionManager = platformSessionManager();
@@ -1449,6 +1349,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return true;
}
#endif // !defined(QT_NO_SESSIONMANAGER)
+ case QtWindows::TaskbarButtonCreated:
+ // Apply application badge if this is the first time we have a taskbar
+ // button, or after Explorer restart.
+ QWindowsIntegration::instance()->updateApplicationBadge();
+ break;
default:
break;
}
@@ -1491,7 +1396,7 @@ void QWindowsContext::handleFocusEvent(QtWindows::WindowsEventType et,
}
if (nextActiveWindow != d->m_lastActiveWindow) {
d->m_lastActiveWindow = nextActiveWindow;
- QWindowSystemInterface::handleWindowActivated(nextActiveWindow);
+ QWindowSystemInterface::handleFocusWindowChanged(nextActiveWindow, Qt::ActiveWindowFocusReason);
}
}
@@ -1521,7 +1426,7 @@ bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg)
}
QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos,
- QWindowsKeyMapper::queryKeyboardModifiers());
+ keyMapper()->queryKeyboardModifiers());
return true;
}
#endif
@@ -1542,7 +1447,7 @@ void QWindowsContext::handleExitSizeMove(QWindow *window)
const Qt::MouseButtons appButtons = QGuiApplication::mouseButtons();
if (currentButtons == appButtons)
return;
- const Qt::KeyboardModifiers keyboardModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
+ const Qt::KeyboardModifiers keyboardModifiers = keyMapper()->queryKeyboardModifiers();
const QPoint globalPos = QWindowsCursor::mousePosition();
const QPlatformWindow *platWin = window->handle();
const QPoint localPos = platWin->mapFromGlobal(globalPos);
@@ -1551,8 +1456,7 @@ void QWindowsContext::handleExitSizeMove(QWindow *window)
for (Qt::MouseButton button : {Qt::LeftButton, Qt::RightButton, Qt::MiddleButton}) {
if (appButtons.testFlag(button) && !currentButtons.testFlag(button)) {
QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos,
- currentButtons, button, type,
- keyboardModifiers);
+ currentButtons, button, type, keyboardModifiers);
}
}
if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer)
@@ -1571,12 +1475,6 @@ void QWindowsContext::setAsyncExpose(bool value)
d->m_asyncExpose = value;
}
-QTouchDevice *QWindowsContext::touchDevice() const
-{
- return (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) ?
- d->m_pointerHandler.touchDevice() : d->m_mouseHandler.touchDevice();
-}
-
DWORD QWindowsContext::readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue)
{
const auto value =
@@ -1623,7 +1521,6 @@ static inline bool isTopLevel(HWND hwnd)
There is another one for timers, sockets, etc in
QEventDispatcherWin32.
- \ingroup qt-lighthouse-win
*/
extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
@@ -1653,7 +1550,7 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR
marginsFromRects(ncCalcSizeFrame, rectFromNcCalcSize(message, wParam, lParam, 0));
if (margins.left() >= 0) {
if (platformWindow) {
- qCDebug(lcQpaWindows) << __FUNCTION__ << "WM_NCCALCSIZE for" << hwnd << margins;
+ qCDebug(lcQpaWindow) << __FUNCTION__ << "WM_NCCALCSIZE for" << hwnd << margins;
platformWindow->setFullFrameMargins(margins);
} else {
const QSharedPointer<QWindowCreationContext> ctx = QWindowsContext::instance()->windowCreationContext();
@@ -1672,11 +1569,7 @@ static inline QByteArray nativeEventType() { return QByteArrayLiteral("windows_g
bool QWindowsContext::filterNativeEvent(MSG *msg, LRESULT *result)
{
QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance();
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
qintptr filterResult = 0;
-#else
- long filterResult = 0;
-#endif
if (dispatcher && dispatcher->filterNativeEvent(nativeEventType(), msg, &filterResult)) {
*result = LRESULT(filterResult);
return true;
@@ -1687,11 +1580,7 @@ bool QWindowsContext::filterNativeEvent(MSG *msg, LRESULT *result)
// Send to QWindowSystemInterface
bool QWindowsContext::filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result)
{
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
qintptr filterResult = 0;
-#else
- long filterResult = 0;
-#endif
if (QWindowSystemInterface::handleNativeEvent(window, nativeEventType(), msg, &filterResult)) {
*result = LRESULT(filterResult);
return true;
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index 8027f09389..0539a22afc 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSCONTEXT_H
#define QWINDOWSCONTEXT_H
@@ -51,12 +15,9 @@
#include <shlobj.h>
#include <shlwapi.h>
-struct IBindCtx;
-struct _SHSTOCKICONINFO;
-
QT_BEGIN_NAMESPACE
-Q_DECLARE_LOGGING_CATEGORY(lcQpaWindows)
+Q_DECLARE_LOGGING_CATEGORY(lcQpaWindow)
Q_DECLARE_LOGGING_CATEGORY(lcQpaEvents)
Q_DECLARE_LOGGING_CATEGORY(lcQpaGl)
Q_DECLARE_LOGGING_CATEGORY(lcQpaMime)
@@ -67,96 +28,27 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaTablet)
Q_DECLARE_LOGGING_CATEGORY(lcQpaAccessibility)
Q_DECLARE_LOGGING_CATEGORY(lcQpaUiAutomation)
Q_DECLARE_LOGGING_CATEGORY(lcQpaTrayIcon)
+Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
class QWindow;
class QPlatformScreen;
class QPlatformWindow;
+class QPlatformKeyMapper;
class QWindowsMenuBar;
class QWindowsScreenManager;
class QWindowsTabletSupport;
class QWindowsWindow;
-class QWindowsMimeConverter;
+class QWindowsMimeRegistry;
struct QWindowCreationContext;
struct QWindowsContextPrivate;
class QPoint;
class QKeyEvent;
-class QTouchDevice;
-
-struct QWindowsUser32DLL
-{
- inline void init();
- inline bool supportsPointerApi();
-
- typedef BOOL (WINAPI *EnableMouseInPointer)(BOOL);
- typedef BOOL (WINAPI *GetPointerType)(UINT32, PVOID);
- typedef BOOL (WINAPI *GetPointerInfo)(UINT32, PVOID);
- typedef BOOL (WINAPI *GetPointerDeviceRects)(HANDLE, RECT *, RECT *);
- typedef BOOL (WINAPI *GetPointerTouchInfo)(UINT32, PVOID);
- typedef BOOL (WINAPI *GetPointerFrameTouchInfo)(UINT32, UINT32 *, PVOID);
- typedef BOOL (WINAPI *GetPointerFrameTouchInfoHistory)(UINT32, UINT32 *, UINT32 *, PVOID);
- typedef BOOL (WINAPI *GetPointerPenInfo)(UINT32, PVOID);
- typedef BOOL (WINAPI *GetPointerPenInfoHistory)(UINT32, UINT32 *, PVOID);
- typedef BOOL (WINAPI *SkipPointerFrameMessages)(UINT32);
- typedef BOOL (WINAPI *SetProcessDPIAware)();
- typedef BOOL (WINAPI *AddClipboardFormatListener)(HWND);
- typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
- typedef BOOL (WINAPI *GetDisplayAutoRotationPreferences)(DWORD *);
- typedef BOOL (WINAPI *SetDisplayAutoRotationPreferences)(DWORD);
- typedef BOOL (WINAPI *AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
- typedef BOOL (WINAPI *EnableNonClientDpiScaling)(HWND);
- typedef int (WINAPI *GetWindowDpiAwarenessContext)(HWND);
- typedef int (WINAPI *GetAwarenessFromDpiAwarenessContext)(int);
- typedef BOOL (WINAPI *SystemParametersInfoForDpi)(UINT, UINT, PVOID, UINT, UINT);
-
- // Windows pointer functions (Windows 8 or later).
- EnableMouseInPointer enableMouseInPointer = nullptr;
- GetPointerType getPointerType = nullptr;
- GetPointerInfo getPointerInfo = nullptr;
- GetPointerDeviceRects getPointerDeviceRects = nullptr;
- GetPointerTouchInfo getPointerTouchInfo = nullptr;
- GetPointerFrameTouchInfo getPointerFrameTouchInfo = nullptr;
- GetPointerFrameTouchInfoHistory getPointerFrameTouchInfoHistory = nullptr;
- GetPointerPenInfo getPointerPenInfo = nullptr;
- GetPointerPenInfoHistory getPointerPenInfoHistory = nullptr;
- SkipPointerFrameMessages skipPointerFrameMessages = nullptr;
-
- // Windows Vista onwards
- SetProcessDPIAware setProcessDPIAware = nullptr;
-
- // Clipboard listeners are present on Windows Vista onwards
- // but missing in MinGW 4.9 stub libs. Can be removed in MinGW 5.
- AddClipboardFormatListener addClipboardFormatListener = nullptr;
- RemoveClipboardFormatListener removeClipboardFormatListener = nullptr;
-
- // Rotation API
- GetDisplayAutoRotationPreferences getDisplayAutoRotationPreferences = nullptr;
- SetDisplayAutoRotationPreferences setDisplayAutoRotationPreferences = nullptr;
-
- AdjustWindowRectExForDpi adjustWindowRectExForDpi = nullptr;
- EnableNonClientDpiScaling enableNonClientDpiScaling = nullptr;
- GetWindowDpiAwarenessContext getWindowDpiAwarenessContext = nullptr;
- GetAwarenessFromDpiAwarenessContext getAwarenessFromDpiAwarenessContext = nullptr;
- SystemParametersInfoForDpi systemParametersInfoForDpi = nullptr;
-};
-
-// Shell scaling library (Windows 8.1 onwards)
-struct QWindowsShcoreDLL {
- void init();
- inline bool isValid() const { return getProcessDpiAwareness && setProcessDpiAwareness && getDpiForMonitor; }
-
- typedef HRESULT (WINAPI *GetProcessDpiAwareness)(HANDLE,int *);
- typedef HRESULT (WINAPI *SetProcessDpiAwareness)(int);
- typedef HRESULT (WINAPI *GetDpiForMonitor)(HMONITOR,int,UINT *,UINT *);
-
- GetProcessDpiAwareness getProcessDpiAwareness = nullptr;
- SetProcessDpiAwareness setProcessDpiAwareness = nullptr;
- GetDpiForMonitor getDpiForMonitor = nullptr;
-};
-
+class QPointingDevice;
class QWindowsContext
{
Q_DISABLE_COPY_MOVE(QWindowsContext)
public:
+ using HandleBaseWindowHash = QHash<HWND, QWindowsWindow *>;
enum SystemInfoFlags
{
@@ -173,13 +65,16 @@ public:
bool initTouch();
bool initTouch(unsigned integrationOptions); // For calls from QWindowsIntegration::QWindowsIntegration() only.
- bool initTablet(unsigned integrationOptions);
+ void registerTouchWindows();
+ bool initTablet();
bool initPointer(unsigned integrationOptions);
+ bool disposeTablet();
bool initPowerNotificationHandler();
int defaultDPI() const;
+ static QString classNamePrefix();
QString registerWindowClass(const QWindow *w);
QString registerWindowClass(QString cname, WNDPROC proc,
unsigned style = 0, HBRUSH brush = nullptr,
@@ -193,8 +88,6 @@ public:
static QWindowsContext *instance();
- static QString windowsErrorMessage(unsigned long errorCode);
-
void addWindow(HWND, QWindowsWindow *w);
void removeWindow(HWND);
@@ -221,9 +114,11 @@ public:
QSharedPointer<QWindowCreationContext> setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx);
QSharedPointer<QWindowCreationContext> windowCreationContext() const;
- void setTabletAbsoluteRange(int a);
- void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness);
- static int processDpiAwareness();
+ static void setTabletAbsoluteRange(int a);
+
+ static bool setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwareness);
+ static QtWindows::DpiAwareness processDpiAwareness();
+ static QtWindows::DpiAwareness windowDpiAwareness(HWND hwnd);
void setDetectAltGrModifier(bool a);
@@ -231,21 +126,21 @@ public:
unsigned systemInfo() const;
bool useRTLExtensions() const;
- QList<int> possibleKeys(const QKeyEvent *e) const;
+ QPlatformKeyMapper *keyMapper() const;
+
+ HandleBaseWindowHash &windows();
static bool isSessionLocked();
- QWindowsMimeConverter &mimeConverter() const;
+ QWindowsMimeRegistry &mimeConverter() const;
QWindowsScreenManager &screenManager();
QWindowsTabletSupport *tabletSupport() const;
- static QWindowsUser32DLL user32dll;
- static QWindowsShcoreDLL shcoredll;
-
- static QByteArray comErrorString(HRESULT hr);
bool asyncExpose() const;
void setAsyncExpose(bool value);
+ static void forceNcCalcSize(HWND hwnd);
+
static bool systemParametersInfo(unsigned action, unsigned param, void *out, unsigned dpi = 0);
static bool systemParametersInfoForScreen(unsigned action, unsigned param, void *out,
const QPlatformScreen *screen = nullptr);
@@ -259,8 +154,6 @@ public:
static DWORD readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue);
- QTouchDevice *touchDevice() const;
-
static bool filterNativeEvent(MSG *msg, LRESULT *result);
static bool filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result);
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index 17e8cffb76..b416886120 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QT_NO_CURSOR
#include "qwindowscursor.h"
@@ -50,6 +14,8 @@
#include <QtGui/qscreen.h>
#include <QtGui/private/qguiapplication_p.h> // getPixmapCursor()
#include <QtGui/private/qhighdpiscaling_p.h>
+#include <QtGui/private/qpixmap_win_p.h>
+#include <QtCore/private/qwinregistry_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qscopedpointer.h>
@@ -64,25 +30,23 @@ static bool initResources()
QT_BEGIN_NAMESPACE
-Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0);
-Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap);
+using namespace Qt::Literals::StringLiterals;
/*!
\class QWindowsCursorCacheKey
\brief Cache key for storing values in a QHash with a QCursor as key.
\internal
- \ingroup qt-lighthouse-win
*/
QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c)
: bitmapCacheKey(c.pixmap().cacheKey()), maskCacheKey(0)
{
if (!bitmapCacheKey) {
- Q_ASSERT(c.bitmap());
- Q_ASSERT(c.mask());
- bitmapCacheKey = c.bitmap()->cacheKey();
- maskCacheKey = c.mask()->cacheKey();
+ Q_ASSERT(!c.bitmap().isNull());
+ Q_ASSERT(!c.mask().isNull());
+ bitmapCacheKey = c.bitmap().cacheKey();
+ maskCacheKey = c.mask().cacheKey();
}
}
@@ -96,14 +60,13 @@ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c)
as do the Window manager frames (resize/move handles).
\internal
- \ingroup qt-lighthouse-win
\sa QWindowsWindowCursor
*/
HCURSOR QWindowsCursor::createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor)
{
HCURSOR cur = nullptr;
- const qreal pixmapScaleFactor = scaleFactor / pixmap.devicePixelRatioF();
+ const qreal pixmapScaleFactor = scaleFactor / pixmap.devicePixelRatio();
if (!qFuzzyCompare(pixmapScaleFactor, 1)) {
pixmap = pixmap.scaled((pixmapScaleFactor * QSizeF(pixmap.size())).toSize(),
Qt::KeepAspectRatio, Qt::SmoothTransformation);
@@ -142,14 +105,16 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits,
hotSpot.setX(width / 2);
if (hotSpot.y() < 0)
hotSpot.setY(height / 2);
- const int n = qMax(1, width / 8);
- QScopedArrayPointer<uchar> xBits(new uchar[height * n]);
- QScopedArrayPointer<uchar> xMask(new uchar[height * n]);
+ // a ddb is word aligned, QImage depends on bow it was created
+ const auto bplDdb = qMax(1, ((width + 15) >> 4) << 1);
+ const auto bplImg = int(bbits.bytesPerLine());
+ QScopedArrayPointer<uchar> xBits(new uchar[height * bplDdb]);
+ QScopedArrayPointer<uchar> xMask(new uchar[height * bplDdb]);
int x = 0;
for (int i = 0; i < height; ++i) {
const uchar *bits = bbits.constScanLine(i);
const uchar *mask = mbits.constScanLine(i);
- for (int j = 0; j < n; ++j) {
+ for (int j = 0; j < bplImg && j < bplDdb; ++j) {
uchar b = bits[j];
uchar m = mask[j];
if (invb)
@@ -160,6 +125,11 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits,
xMask[x] = b ^ m;
++x;
}
+ for (int i = bplImg; i < bplDdb; ++i) {
+ xBits[x] = 0;
+ xMask[x] = 0;
+ ++x;
+ }
}
return CreateCursor(GetModuleHandle(nullptr), hotSpot.x(), hotSpot.y(), width, height,
xBits.data(), xMask.data());
@@ -168,17 +138,17 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits,
// Create a cursor from image and mask of the format QImage::Format_Mono.
static HCURSOR createBitmapCursor(const QCursor &cursor, qreal scaleFactor = 1)
{
- Q_ASSERT(cursor.shape() == Qt::BitmapCursor && cursor.bitmap());
- QImage bbits = cursor.bitmap()->toImage();
- QImage mbits = cursor.mask()->toImage();
- scaleFactor /= bbits.devicePixelRatioF();
+ Q_ASSERT(cursor.shape() == Qt::BitmapCursor && !cursor.bitmap().isNull());
+ QImage bbits = cursor.bitmap().toImage();
+ QImage mbits = cursor.mask().toImage();
+ scaleFactor /= bbits.devicePixelRatio();
if (!qFuzzyCompare(scaleFactor, 1)) {
const QSize scaledSize = (QSizeF(bbits.size()) * scaleFactor).toSize();
bbits = bbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
mbits = mbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
- bbits = bbits.convertToFormat(QImage::Format_Mono);
- mbits = mbits.convertToFormat(QImage::Format_Mono);
+ bbits = std::move(bbits).convertToFormat(QImage::Format_Mono);
+ mbits = std::move(mbits).convertToFormat(QImage::Format_Mono);
const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
return createBitmapCursor(bbits, mbits, cursor.hotSpot(), invb, invm);
@@ -475,8 +445,8 @@ QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursor
if (!bestFit)
return PixmapCursor();
- const QPixmap rawImage(QStringLiteral(":/qt-project.org/windows/cursors/images/") +
- QString::fromLatin1(bestFit->fileName));
+ const QPixmap rawImage(":/qt-project.org/windows/cursors/images/"_L1 +
+ QLatin1StringView(bestFit->fileName));
return PixmapCursor(rawImage, QPoint(bestFit->hotSpotX, bestFit->hotSpotY));
}
#endif // !QT_NO_IMAGEFORMAT_PNG
@@ -589,7 +559,7 @@ QWindowsCursor::QWindowsCursor(const QPlatformScreen *screen)
: m_screen(screen)
{
static const bool dummy = initResources();
- Q_UNUSED(dummy)
+ Q_UNUSED(dummy);
}
inline CursorHandlePtr QWindowsCursor::cursorHandle(const QCursor &cursor)
@@ -653,6 +623,11 @@ void QWindowsCursor::clearOverrideCursor()
SetCursor(m_overriddenCursor);
m_overriddenCursor = m_overrideCursor = nullptr;
}
+ auto &windows = QWindowsContext::instance()->windows();
+ for (auto it = windows.cbegin(), end = windows.cend(); it != end; ++it) {
+ if (it.value()->screen() == m_screen)
+ it.value()->setFlag(QWindowsWindow::RestoreOverrideCursor);
+ }
}
QPoint QWindowsCursor::mousePosition()
@@ -686,6 +661,30 @@ void QWindowsCursor::setPos(const QPoint &pos)
SetCursorPos(pos.x() , pos.y());
}
+/*
+ The standard size is 32x32, even though the cursor is actually just
+ 16 pixels large. If a large cursor is set in the accessibility settings,
+ then the cursor increases with 8 pixels for each step.
+*/
+QSize QWindowsCursor::size() const
+{
+ const QPair<DWORD,bool> cursorSizeSetting =
+ QWinRegistryKey(HKEY_CURRENT_USER, LR"(Control Panel\Cursors)")
+ .dwordValue(L"CursorBaseSize");
+ const int baseSize = screenCursorSize(m_screen).width() / 2;
+ if (!cursorSizeSetting.second)
+ return QSize(baseSize / 2, baseSize / 2);
+
+ // The registry values are dpi-independent, so we need to scale the result.
+ int cursorSizeValue = cursorSizeSetting.first * m_screen->logicalDpi().first
+ / m_screen->logicalBaseDpi().first;
+
+ // map from registry value 32-256 to 0-14, and from there to pixels
+ cursorSizeValue = (cursorSizeValue - 2 * baseSize) / baseSize;
+ const int cursorSize = baseSize + cursorSizeValue * (baseSize / 2);
+ return QSize(cursorSize, cursorSize);
+}
+
QPixmap QWindowsCursor::dragDefaultCursor(Qt::DropAction action) const
{
switch (action) {
@@ -791,7 +790,6 @@ HCURSOR QWindowsCursor::hCursor(const QCursor &c) const
cursor handle resource.
\internal
- \ingroup qt-lighthouse-win
\sa QWindowsCursor
*/
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index b896f4c7a9..d5c0388d1d 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSCURSOR_H
#define QWINDOWSCURSOR_H
@@ -61,9 +25,9 @@ inline bool operator==(const QWindowsPixmapCursorCacheKey &k1, const QWindowsPix
return k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey;
}
-inline uint qHash(const QWindowsPixmapCursorCacheKey &k, uint seed) noexcept
+inline size_t qHash(const QWindowsPixmapCursorCacheKey &k, size_t seed) noexcept
{
- return (uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed;
+ return (size_t(k.bitmapCacheKey) + size_t(k.maskCacheKey)) ^ seed;
}
class CursorHandle
@@ -113,6 +77,8 @@ public:
QPoint pos() const override;
void setPos(const QPoint &pos) override;
+ QSize size() const override;
+
static HCURSOR createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor = 1);
static HCURSOR createPixmapCursor(const PixmapCursor &pc, qreal scaleFactor = 1) { return createPixmapCursor(pc.pixmap, pc.hotSpot, scaleFactor); }
static PixmapCursor customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen = nullptr);
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index cdb4e407d1..0ce0b0e2a7 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -1,49 +1,9 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#define QT_NO_URL_CAST_FROM_STRING 1
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0601
-#endif
-
-#include "qwindowscombase.h"
+#include <QtCore/qt_windows.h>
#include "qwindowsdialoghelpers.h"
#include "qwindowscontext.h"
@@ -55,7 +15,9 @@
#include <QtGui/qcolor.h>
#include <QtCore/qdebug.h>
-#include <QtCore/qregularexpression.h>
+#if QT_CONFIG(regularexpression)
+# include <QtCore/qregularexpression.h>
+#endif
#include <QtCore/qtimer.h>
#include <QtCore/qdir.h>
#include <QtCore/qscopedpointer.h>
@@ -68,44 +30,18 @@
#include <QtCore/qmutex.h>
#include <QtCore/quuid.h>
#include <QtCore/qtemporaryfile.h>
-#include <QtCore/private/qsystemlibrary_p.h>
+#include <QtCore/private/qfunctions_win_p.h>
+#include <QtCore/private/qsystemerror_p.h>
+#include <QtCore/private/qcomobject_p.h>
#include <algorithm>
#include <vector>
-#include <QtCore/qt_windows.h>
-
// #define USE_NATIVE_COLOR_DIALOG /* Testing purposes only */
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_DEBUG_STREAM
-/* Output UID (IID, CLSID) as C++ constants.
- * The constants are contained in the Windows SDK libs, but not for MinGW. */
-static inline QString guidToString(const GUID &g)
-{
- QString rc;
- QTextStream str(&rc);
- str.setIntegerBase(16);
- str.setNumberFlags(str.numberFlags() | QTextStream::ShowBase);
- str << '{' << g.Data1 << ", " << g.Data2 << ", " << g.Data3;
- str.setFieldWidth(2);
- str.setFieldAlignment(QTextStream::AlignRight);
- str.setPadChar(QLatin1Char('0'));
- str << ",{" << g.Data4[0] << ", " << g.Data4[1] << ", " << g.Data4[2] << ", " << g.Data4[3]
- << ", " << g.Data4[4] << ", " << g.Data4[5] << ", " << g.Data4[6] << ", " << g.Data4[7]
- << "}};";
- return rc;
-}
-
-inline QDebug operator<<(QDebug d, const GUID &g)
-{
- QDebugStateSaver saver(d);
- d.nospace();
- d << guidToString(g);
- return d;
-}
-#endif // !QT_NO_DEBUG_STREAM
+using namespace Qt::StringLiterals;
// Return an allocated wchar_t array from a QString, reserve more memory if desired.
static wchar_t *qStringToWCharArray(const QString &s, size_t reserveSize = 0)
@@ -128,7 +64,6 @@ namespace QWindowsDialogs
remove all those messages (usually 1) and post the last one with a
reset button state.
- \ingroup qt-lighthouse-win
*/
void eatMouseMove()
@@ -141,6 +76,22 @@ void eatMouseMove()
qCDebug(lcQpaDialogs) << __FUNCTION__ << "triggered=" << (msg.message == WM_MOUSEMOVE);
}
+HWND getHWND(IFileDialog *fileDialog)
+{
+ IOleWindow *oleWindow = nullptr;
+ if (FAILED(fileDialog->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&oleWindow)))) {
+ qCWarning(lcQpaDialogs, "Native file dialog: unable to query IID_IOleWindow interface.");
+ return HWND(0);
+ }
+
+ HWND result(0);
+ if (FAILED(oleWindow->GetWindow(&result)))
+ qCWarning(lcQpaDialogs, "Native file dialog: unable to get dialog's window.");
+
+ oleWindow->Release();
+ return result;
+}
+
} // namespace QWindowsDialogs
/*!
@@ -149,7 +100,7 @@ void eatMouseMove()
Base classes for native dialogs (using the CLSID-based
dialog interfaces "IFileDialog", etc. available from Windows
- Vista on) that mimick the behaviour of their QDialog
+ Vista on) that mimic the behavior of their QDialog
counterparts as close as possible.
Instances of derived classes are controlled by
@@ -171,7 +122,6 @@ void eatMouseMove()
\sa QWindowsDialogHelperBase
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsNativeDialogBase : public QObject
@@ -211,24 +161,28 @@ private:
\sa QWindowsDialogThread, QWindowsNativeDialogBase
\internal
- \ingroup qt-lighthouse-win
*/
template <class BaseClass>
+QWindowsDialogHelperBase<BaseClass>::~QWindowsDialogHelperBase()
+{
+ hide();
+ cleanupThread();
+}
+
+template <class BaseClass>
void QWindowsDialogHelperBase<BaseClass>::cleanupThread()
{
- if (m_thread) { // Thread may be running if the dialog failed to close.
- if (m_thread->isRunning())
- m_thread->wait(500);
- if (m_thread->isRunning()) {
- m_thread->terminate();
- m_thread->wait(300);
- if (m_thread->isRunning())
- qCCritical(lcQpaDialogs) <<__FUNCTION__ << "Failed to terminate thread.";
- else
- qCWarning(lcQpaDialogs) << __FUNCTION__ << "Thread terminated.";
- }
- delete m_thread;
+ if (m_thread) {
+ // Thread may be running if the dialog failed to close. Give it a bit
+ // to exit, but let it be a memory leak if that fails. We must not
+ // terminate the thread, it might be stuck in Comdlg32 or an IModalWindow
+ // implementation, and we might end up dead-locking the application if the thread
+ // holds a mutex or critical section.
+ if (m_thread->wait(500))
+ delete m_thread;
+ else
+ qCCritical(lcQpaDialogs) <<__FUNCTION__ << "Thread failed to finish.";
m_thread = nullptr;
}
}
@@ -255,7 +209,7 @@ QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::ensureNativeDialo
// Create dialog and apply common settings. Check "executed" flag as well
// since for example IFileDialog::Show() works only once.
if (m_nativeDialog.isNull() || m_nativeDialog->executed())
- m_nativeDialog = QWindowsNativeDialogBasePtr(createNativeDialog());
+ m_nativeDialog = QWindowsNativeDialogBasePtr(createNativeDialog(), &QObject::deleteLater);
return m_nativeDialog.data();
}
@@ -265,7 +219,6 @@ QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::ensureNativeDialo
\sa QWindowsDialogHelperBase
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsDialogThread : public QThread
@@ -275,7 +228,7 @@ public:
explicit QWindowsDialogThread(const QWindowsNativeDialogBasePtr &d, HWND owner)
: m_dialog(d), m_owner(owner) {}
- void run();
+ void run() override;
private:
const QWindowsNativeDialogBasePtr m_dialog;
@@ -285,6 +238,7 @@ private:
void QWindowsDialogThread::run()
{
qCDebug(lcQpaDialogs) << '>' << __FUNCTION__;
+ QComHelper comInit(COINIT_APARTMENTTHREADED);
m_dialog->exec(m_owner);
qCDebug(lcQpaDialogs) << '<' << __FUNCTION__;
}
@@ -341,47 +295,13 @@ void QWindowsDialogHelperBase<BaseClass>::stopTimer()
}
}
-// Find a file dialog window created by IFileDialog by process id, window
-// title and class, which starts with a hash '#'.
-
-struct FindDialogContext
-{
- explicit FindDialogContext(const QString &titleIn)
- : title(qStringToWCharArray(titleIn)), processId(GetCurrentProcessId()), hwnd(nullptr) {}
-
- const QScopedArrayPointer<wchar_t> title;
- const DWORD processId;
- HWND hwnd; // contains the HWND of the window found.
-};
-
-static BOOL QT_WIN_CALLBACK findDialogEnumWindowsProc(HWND hwnd, LPARAM lParam)
-{
- auto *context = reinterpret_cast<FindDialogContext *>(lParam);
- DWORD winPid = 0;
- GetWindowThreadProcessId(hwnd, &winPid);
- if (winPid != context->processId)
- return TRUE;
- wchar_t buf[256];
- if (!RealGetWindowClass(hwnd, buf, sizeof(buf)/sizeof(wchar_t)) || buf[0] != L'#')
- return TRUE;
- if (!GetWindowTextW(hwnd, buf, sizeof(buf)/sizeof(wchar_t)) || wcscmp(buf, context->title.data()) != 0)
- return TRUE;
- context->hwnd = hwnd;
- return FALSE;
-}
-
-static inline HWND findDialogWindow(const QString &title)
-{
- FindDialogContext context(title);
- EnumWindows(findDialogEnumWindowsProc, reinterpret_cast<LPARAM>(&context));
- return context.hwnd;
-}
-
template <class BaseClass>
void QWindowsDialogHelperBase<BaseClass>::hide()
{
- if (m_nativeDialog)
+ if (m_nativeDialog) {
m_nativeDialog->close();
+ m_nativeDialog.clear();
+ }
m_ownerWindow = nullptr;
}
@@ -406,7 +326,6 @@ void QWindowsDialogHelperBase<BaseClass>::exec()
does not reliably work. Provides thread-safe setters (for the non-modal case).
\internal
- \ingroup qt-lighthouse-win
\sa QFileDialogOptions
*/
@@ -500,26 +419,31 @@ inline void QWindowsFileDialogSharedData::fromOptions(const QSharedPointer<QFile
\sa QWindowsNativeFileDialogBase, QWindowsFileDialogHelper
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsNativeFileDialogBase;
-class QWindowsNativeFileDialogEventHandler : public QWindowsComBase<IFileDialogEvents>
+class QWindowsNativeFileDialogEventHandler : public QComObject<IFileDialogEvents>
{
Q_DISABLE_COPY_MOVE(QWindowsNativeFileDialogEventHandler)
public:
static IFileDialogEvents *create(QWindowsNativeFileDialogBase *nativeFileDialog);
// IFileDialogEvents methods
- IFACEMETHODIMP OnFileOk(IFileDialog *);
- IFACEMETHODIMP OnFolderChange(IFileDialog *) { return S_OK; }
- IFACEMETHODIMP OnFolderChanging(IFileDialog *, IShellItem *);
- IFACEMETHODIMP OnHelp(IFileDialog *) { return S_OK; }
- IFACEMETHODIMP OnSelectionChange(IFileDialog *);
- IFACEMETHODIMP OnShareViolation(IFileDialog *, IShellItem *, FDE_SHAREVIOLATION_RESPONSE *) { return S_OK; }
- IFACEMETHODIMP OnTypeChange(IFileDialog *);
- IFACEMETHODIMP OnOverwrite(IFileDialog *, IShellItem *, FDE_OVERWRITE_RESPONSE *) { return S_OK; }
+ IFACEMETHODIMP OnFileOk(IFileDialog *) override;
+ IFACEMETHODIMP OnFolderChange(IFileDialog *) override { return S_OK; }
+ IFACEMETHODIMP OnFolderChanging(IFileDialog *, IShellItem *) override;
+ IFACEMETHODIMP OnSelectionChange(IFileDialog *) override;
+ IFACEMETHODIMP OnShareViolation(IFileDialog *, IShellItem *,
+ FDE_SHAREVIOLATION_RESPONSE *) override
+ {
+ return S_OK;
+ }
+ IFACEMETHODIMP OnTypeChange(IFileDialog *) override;
+ IFACEMETHODIMP OnOverwrite(IFileDialog *, IShellItem *, FDE_OVERWRITE_RESPONSE *) override
+ {
+ return S_OK;
+ }
QWindowsNativeFileDialogEventHandler(QWindowsNativeFileDialogBase *nativeFileDialog) :
m_nativeFileDialog(nativeFileDialog) {}
@@ -546,7 +470,6 @@ IFileDialogEvents *QWindowsNativeFileDialogEventHandler::create(QWindowsNativeFi
\sa QWindowsNativeFileDialogBase
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsShellItem
{
@@ -593,8 +516,18 @@ QWindowsShellItem::QWindowsShellItem(IShellItem *item)
: m_item(item)
, m_attributes(0)
{
- if (FAILED(item->GetAttributes(SFGAO_CAPABILITYMASK | SFGAO_DISPLAYATTRMASK | SFGAO_CONTENTSMASK | SFGAO_STORAGECAPMASK, &m_attributes)))
+ SFGAOF mask = (SFGAO_CAPABILITYMASK | SFGAO_CONTENTSMASK | SFGAO_STORAGECAPMASK);
+
+ // Check for attributes which might be expensive to enumerate for subfolders
+ if (FAILED(item->GetAttributes((SFGAO_STREAM | SFGAO_COMPRESSED), &m_attributes))) {
m_attributes = 0;
+ } else {
+ // If the item is compressed or stream, skip expensive subfolder test
+ if (m_attributes & (SFGAO_STREAM | SFGAO_COMPRESSED))
+ mask &= ~SFGAO_HASSUBFOLDER;
+ if (FAILED(item->GetAttributes(mask, &m_attributes)))
+ m_attributes = 0;
+ }
}
QString QWindowsShellItem::path() const
@@ -633,8 +566,8 @@ QUrl QWindowsShellItem::url() const
if (urlV.isValid())
return urlV;
// Last resort: encode the absolute desktop parsing id as data URL
- const QString data = QStringLiteral("data:text/plain;base64,")
- + QLatin1String(desktopAbsoluteParsing().toLatin1().toBase64());
+ const QString data = "data:text/plain;base64,"_L1
+ + QLatin1StringView(desktopAbsoluteParsing().toLatin1().toBase64());
return QUrl(data);
}
@@ -667,14 +600,14 @@ QWindowsShellItem::IShellItems QWindowsShellItem::itemsFromItemArray(IShellItemA
bool QWindowsShellItem::copyData(QIODevice *out, QString *errorMessage)
{
if (!canStream()) {
- *errorMessage = QLatin1String("Item not streamable");
+ *errorMessage = "Item not streamable"_L1;
return false;
}
IStream *istream = nullptr;
HRESULT hr = m_item->BindToHandler(nullptr, BHID_Stream, IID_PPV_ARGS(&istream));
if (FAILED(hr)) {
- *errorMessage = QLatin1String("BindToHandler() failed: ")
- + QLatin1String(QWindowsContext::comErrorString(hr));
+ *errorMessage = "BindToHandler() failed: "_L1
+ + QSystemError::windowsComString(hr);
return false;
}
enum : ULONG { bufSize = 102400 };
@@ -690,8 +623,8 @@ bool QWindowsShellItem::copyData(QIODevice *out, QString *errorMessage)
}
istream->Release();
if (hr != S_OK && hr != S_FALSE) {
- *errorMessage = QLatin1String("Read() failed: ")
- + QLatin1String(QWindowsContext::comErrorString(hr));
+ *errorMessage = "Read() failed: "_L1
+ + QSystemError::windowsComString(hr);
return false;
}
return true;
@@ -789,7 +722,6 @@ QDebug operator<<(QDebug d, IShellItem *i)
\sa QWindowsNativeFileDialogEventHandler, QWindowsFileDialogHelper
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsNativeFileDialogBase : public QWindowsNativeDialogBase
@@ -915,7 +847,7 @@ IShellItem *QWindowsNativeFileDialogBase::shellItem(const QUrl &url)
return nullptr;
}
return result;
- } else if (url.scheme() == QLatin1String("clsid")) {
+ } else if (url.scheme() == u"clsid") {
// Support for virtual folders via GUID
// (see https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx)
// specified as "clsid:<GUID>" (without '{', '}').
@@ -1034,26 +966,33 @@ static QList<FilterSpec> filterSpecs(const QStringList &filters,
result.reserve(filters.size());
*totalStringLength = 0;
+#if QT_CONFIG(regularexpression)
const QRegularExpression filterSeparatorRE(QStringLiteral("[;\\s]+"));
const QString separator = QStringLiteral(";");
Q_ASSERT(filterSeparatorRE.isValid());
+#endif
+
// Split filter specification as 'Texts (*.txt[;] *.doc)', '*.txt[;] *.doc'
// into description and filters specification as '*.txt;*.doc'
for (const QString &filterString : filters) {
- const int openingParenPos = filterString.lastIndexOf(QLatin1Char('('));
+ const int openingParenPos = filterString.lastIndexOf(u'(');
const int closingParenPos = openingParenPos != -1 ?
- filterString.indexOf(QLatin1Char(')'), openingParenPos + 1) : -1;
+ filterString.indexOf(u')', openingParenPos + 1) : -1;
FilterSpec filterSpec;
filterSpec.filter = closingParenPos == -1 ?
filterString :
filterString.mid(openingParenPos + 1, closingParenPos - openingParenPos - 1).trimmed();
if (filterSpec.filter.isEmpty())
- filterSpec.filter += QLatin1Char('*');
+ filterSpec.filter += u'*';
+#if QT_CONFIG(regularexpression)
filterSpec.filter.replace(filterSeparatorRE, separator);
+#else
+ filterSpec.filter.replace(u' ', u';');
+#endif
filterSpec.description = filterString;
if (hideFilterDetails && openingParenPos != -1) { // Do not show pattern in description
filterSpec.description.truncate(openingParenPos);
- while (filterSpec.description.endsWith(QLatin1Char(' ')))
+ while (filterSpec.description.endsWith(u' '))
filterSpec.description.truncate(filterSpec.description.size() - 1);
}
*totalStringLength += filterSpec.filter.size() + filterSpec.description.size();
@@ -1084,10 +1023,13 @@ void QWindowsNativeFileDialogBase::setNameFilters(const QStringList &filters)
// 'AAA files (a.*) (a.*)'
QString description = specs[i].description;
const QString &filter = specs[i].filter;
- if (!m_hideFiltersDetails && !filter.startsWith(QLatin1String("*."))) {
- const int pos = description.lastIndexOf(QLatin1Char('('));
- if (pos > 0)
+ if (!m_hideFiltersDetails && !filter.startsWith(u"*.")) {
+ const int pos = description.lastIndexOf(u'(');
+ if (pos > 0) {
description.truncate(pos);
+ while (!description.isEmpty() && description.back().isSpace())
+ description.chop(1);
+ }
}
// Add to buffer.
comFilterSpec[i].pszName = ptr;
@@ -1151,8 +1093,8 @@ static bool isHexRange(const QString& s, int start, int end)
for (;start < end; ++start) {
QChar ch = s.at(start);
if (!(ch.isDigit()
- || (ch >= QLatin1Char('a') && ch <= QLatin1Char('f'))
- || (ch >= QLatin1Char('A') && ch <= QLatin1Char('F'))))
+ || (ch >= u'a' && ch <= u'f')
+ || (ch >= u'A' && ch <= u'F')))
return false;
}
return true;
@@ -1161,7 +1103,7 @@ static bool isHexRange(const QString& s, int start, int end)
static inline bool isClsid(const QString &s)
{
// detect "374DE290-123F-4565-9164-39C4925E467B".
- const QChar dash(QLatin1Char('-'));
+ const QChar dash(u'-');
return s.size() == 36
&& isHexRange(s, 0, 8)
&& s.at(8) == dash
@@ -1204,7 +1146,7 @@ void QWindowsNativeFileDialogBase::selectNameFilter(const QString &filter)
if (index < 0) {
qWarning("%s: Invalid parameter '%s' not found in '%s'.",
__FUNCTION__, qPrintable(filter),
- qPrintable(m_nameFilters.join(QLatin1String(", "))));
+ qPrintable(m_nameFilters.join(u", ")));
return;
}
m_fileDialog->SetFileTypeIndex(index + 1); // one-based.
@@ -1259,7 +1201,7 @@ void QWindowsNativeFileDialogBase::close()
m_fileDialog->Close(S_OK);
// IFileDialog::Close() does not work unless invoked from a callback.
// Try to find the window and send it a WM_CLOSE in addition.
- const HWND hwnd = findDialogWindow(m_title);
+ const HWND hwnd = QWindowsDialogs::getHWND(m_fileDialog);
qCDebug(lcQpaDialogs) << __FUNCTION__ << "closing" << hwnd;
if (hwnd && IsWindowVisible(hwnd))
PostMessageW(hwnd, WM_CLOSE, 0, 0);
@@ -1295,7 +1237,6 @@ HRESULT QWindowsNativeFileDialogEventHandler::OnFileOk(IFileDialog *)
Implements single-selection methods.
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsNativeSaveFileDialog : public QWindowsNativeFileDialogBase
@@ -1313,15 +1254,15 @@ public:
// Also handles the simple name filter case "*.txt" -> "txt"
static inline QString suffixFromFilter(const QString &filter)
{
- int suffixPos = filter.indexOf(QLatin1String("*."));
+ int suffixPos = filter.indexOf(u"*.");
if (suffixPos < 0)
return QString();
suffixPos += 2;
- int endPos = filter.indexOf(QLatin1Char(' '), suffixPos + 1);
+ int endPos = filter.indexOf(u' ', suffixPos + 1);
if (endPos < 0)
- endPos = filter.indexOf(QLatin1Char(';'), suffixPos + 1);
+ endPos = filter.indexOf(u';', suffixPos + 1);
if (endPos < 0)
- endPos = filter.indexOf(QLatin1Char(')'), suffixPos + 1);
+ endPos = filter.indexOf(u')', suffixPos + 1);
if (endPos < 0)
endPos = filter.size();
return filter.mid(suffixPos, endPos - suffixPos);
@@ -1372,7 +1313,6 @@ QList<QUrl> QWindowsNativeSaveFileDialog::selectedFiles() const
Implements multi-selection methods.
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsNativeOpenFileDialog : public QWindowsNativeFileDialogBase
@@ -1397,7 +1337,7 @@ Q_GLOBAL_STATIC(QStringList, temporaryItemCopies)
static void cleanupTemporaryItemCopies()
{
- for (const QString &file : qAsConst(*temporaryItemCopies()))
+ for (const QString &file : std::as_const(*temporaryItemCopies()))
QFile::remove(file);
}
@@ -1406,41 +1346,41 @@ static void cleanupTemporaryItemCopies()
static bool validFileNameCharacter(QChar c)
{
- return c.isLetterOrNumber() || c == QLatin1Char('_') || c == QLatin1Char('-');
+ return c.isLetterOrNumber() || c == u'_' || c == u'-';
}
QString tempFilePattern(QString name)
{
- const int lastSlash = qMax(name.lastIndexOf(QLatin1Char('/')),
- name.lastIndexOf(QLatin1Char('\\')));
+ const int lastSlash = qMax(name.lastIndexOf(u'/'),
+ name.lastIndexOf(u'\\'));
if (lastSlash != -1)
name.remove(0, lastSlash + 1);
- int lastDot = name.lastIndexOf(QLatin1Char('.'));
+ int lastDot = name.lastIndexOf(u'.');
if (lastDot < 0)
lastDot = name.size();
- name.insert(lastDot, QStringLiteral("_XXXXXX"));
+ name.insert(lastDot, "_XXXXXX"_L1);
for (int i = lastDot - 1; i >= 0; --i) {
if (!validFileNameCharacter(name.at(i)))
- name[i] = QLatin1Char('_');
+ name[i] = u'_';
}
- name.prepend(QDir::tempPath() + QLatin1Char('/'));
+ name.prepend(QDir::tempPath() + u'/');
return name;
}
static QString createTemporaryItemCopy(QWindowsShellItem &qItem, QString *errorMessage)
{
if (!qItem.canStream()) {
- *errorMessage = QLatin1String("Item not streamable");
+ *errorMessage = "Item not streamable"_L1;
return QString();
}
QTemporaryFile targetFile(tempFilePattern(qItem.normalDisplay()));
targetFile.setAutoRemove(false);
if (!targetFile.open()) {
- *errorMessage = QLatin1String("Cannot create temporary file: ")
+ *errorMessage = "Cannot create temporary file: "_L1
+ targetFile.errorString();
return QString();
}
@@ -1456,7 +1396,7 @@ static QString createTemporaryItemCopy(QWindowsShellItem &qItem, QString *errorM
static QUrl itemToDialogUrl(QWindowsShellItem &qItem, QString *errorMessage)
{
QUrl url = qItem.url();
- if (url.isLocalFile() || url.scheme().startsWith(QLatin1String("http")))
+ if (url.isLocalFile() || url.scheme().startsWith(u"http"))
return url;
const QString path = qItem.path();
if (path.isEmpty() && !qItem.isDir() && qItem.canStream()) {
@@ -1545,7 +1485,6 @@ QWindowsNativeFileDialogBase *QWindowsNativeFileDialogBase::create(QFileDialogOp
but only on QQuickWindows, which do not have a fallback.
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFileDialogHelper>
@@ -1612,7 +1551,7 @@ QWindowsNativeDialogBase *QWindowsFileDialogHelper::createNativeDialog()
if (!info.isDir())
result->selectFile(info.fileName());
} else {
- result->selectFile(url.path()); // TODO url.fileName() once it exists
+ result->selectFile(url.fileName());
}
}
// No need to select initialNameFilter if mode is Dir
@@ -1646,7 +1585,7 @@ void QWindowsFileDialogHelper::selectFile(const QUrl &fileName)
qCDebug(lcQpaDialogs) << __FUNCTION__ << fileName.toString();
if (hasNativeDialog()) // Might be invoked from the QFileDialog constructor.
- nativeFileDialog()->selectFile(fileName.toLocalFile()); // ## should use QUrl::fileName() once it exists
+ nativeFileDialog()->selectFile(fileName.fileName());
}
QList<QUrl> QWindowsFileDialogHelper::selectedFiles() const
@@ -1681,7 +1620,6 @@ QString QWindowsFileDialogHelper::selectedNameFilter() const
\internal
\sa QWindowsXpFileDialogHelper
- \ingroup qt-lighthouse-win
*/
class QWindowsXpNativeFileDialog : public QWindowsNativeDialogBase
@@ -1701,9 +1639,6 @@ public slots:
void close() override {}
private:
- typedef BOOL (APIENTRY *PtrGetOpenFileNameW)(LPOPENFILENAMEW);
- typedef BOOL (APIENTRY *PtrGetSaveFileNameW)(LPOPENFILENAMEW);
-
explicit QWindowsXpNativeFileDialog(const OptionsPtr &options, const QWindowsFileDialogSharedData &data);
void populateOpenFileName(OPENFILENAME *ofn, HWND owner) const;
QList<QUrl> execExistingDir(HWND owner);
@@ -1713,27 +1648,11 @@ private:
QString m_title;
QPlatformDialogHelper::DialogCode m_result;
QWindowsFileDialogSharedData m_data;
-
- static PtrGetOpenFileNameW m_getOpenFileNameW;
- static PtrGetSaveFileNameW m_getSaveFileNameW;
};
-QWindowsXpNativeFileDialog::PtrGetOpenFileNameW QWindowsXpNativeFileDialog::m_getOpenFileNameW = nullptr;
-QWindowsXpNativeFileDialog::PtrGetSaveFileNameW QWindowsXpNativeFileDialog::m_getSaveFileNameW = nullptr;
-
QWindowsXpNativeFileDialog *QWindowsXpNativeFileDialog::create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data)
{
- // GetOpenFileNameW() GetSaveFileName() are resolved
- // dynamically as not to create a dependency on Comdlg32, which
- // is used on XP only.
- if (!m_getOpenFileNameW) {
- QSystemLibrary library(QStringLiteral("Comdlg32"));
- m_getOpenFileNameW = (PtrGetOpenFileNameW)(library.resolve("GetOpenFileNameW"));
- m_getSaveFileNameW = (PtrGetSaveFileNameW)(library.resolve("GetSaveFileNameW"));
- }
- if (m_getOpenFileNameW && m_getSaveFileNameW)
- return new QWindowsXpNativeFileDialog(options, data);
- return nullptr;
+ return new QWindowsXpNativeFileDialog(options, data);
}
QWindowsXpNativeFileDialog::QWindowsXpNativeFileDialog(const OptionsPtr &options,
@@ -1774,14 +1693,6 @@ static int QT_WIN_CALLBACK xpFileDialogGetExistingDirCallbackProc(HWND hwnd, UIN
return dialog->existingDirCallback(hwnd, uMsg, lParam);
}
-/* The correct declaration of the SHGetPathFromIDList symbol is
- * being used in mingw-w64 as of r6215, which is a v3 snapshot. */
-#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
-typedef ITEMIDLIST *qt_LpItemIdList;
-#else
-using qt_LpItemIdList = PIDLIST_ABSOLUTE;
-#endif
-
int QWindowsXpNativeFileDialog::existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam)
{
switch (uMsg) {
@@ -1795,7 +1706,7 @@ int QWindowsXpNativeFileDialog::existingDirCallback(HWND hwnd, UINT uMsg, LPARAM
break;
case BFFM_SELCHANGED: {
wchar_t path[MAX_PATH];
- const bool ok = SHGetPathFromIDList(reinterpret_cast<qt_LpItemIdList>(lParam), path)
+ const bool ok = SHGetPathFromIDList(reinterpret_cast<PIDLIST_ABSOLUTE>(lParam), path)
&& path[0];
SendMessage(hwnd, BFFM_ENABLEOK, ok ? 1 : 0, 1);
}
@@ -1817,7 +1728,7 @@ QList<QUrl> QWindowsXpNativeFileDialog::execExistingDir(HWND owner)
bi.lpfn = xpFileDialogGetExistingDirCallbackProc;
bi.lParam = LPARAM(this);
QList<QUrl> selectedFiles;
- if (qt_LpItemIdList pItemIDList = SHBrowseForFolder(&bi)) {
+ if (const auto pItemIDList = SHBrowseForFolder(&bi)) {
wchar_t path[MAX_PATH];
path[0] = 0;
if (SHGetPathFromIDList(pItemIDList, path) && path[0])
@@ -1859,10 +1770,12 @@ void QWindowsXpNativeFileDialog::populateOpenFileName(OPENFILENAME *ofn, HWND ow
// for the target. If it contains any invalid character, the dialog
// will not show.
ofn->nMaxFile = 65535;
- const QString initiallySelectedFile =
- QDir::toNativeSeparators(m_data.selectedFile()).remove(QLatin1Char('<')).
- remove(QLatin1Char('>')).remove(QLatin1Char('"')).remove(QLatin1Char('|'));
- ofn->lpstrFile = qStringToWCharArray(initiallySelectedFile, ofn->nMaxFile);
+ QString initiallySelectedFile = m_data.selectedFile();
+ initiallySelectedFile.remove(u'<');
+ initiallySelectedFile.remove(u'>');
+ initiallySelectedFile.remove(u'"');
+ initiallySelectedFile.remove(u'|');
+ ofn->lpstrFile = qStringToWCharArray(QDir::toNativeSeparators(initiallySelectedFile), ofn->nMaxFile);
ofn->lpstrInitialDir = qStringToWCharArray(QDir::toNativeSeparators(m_data.directory().toLocalFile()));
ofn->lpstrTitle = (wchar_t*)m_title.utf16();
// Determine lpstrDefExt. Note that the current MSDN docs document this
@@ -1872,7 +1785,7 @@ void QWindowsXpNativeFileDialog::populateOpenFileName(OPENFILENAME *ofn, HWND ow
// the extension of the current filter".
if (m_options->acceptMode() == QFileDialogOptions::AcceptSave) {
QString defaultSuffix = m_options->defaultSuffix();
- if (defaultSuffix.startsWith(QLatin1Char('.')))
+ if (defaultSuffix.startsWith(u'.'))
defaultSuffix.remove(0, 1);
// QTBUG-33156, also create empty strings to trigger the appending mechanism.
ofn->lpstrDefExt = qStringToWCharArray(defaultSuffix);
@@ -1895,7 +1808,7 @@ QList<QUrl> QWindowsXpNativeFileDialog::execFileNames(HWND owner, int *selectedF
populateOpenFileName(&ofn, owner);
QList<QUrl> result;
const bool isSave = m_options->acceptMode() == QFileDialogOptions::AcceptSave;
- if (isSave ? m_getSaveFileNameW(&ofn) : m_getOpenFileNameW(&ofn)) {
+ if (isSave ? GetSaveFileNameW(&ofn) : GetOpenFileNameW(&ofn)) {
*selectedFilterIndex = ofn.nFilterIndex - 1;
const QString dir = QDir::cleanPath(QString::fromWCharArray(ofn.lpstrFile));
result.push_back(QUrl::fromLocalFile(dir));
@@ -1905,7 +1818,7 @@ QList<QUrl> QWindowsXpNativeFileDialog::execFileNames(HWND owner, int *selectedF
wchar_t *ptr = ofn.lpstrFile + dir.size() + 1;
if (*ptr) {
result.pop_front();
- const QString path = dir + QLatin1Char('/');
+ const QString path = dir + u'/';
while (*ptr) {
const QString fileName = QString::fromWCharArray(ptr);
result.push_back(QUrl::fromLocalFile(path + fileName));
@@ -1927,7 +1840,6 @@ QList<QUrl> QWindowsXpNativeFileDialog::execFileNames(HWND owner, int *selectedF
\sa QWindowsXpNativeFileDialog
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsXpFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFileDialogHelper>
@@ -2004,7 +1916,6 @@ QString QWindowsXpFileDialogHelper::selectedNameFilter() const
\sa QWindowsColorDialogHelper
\sa #define USE_NATIVE_COLOR_DIALOG
\internal
- \ingroup qt-lighthouse-win
*/
using SharedPointerColor = QSharedPointer<QColor>;
@@ -2039,8 +1950,6 @@ QWindowsNativeColorDialog::QWindowsNativeColorDialog(const SharedPointerColor &c
void QWindowsNativeColorDialog::doExec(HWND owner)
{
- typedef BOOL (WINAPI *ChooseColorWType)(LPCHOOSECOLORW);
-
CHOOSECOLOR chooseColor;
ZeroMemory(&chooseColor, sizeof(chooseColor));
chooseColor.lStructSize = sizeof(chooseColor);
@@ -2053,18 +1962,9 @@ void QWindowsNativeColorDialog::doExec(HWND owner)
m_customColors[c] = qColorToCOLORREF(QColor(qCustomColors[c]));
chooseColor.rgbResult = qColorToCOLORREF(*m_color);
chooseColor.Flags = CC_FULLOPEN | CC_RGBINIT;
- static ChooseColorWType chooseColorW = 0;
- if (!chooseColorW) {
- QSystemLibrary library(QStringLiteral("Comdlg32"));
- chooseColorW = (ChooseColorWType)library.resolve("ChooseColorW");
- }
- if (chooseColorW) {
- m_code = chooseColorW(&chooseColor) ?
- QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected;
- QWindowsDialogs::eatMouseMove();
- } else {
- m_code = QPlatformDialogHelper::Rejected;
- }
+ m_code = ChooseColorW(&chooseColor) ?
+ QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected;
+ QWindowsDialogs::eatMouseMove();
if (m_code == QPlatformDialogHelper::Accepted) {
*m_color = COLORREFToQColor(chooseColor.rgbResult);
for (int c= 0; c < customColorCount; ++c)
@@ -2084,7 +1984,6 @@ void QWindowsNativeColorDialog::doExec(HWND owner)
\sa #define USE_NATIVE_COLOR_DIALOG
\sa QWindowsNativeColorDialog
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsColorDialogHelper : public QWindowsDialogHelperBase<QPlatformColorDialogHelper>
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
index 8686749011..64f40bc3a9 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSDIALOGHELPER_H
#define QWINDOWSDIALOGHELPER_H
@@ -67,7 +31,7 @@ class QWindowsDialogHelperBase : public BaseClass
Q_DISABLE_COPY_MOVE(QWindowsDialogHelperBase)
public:
using QWindowsNativeDialogBasePtr = QSharedPointer<QWindowsNativeDialogBase>;
- ~QWindowsDialogHelperBase() { cleanupThread(); }
+ ~QWindowsDialogHelperBase();
void exec() override;
bool show(Qt::WindowFlags windowFlags,
@@ -80,7 +44,7 @@ public:
protected:
QWindowsDialogHelperBase() = default;
QWindowsNativeDialogBase *nativeDialog() const;
- inline bool hasNativeDialog() const { return m_nativeDialog; }
+ inline bool hasNativeDialog() const { return !m_nativeDialog.isNull(); }
void timerEvent(QTimerEvent *) override;
private:
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 3e4c93d47a..c6f55c3509 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -1,42 +1,7 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#include <QtCore/qt_windows.h>
#include "qwindowsdrag.h"
#include "qwindowscontext.h"
#include "qwindowsscreen.h"
@@ -45,7 +10,6 @@
#endif
#include "qwindowsintegration.h"
#include "qwindowsdropdataobject.h"
-#include <QtCore/qt_windows.h>
#include "qwindowswindow.h"
#include "qwindowsmousehandler.h"
#include "qwindowscursor.h"
@@ -64,6 +28,8 @@
#include <QtCore/qdebug.h>
#include <QtCore/qbuffer.h>
#include <QtCore/qpoint.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/private/qcomobject_p.h>
#include <shlobj.h>
@@ -75,7 +41,6 @@ QT_BEGIN_NAMESPACE
\sa QWindowsOleDropSource
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsDragCursorWindow : public QRasterWindow
@@ -135,7 +100,6 @@ void QWindowsDragCursorWindow::setPixmap(const QPixmap &p)
\sa QWindowsDrag
\internal
- \ingroup qt-lighthouse-win
*/
IDataObject *QWindowsDropMimeData::retrieveDataObject() const
@@ -192,20 +156,6 @@ static inline Qt::KeyboardModifiers toQtKeyboardModifiers(DWORD keyState)
return modifiers;
}
-static inline Qt::MouseButtons toQtMouseButtons(DWORD keyState)
-{
- Qt::MouseButtons buttons = Qt::NoButton;
-
- if (keyState & MK_LBUTTON)
- buttons |= Qt::LeftButton;
- if (keyState & MK_RBUTTON)
- buttons |= Qt::RightButton;
- if (keyState & MK_MBUTTON)
- buttons |= Qt::MidButton;
-
- return buttons;
-}
-
static Qt::KeyboardModifiers lastModifiers = Qt::NoModifier;
static Qt::MouseButtons lastButtons = Qt::NoButton;
@@ -217,10 +167,9 @@ static Qt::MouseButtons lastButtons = Qt::NoButton;
\sa QWindowsDrag
\internal
- \ingroup qt-lighthouse-win
*/
-class QWindowsOleDropSource : public QWindowsComBase<IDropSource>
+class QWindowsOleDropSource : public QComObject<IDropSource>
{
public:
enum Mode {
@@ -234,8 +183,8 @@ public:
void createCursors();
// IDropSource methods
- STDMETHOD(QueryContinueDrag)(BOOL fEscapePressed, DWORD grfKeyState);
- STDMETHOD(GiveFeedback)(DWORD dwEffect);
+ STDMETHOD(QueryContinueDrag)(BOOL fEscapePressed, DWORD grfKeyState) override;
+ STDMETHOD(GiveFeedback)(DWORD dwEffect) override;
private:
struct CursorEntry {
@@ -389,7 +338,10 @@ void QWindowsOleDropSource::createCursors()
QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
{
- Qt::MouseButtons buttons = toQtMouseButtons(grfKeyState);
+ // In some rare cases, when a mouse button is released but the mouse is static,
+ // grfKeyState will not be updated with these released buttons until the mouse
+ // is moved. So we use the async key state given by queryMouseButtons() instead.
+ Qt::MouseButtons buttons = QWindowsMouseHandler::queryMouseButtons();
SCODE result = S_OK;
if (fEscapePressed || QWindowsDrag::isCanceled()) {
@@ -398,7 +350,7 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
} else {
if (buttons && !m_currentButtons) {
m_currentButtons = buttons;
- } else if (!(m_currentButtons & buttons)) { // Button changed: Complete Drop operation.
+ } else if (m_currentButtons != buttons) { // Button changed: Complete Drop operation.
result = DRAGDROP_S_DROP;
}
}
@@ -434,7 +386,7 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
}
/*!
- \brief Give feedback: Change cursor accoding to action.
+ \brief Give feedback: Change cursor according to action.
*/
QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
@@ -485,7 +437,6 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect)
\sa QWindowsDrag
\internal
- \ingroup qt-lighthouse-win
*/
QWindowsOleDropTarget::QWindowsOleDropTarget(QWindow *w) : m_window(w)
@@ -509,7 +460,7 @@ void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState,
const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect);
lastModifiers = toQtKeyboardModifiers(grfKeyState);
- lastButtons = toQtMouseButtons(grfKeyState);
+ lastButtons = QWindowsMouseHandler::queryMouseButtons();
const QPlatformDragQtResponse response =
QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(),
@@ -577,7 +528,8 @@ QWindowsOleDropTarget::DragLeave()
qCDebug(lcQpaMime) << __FUNCTION__ << ' ' << m_window;
- lastModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
+ const auto *keyMapper = QWindowsContext::instance()->keyMapper();
+ lastModifiers = keyMapper->queryKeyboardModifiers();
lastButtons = QWindowsMouseHandler::queryMouseButtons();
QWindowSystemInterface::handleDrag(m_window, nullptr, QPoint(), Qt::IgnoreAction,
@@ -607,7 +559,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
QWindowsDrag *windowsDrag = QWindowsDrag::instance();
lastModifiers = toQtKeyboardModifiers(grfKeyState);
- lastButtons = toQtMouseButtons(grfKeyState);
+ lastButtons = QWindowsMouseHandler::queryMouseButtons();
const QPlatformDropQtResponse response =
QWindowSystemInterface::handleDrop(m_window, windowsDrag->dropData(),
@@ -659,11 +611,9 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
\class QWindowsDrag
\brief Windows drag implementation.
\internal
- \ingroup qt-lighthouse-win
*/
bool QWindowsDrag::m_canceled = false;
-bool QWindowsDrag::m_dragging = false;
QWindowsDrag::QWindowsDrag() = default;
@@ -696,6 +646,86 @@ IDropTargetHelper* QWindowsDrag::dropHelper() {
return m_cachedDropTargetHelper;
}
+// Workaround for DoDragDrop() not working with touch/pen input, causing DnD to hang until the mouse is moved.
+// We process pointer messages for touch/pen and generate mouse input through SendInput() to trigger DoDragDrop()
+static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource, DWORD dwOKEffects, LPDWORD pdwEffect)
+{
+ QWindow *underMouse = QWindowsContext::instance()->windowUnderMouse();
+ const bool hasMouseCapture = underMouse && static_cast<QWindowsWindow *>(underMouse->handle())->hasMouseCapture();
+ const HWND hwnd = hasMouseCapture ? reinterpret_cast<HWND>(underMouse->winId()) : ::GetFocus();
+ bool starting = false;
+
+ for (;;) {
+ MSG msg{};
+ if (::GetMessage(&msg, hwnd, 0, 0) > 0) {
+
+ if (msg.message == WM_MOUSEMOVE) {
+
+ // Only consider the first simulated event, or actual mouse messages.
+ if (!starting && (msg.wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | MK_XBUTTON1 | MK_XBUTTON2)) == 0)
+ return E_FAIL;
+
+ return ::DoDragDrop(pDataObj, pDropSource, dwOKEffects, pdwEffect);
+ }
+
+ if (msg.message == WM_POINTERUPDATE) {
+
+ const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
+
+ POINTER_INFO pointerInfo{};
+ if (!GetPointerInfo(pointerId, &pointerInfo))
+ return E_FAIL;
+
+ if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
+
+ DWORD flags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK | MOUSEEVENTF_MOVE;
+ if (IS_POINTER_FIRSTBUTTON_WPARAM(msg.wParam))
+ flags |= MOUSEEVENTF_LEFTDOWN;
+ if (IS_POINTER_SECONDBUTTON_WPARAM(msg.wParam))
+ flags |= MOUSEEVENTF_RIGHTDOWN;
+ if (IS_POINTER_THIRDBUTTON_WPARAM(msg.wParam))
+ flags |= MOUSEEVENTF_MIDDLEDOWN;
+
+ if (!starting) {
+ POINT pt{};
+ if (::GetCursorPos(&pt)) {
+
+ // Send mouse input that can generate a WM_MOUSEMOVE message.
+ if ((flags & MOUSEEVENTF_LEFTDOWN || flags & MOUSEEVENTF_RIGHTDOWN || flags & MOUSEEVENTF_MIDDLEDOWN)
+ && (pt.x != pointerInfo.ptPixelLocation.x || pt.y != pointerInfo.ptPixelLocation.y)) {
+
+ const int origin_x = ::GetSystemMetrics(SM_XVIRTUALSCREEN);
+ const int origin_y = ::GetSystemMetrics(SM_YVIRTUALSCREEN);
+ const int virt_w = ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ const int virt_h = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
+ const int virt_x = pointerInfo.ptPixelLocation.x - origin_x;
+ const int virt_y = pointerInfo.ptPixelLocation.y - origin_y;
+
+ INPUT input{};
+ input.type = INPUT_MOUSE;
+ input.mi.dx = static_cast<DWORD>(virt_x * (65535.0 / virt_w));
+ input.mi.dy = static_cast<DWORD>(virt_y * (65535.0 / virt_h));
+ input.mi.dwFlags = flags;
+
+ ::SendInput(1, &input, sizeof(input));
+ starting = true;
+ }
+ }
+ }
+ }
+ } else {
+ // Handle other messages.
+ qWindowsWndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
+
+ if (msg.message == WM_POINTERLEAVE)
+ return E_FAIL;
+ }
+ } else {
+ return E_FAIL;
+ }
+ }
+}
+
Qt::DropAction QWindowsDrag::drag(QDrag *drag)
{
// TODO: Accessibility handling?
@@ -711,10 +741,7 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag)
const DWORD allowedEffects = translateToWinDragEffects(possibleActions);
qCDebug(lcQpaMime) << '>' << __FUNCTION__ << "possible Actions=0x"
<< Qt::hex << int(possibleActions) << "effects=0x" << allowedEffects << Qt::dec;
- // Indicate message handlers we are in DoDragDrop() event loop.
- QWindowsDrag::m_dragging = true;
- const HRESULT r = DoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect);
- QWindowsDrag::m_dragging = false;
+ const HRESULT r = startDoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect);
const DWORD reportedPerformedEffect = dropDataObject->reportedPerformedEffect();
if (r == DRAGDROP_S_DROP) {
if (reportedPerformedEffect == DROPEFFECT_MOVE && resultEffect != DROPEFFECT_MOVE) {
diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h
index 5f30c59882..a2d0e54044 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.h
+++ b/src/plugins/platforms/windows/qwindowsdrag.h
@@ -1,51 +1,15 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSDRAG_H
#define QWINDOWSDRAG_H
-#include "qwindowscombase.h"
#include "qwindowsinternalmimedata.h"
#include <qpa/qplatformdrag.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qdrag.h>
+#include <QtCore/private/qcomobject_p.h>
struct IDropTargetHelper;
@@ -59,17 +23,19 @@ public:
IDataObject *retrieveDataObject() const override;
};
-class QWindowsOleDropTarget : public QWindowsComBase<IDropTarget>
+class QWindowsOleDropTarget : public QComObject<IDropTarget>
{
public:
explicit QWindowsOleDropTarget(QWindow *w);
~QWindowsOleDropTarget() override;
// IDropTarget methods
- STDMETHOD(DragEnter)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
- STDMETHOD(DragOver)(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
- STDMETHOD(DragLeave)();
- STDMETHOD(Drop)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
+ STDMETHOD(DragEnter)
+ (LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) override;
+ STDMETHOD(DragOver)(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) override;
+ STDMETHOD(DragLeave)() override;
+ STDMETHOD(Drop)
+ (LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) override;
private:
void handleDrag(QWindow *window, DWORD grfKeyState, const QPoint &, LPDWORD pdwEffect);
@@ -92,7 +58,6 @@ public:
static QWindowsDrag *instance();
void cancelDrag() override { QWindowsDrag::m_canceled = true; }
static bool isCanceled() { return QWindowsDrag::m_canceled; }
- static bool isDragging() { return QWindowsDrag::m_dragging; }
IDataObject *dropDataObject() const { return m_dropDataObject; }
void setDropDataObject(IDataObject *dataObject) { m_dropDataObject = dataObject; }
@@ -103,7 +68,6 @@ public:
private:
static bool m_canceled;
- static bool m_dragging;
QWindowsDropMimeData m_dropData;
IDataObject *m_dropDataObject = nullptr;
diff --git a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp
index c9dd1c7c17..629291640f 100644
--- a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp
+++ b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp
@@ -1,50 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsdropdataobject.h"
#include <QtCore/qurl.h>
#include <QtCore/qmimedata.h>
-#include "qwindowsmime.h"
+#include "qwindowsmimeregistry.h"
QT_BEGIN_NAMESPACE
+using namespace Qt::Literals::StringLiterals;
+
/*!
\class QWindowsDropDataObject
\brief QWindowsOleDataObject subclass specialized for handling Drag&Drop.
@@ -54,7 +20,6 @@ QT_BEGIN_NAMESPACE
(instead of creating local hyperlinks).
\internal
- \ingroup qt-lighthouse-win
*/
QWindowsDropDataObject::QWindowsDropDataObject(QMimeData *mimeData) :
@@ -90,11 +55,11 @@ bool QWindowsDropDataObject::shouldIgnore(LPFORMATETC pformatetc) const
QMimeData *dropData = mimeData();
if (dropData && dropData->formats().size() == 1 && dropData->hasUrls()) {
- QString formatName = QWindowsMimeConverter::clipboardFormatName(pformatetc->cfFormat);
+ QString formatName = QWindowsMimeRegistry::clipboardFormatName(pformatetc->cfFormat);
if (pformatetc->cfFormat == CF_UNICODETEXT
|| pformatetc->cfFormat == CF_TEXT
- || formatName == QStringLiteral("UniformResourceLocator")
- || formatName == QStringLiteral("UniformResourceLocatorW")) {
+ || formatName == "UniformResourceLocator"_L1
+ || formatName == "UniformResourceLocatorW"_L1) {
const auto urls = dropData->urls();
return std::all_of(urls.cbegin(), urls.cend(), [] (const QUrl &u) { return u.isLocalFile(); });
}
diff --git a/src/plugins/platforms/windows/qwindowsdropdataobject.h b/src/plugins/platforms/windows/qwindowsdropdataobject.h
index 16ba7b036a..b74a3dbc7e 100644
--- a/src/plugins/platforms/windows/qwindowsdropdataobject.h
+++ b/src/plugins/platforms/windows/qwindowsdropdataobject.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSDROPDATAOBJECT_H
#define QWINDOWSDROPDATAOBJECT_H
@@ -51,8 +15,8 @@ public:
~QWindowsDropDataObject() override;
// overridden IDataObject methods
- STDMETHOD(GetData)(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium);
- STDMETHOD(QueryGetData)(LPFORMATETC pformatetc);
+ STDMETHOD(GetData)(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium) override;
+ STDMETHOD(QueryGetData)(LPFORMATETC pformatetc) override;
private:
bool shouldIgnore(LPFORMATETC pformatetc) const;
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
deleted file mode 100644
index e9f3dc5189..0000000000
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ /dev/null
@@ -1,920 +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 "qwindowseglcontext.h"
-#include "qwindowscontext.h"
-#include "qwindowswindow.h"
-
-#include <QtCore/qdebug.h>
-#include <QtGui/qopenglcontext.h>
-
-#if defined(QT_OPENGL_ES_2_ANGLE) || defined(QT_OPENGL_DYNAMIC)
-# include <EGL/eglext.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QWindowsEGLStaticContext
- \brief Static data for QWindowsEGLContext.
-
- Keeps the display. The class is shared via QSharedPointer in the windows, the
- contexts and in QWindowsIntegration. The display will be closed if the last instance
- is deleted.
-
- No EGL or OpenGL functions are called directly. Instead, they are resolved
- dynamically. This works even if the plugin links directly to libegl/libglesv2 so
- there is no need to differentiate between dynamic or Angle-only builds in here.
-
- \internal
- \ingroup qt-lighthouse-win
-*/
-
-QWindowsLibEGL QWindowsEGLStaticContext::libEGL;
-QWindowsLibGLESv2 QWindowsEGLStaticContext::libGLESv2;
-
-#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
-
-#ifdef Q_CC_MINGW
-static void *resolveFunc(HMODULE lib, const char *name)
-{
- QString baseNameStr = QString::fromLatin1(name);
- QString nameStr;
- void *proc = 0;
-
- // Play nice with 32-bit mingw: Try func first, then func@0, func@4,
- // func@8, func@12, ..., func@64. The def file does not provide any aliases
- // in libEGL and libGLESv2 in these builds which results in exporting
- // function names like eglInitialize@12. This cannot be fixed without
- // breaking binary compatibility. So be flexible here instead.
-
- int argSize = -1;
- while (!proc && argSize <= 64) {
- nameStr = baseNameStr;
- if (argSize >= 0)
- nameStr += QLatin1Char('@') + QString::number(argSize);
- argSize = argSize < 0 ? 0 : argSize + 4;
- proc = (void *) ::GetProcAddress(lib, nameStr.toLatin1().constData());
- }
- return proc;
-}
-#else
-static inline void *resolveFunc(HMODULE lib, const char *name)
-{
- return ::GetProcAddress(lib, name);
-}
-#endif // Q_CC_MINGW
-
-void *QWindowsLibEGL::resolve(const char *name)
-{
- return m_lib ? resolveFunc(m_lib, name) : nullptr;
-}
-
-#endif // !QT_STATIC
-
-#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
-# define RESOLVE(signature, name) signature(resolve( #name ));
-#else
-# define RESOLVE(signature, name) signature(&::name);
-#endif
-
-bool QWindowsLibEGL::init()
-{
- const char dllName[] = QT_STRINGIFY(LIBEGL_NAME)
-#if defined(QT_DEBUG)
- "d"
-#endif
- "";
-
- qCDebug(lcQpaGl) << "Qt: Using EGL from" << dllName;
-
-#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
- m_lib = ::LoadLibraryW((const wchar_t *) QString::fromLatin1(dllName).utf16());
- if (!m_lib) {
- qErrnoWarning(::GetLastError(), "Failed to load %s", dllName);
- return false;
- }
-#endif
-
- eglGetError = RESOLVE((EGLint (EGLAPIENTRY *)(void)), eglGetError);
- eglGetDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(EGLNativeDisplayType)), eglGetDisplay);
- eglInitialize = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLint *, EGLint *)), eglInitialize);
- eglTerminate = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay)), eglTerminate);
- eglChooseConfig = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *)), eglChooseConfig);
- eglGetConfigAttrib = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLConfig, EGLint, EGLint *)), eglGetConfigAttrib);
- eglCreateWindowSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLDisplay, EGLConfig, EGLNativeWindowType, const EGLint *)), eglCreateWindowSurface);
- eglCreatePbufferSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLDisplay , EGLConfig, const EGLint *)), eglCreatePbufferSurface);
- eglDestroySurface = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface )), eglDestroySurface);
- eglBindAPI = RESOLVE((EGLBoolean (EGLAPIENTRY * )(EGLenum )), eglBindAPI);
- eglSwapInterval = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLint )), eglSwapInterval);
- eglCreateContext = RESOLVE((EGLContext (EGLAPIENTRY *)(EGLDisplay , EGLConfig , EGLContext , const EGLint *)), eglCreateContext);
- eglDestroyContext = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLContext)), eglDestroyContext);
- eglMakeCurrent = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface , EGLSurface , EGLContext )), eglMakeCurrent);
- eglGetCurrentContext = RESOLVE((EGLContext (EGLAPIENTRY *)(void)), eglGetCurrentContext);
- eglGetCurrentSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLint )), eglGetCurrentSurface);
- eglGetCurrentDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(void)), eglGetCurrentDisplay);
- eglSwapBuffers = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface)), eglSwapBuffers);
- eglGetProcAddress = RESOLVE((QFunctionPointer (EGLAPIENTRY * )(const char *)), eglGetProcAddress);
-
- if (!eglGetError || !eglGetDisplay || !eglInitialize || !eglGetProcAddress)
- return false;
-
- eglGetPlatformDisplayEXT = nullptr;
-#ifdef EGL_ANGLE_platform_angle
- eglGetPlatformDisplayEXT = reinterpret_cast<EGLDisplay (EGLAPIENTRY *)(EGLenum, void *, const EGLint *)>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
-#endif
-
- return true;
-}
-
-#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
-void *QWindowsLibGLESv2::resolve(const char *name)
-{
- return m_lib ? resolveFunc(m_lib, name) : nullptr;
-}
-#endif // !QT_STATIC
-
-bool QWindowsLibGLESv2::init()
-{
-
- const char dllName[] = QT_STRINGIFY(LIBGLESV2_NAME)
-#if defined(QT_DEBUG)
- "d"
-#endif
- "";
-
- qCDebug(lcQpaGl) << "Qt: Using OpenGL ES 2.0 from" << dllName;
-#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
- m_lib = ::LoadLibraryW(reinterpret_cast<LPCWSTR>(QString::fromLatin1(dllName).utf16()));
- if (!m_lib) {
- qErrnoWarning(int(GetLastError()), "Failed to load %s", dllName);
- return false;
- }
-#endif // !QT_STATIC
-
- void (APIENTRY * glBindTexture)(GLenum target, GLuint texture) = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindTexture);
- GLuint (APIENTRY * glCreateShader)(GLenum type) = RESOLVE((GLuint (APIENTRY *)(GLenum )), glCreateShader);
- void (APIENTRY * glClearDepthf)(GLclampf depth) = RESOLVE((void (APIENTRY *)(GLclampf )), glClearDepthf);
- glGetString = RESOLVE((const GLubyte * (APIENTRY *)(GLenum )), glGetString);
-
- return glBindTexture && glCreateShader && glClearDepthf;
-}
-
-QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display)
- : m_display(display)
-{
-}
-
-bool QWindowsEGLStaticContext::initializeAngle(QWindowsOpenGLTester::Renderers preferredType, HDC dc,
- EGLDisplay *display, EGLint *major, EGLint *minor)
-{
-#ifdef EGL_ANGLE_platform_angle
- if (libEGL.eglGetPlatformDisplayEXT
- && (preferredType & QWindowsOpenGLTester::AngleBackendMask)) {
- const EGLint anglePlatformAttributes[][5] = {
- { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE },
- { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_NONE },
- { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
- EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, EGL_NONE }
- };
- const EGLint *attributes = nullptr;
- if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11)
- attributes = anglePlatformAttributes[0];
- else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d9)
- attributes = anglePlatformAttributes[1];
- else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11Warp)
- attributes = anglePlatformAttributes[2];
- if (attributes) {
- *display = libEGL.eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc, attributes);
- if (!libEGL.eglInitialize(*display, major, minor)) {
- libEGL.eglTerminate(*display);
- *display = EGL_NO_DISPLAY;
- *major = *minor = 0;
- return false;
- }
- }
- }
-#else // EGL_ANGLE_platform_angle
- Q_UNUSED(preferredType);
- Q_UNUSED(dc);
- Q_UNUSED(display);
- Q_UNUSED(major);
- Q_UNUSED(minor);
-#endif
- return true;
-}
-
-QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester::Renderers preferredType)
-{
- const HDC dc = QWindowsContext::instance()->displayContext();
- if (!dc){
- qWarning("%s: No Display", __FUNCTION__);
- return nullptr;
- }
-
- if (!libEGL.init()) {
- qWarning("%s: Failed to load and resolve libEGL functions", __FUNCTION__);
- return nullptr;
- }
- if (!libGLESv2.init()) {
- qWarning("%s: Failed to load and resolve libGLESv2 functions", __FUNCTION__);
- return nullptr;
- }
-
- EGLDisplay display = EGL_NO_DISPLAY;
- EGLint major = 0;
- EGLint minor = 0;
-
- if (!initializeAngle(preferredType, dc, &display, &major, &minor)
- && (preferredType & QWindowsOpenGLTester::AngleRendererD3d11)) {
- preferredType &= ~QWindowsOpenGLTester::AngleRendererD3d11;
- initializeAngle(preferredType, dc, &display, &major, &minor);
- }
-
- if (display == EGL_NO_DISPLAY)
- display = libEGL.eglGetDisplay(dc);
- if (!display) {
- qWarning("%s: Could not obtain EGL display", __FUNCTION__);
- return nullptr;
- }
-
- if (!major && !libEGL.eglInitialize(display, &major, &minor)) {
- int err = libEGL.eglGetError();
- qWarning("%s: Could not initialize EGL display: error 0x%x", __FUNCTION__, err);
- if (err == 0x3001)
- qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", __FUNCTION__);
- return nullptr;
- }
-
- qCDebug(lcQpaGl) << __FUNCTION__ << "Created EGL display" << display << 'v' <<major << '.' << minor;
- return new QWindowsEGLStaticContext(display);
-}
-
-QWindowsEGLStaticContext::~QWindowsEGLStaticContext()
-{
- qCDebug(lcQpaGl) << __FUNCTION__ << "Releasing EGL display " << m_display;
- libEGL.eglTerminate(m_display);
-}
-
-QWindowsOpenGLContext *QWindowsEGLStaticContext::createContext(QOpenGLContext *context)
-{
- return new QWindowsEGLContext(this, context->format(), context->shareHandle());
-}
-
-void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig, int *err)
-{
- *err = 0;
- EGLSurface surface = libEGL.eglCreateWindowSurface(m_display, nativeConfig,
- static_cast<EGLNativeWindowType>(nativeWindow), nullptr);
- if (surface == EGL_NO_SURFACE) {
- *err = libEGL.eglGetError();
- qWarning("%s: Could not create the EGL window surface: 0x%x", __FUNCTION__, *err);
- }
-
- return surface;
-}
-
-void QWindowsEGLStaticContext::destroyWindowSurface(void *nativeSurface)
-{
- libEGL.eglDestroySurface(m_display, nativeSurface);
-}
-
-QSurfaceFormat QWindowsEGLStaticContext::formatFromConfig(EGLDisplay display, EGLConfig config,
- const QSurfaceFormat &referenceFormat)
-{
- QSurfaceFormat format;
- EGLint redSize = 0;
- EGLint greenSize = 0;
- EGLint blueSize = 0;
- EGLint alphaSize = 0;
- EGLint depthSize = 0;
- EGLint stencilSize = 0;
- EGLint sampleCount = 0;
-
- libEGL.eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize);
- libEGL.eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize);
- libEGL.eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize);
- libEGL.eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize);
- libEGL.eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize);
- libEGL.eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize);
- libEGL.eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount);
-
- format.setRenderableType(QSurfaceFormat::OpenGLES);
- format.setVersion(referenceFormat.majorVersion(), referenceFormat.minorVersion());
- format.setProfile(referenceFormat.profile());
- format.setOptions(referenceFormat.options());
-
- format.setRedBufferSize(redSize);
- format.setGreenBufferSize(greenSize);
- format.setBlueBufferSize(blueSize);
- format.setAlphaBufferSize(alphaSize);
- format.setDepthBufferSize(depthSize);
- format.setStencilBufferSize(stencilSize);
- format.setSamples(sampleCount);
- format.setStereo(false);
- format.setSwapInterval(referenceFormat.swapInterval());
-
- // Clear the EGL error state because some of the above may
- // have errored out because the attribute is not applicable
- // to the surface type. Such errors don't matter.
- libEGL.eglGetError();
-
- return format;
-}
-
-/*!
- \class QWindowsEGLContext
- \brief Open EGL context.
-
- \section1 Using QWindowsEGLContext for Desktop with ANGLE
- \section2 Build Instructions
- \list
- \o Install the Direct X SDK
- \o Checkout and build ANGLE (SVN repository) as explained here:
- \l{https://chromium.googlesource.com/angle/angle/+/master/README.md}
- When building for 64bit, de-activate the "WarnAsError" option
- in every project file (as otherwise integer conversion
- warnings will break the build).
- \o Run configure.exe with the options "-opengl es2".
- \o Build qtbase and test some examples.
- \endlist
-
- \internal
- \ingroup qt-lighthouse-win
-*/
-
-QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
- const QSurfaceFormat &format,
- QPlatformOpenGLContext *share)
- : m_staticContext(staticContext)
- , m_eglDisplay(staticContext->display())
-{
- if (!m_staticContext)
- return;
-
- m_eglConfig = chooseConfig(format);
- m_format = m_staticContext->formatFromConfig(m_eglDisplay, m_eglConfig, format);
- m_shareContext = share ? static_cast<QWindowsEGLContext *>(share)->m_eglContext : nullptr;
-
- QVector<EGLint> contextAttrs;
- const int major = m_format.majorVersion();
- const int minor = m_format.minorVersion();
- if (major > 3 || (major == 3 && minor > 0))
- qWarning("QWindowsEGLContext: ANGLE only partially supports OpenGL ES > 3.0");
- contextAttrs.append(EGL_CONTEXT_MAJOR_VERSION);
- contextAttrs.append(major);
- contextAttrs.append(EGL_CONTEXT_MINOR_VERSION);
- contextAttrs.append(minor);
- contextAttrs.append(EGL_NONE);
-
- QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
- m_eglContext = QWindowsEGLStaticContext::libEGL.eglCreateContext(m_eglDisplay, m_eglConfig, m_shareContext, contextAttrs.constData());
- if (m_eglContext == EGL_NO_CONTEXT && m_shareContext != EGL_NO_CONTEXT) {
- m_shareContext = nullptr;
- m_eglContext = QWindowsEGLStaticContext::libEGL.eglCreateContext(m_eglDisplay, m_eglConfig, nullptr, contextAttrs.constData());
- }
-
- if (m_eglContext == EGL_NO_CONTEXT) {
- int err = QWindowsEGLStaticContext::libEGL.eglGetError();
- qWarning("QWindowsEGLContext: Failed to create context, eglError: %x, this: %p", err, this);
- // ANGLE gives bad alloc when it fails to reset a previously lost D3D device.
- // A common cause for this is disabling the graphics adapter used by the app.
- if (err == EGL_BAD_ALLOC)
- qWarning("QWindowsEGLContext: Graphics device lost. (Did the adapter get disabled?)");
- return;
- }
-
- // Make the context current to ensure the GL version query works. This needs a surface too.
- const EGLint pbufferAttributes[] = {
- EGL_WIDTH, 1,
- EGL_HEIGHT, 1,
- EGL_LARGEST_PBUFFER, EGL_FALSE,
- EGL_NONE
- };
- EGLSurface pbuffer = QWindowsEGLStaticContext::libEGL.eglCreatePbufferSurface(m_eglDisplay, m_eglConfig, pbufferAttributes);
- if (pbuffer == EGL_NO_SURFACE)
- return;
-
- EGLDisplay prevDisplay = QWindowsEGLStaticContext::libEGL.eglGetCurrentDisplay();
- if (prevDisplay == EGL_NO_DISPLAY) // when no context is current
- prevDisplay = m_eglDisplay;
- EGLContext prevContext = QWindowsEGLStaticContext::libEGL.eglGetCurrentContext();
- EGLSurface prevSurfaceDraw = QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_DRAW);
- EGLSurface prevSurfaceRead = QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_READ);
-
- if (QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, pbuffer, pbuffer, m_eglContext)) {
- const GLubyte *s = QWindowsEGLStaticContext::libGLESv2.glGetString(GL_VERSION);
- if (s) {
- QByteArray version = QByteArray(reinterpret_cast<const char *>(s));
- int major, minor;
- if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) {
- m_format.setMajorVersion(major);
- m_format.setMinorVersion(minor);
- }
- }
- m_format.setProfile(QSurfaceFormat::NoProfile);
- m_format.setOptions(QSurfaceFormat::FormatOptions());
- QWindowsEGLStaticContext::libEGL.eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext);
- }
- QWindowsEGLStaticContext::libEGL.eglDestroySurface(m_eglDisplay, pbuffer);
-}
-
-QWindowsEGLContext::~QWindowsEGLContext()
-{
- if (m_eglContext != EGL_NO_CONTEXT) {
- QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext);
- m_eglContext = EGL_NO_CONTEXT;
- }
-}
-
-bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
-{
- Q_ASSERT(surface->surface()->supportsOpenGL());
-
- QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
-
- auto *window = static_cast<QWindowsWindow *>(surface);
- window->aboutToMakeCurrent();
- int err = 0;
- auto eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
- if (eglSurface == EGL_NO_SURFACE) {
- if (err == EGL_CONTEXT_LOST) {
- m_eglContext = EGL_NO_CONTEXT;
- qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this;
- } else if (err == EGL_BAD_ACCESS) {
- // With ANGLE this means no (D3D) device and can happen when disabling/changing graphics adapters.
- qCDebug(lcQpaGl) << "Bad access (missing device?) in createWindowSurface() for context" << this;
- // Simulate context loss as the context is useless.
- QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext);
- m_eglContext = EGL_NO_CONTEXT;
- }
- return false;
- }
-
- // shortcut: on some GPUs, eglMakeCurrent is not a cheap operation
- if (QWindowsEGLStaticContext::libEGL.eglGetCurrentContext() == m_eglContext &&
- QWindowsEGLStaticContext::libEGL.eglGetCurrentDisplay() == m_eglDisplay &&
- QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_READ) == eglSurface &&
- QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_DRAW) == eglSurface) {
- return true;
- }
-
- const bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_eglContext);
- if (ok) {
- const int requestedSwapInterval = surface->format().swapInterval();
- if (requestedSwapInterval >= 0 && m_swapInterval != requestedSwapInterval) {
- m_swapInterval = requestedSwapInterval;
- QWindowsEGLStaticContext::libEGL.eglSwapInterval(m_staticContext->display(), m_swapInterval);
- }
- } else {
- err = QWindowsEGLStaticContext::libEGL.eglGetError();
- // EGL_CONTEXT_LOST (loss of the D3D device) is not necessarily fatal.
- // Qt Quick is able to recover for example.
- if (err == EGL_CONTEXT_LOST) {
- m_eglContext = EGL_NO_CONTEXT;
- qCDebug(lcQpaGl) << "Got EGL context lost in makeCurrent() for context" << this;
- // Drop the surface. Will recreate on the next makeCurrent.
- window->invalidateSurface();
- } else {
- qWarning("%s: Failed to make surface current. eglError: %x, this: %p", __FUNCTION__, err, this);
- }
- }
-
- return ok;
-}
-
-void QWindowsEGLContext::doneCurrent()
-{
- QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
- bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- if (!ok)
- qWarning("%s: Failed to make no context/surface current. eglError: %d, this: %p", __FUNCTION__,
- QWindowsEGLStaticContext::libEGL.eglGetError(), this);
-}
-
-void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
-{
- QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
- auto *window = static_cast<QWindowsWindow *>(surface);
- int err = 0;
- auto eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
- if (eglSurface == EGL_NO_SURFACE) {
- if (err == EGL_CONTEXT_LOST) {
- m_eglContext = EGL_NO_CONTEXT;
- qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this;
- }
- return;
- }
-
- bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface);
- if (!ok) {
- err = QWindowsEGLStaticContext::libEGL.eglGetError();
- if (err == EGL_CONTEXT_LOST) {
- m_eglContext = EGL_NO_CONTEXT;
- qCDebug(lcQpaGl) << "Got EGL context lost in eglSwapBuffers()";
- } else {
- qWarning("%s: Failed to swap buffers. eglError: %d, this: %p", __FUNCTION__, err, this);
- }
- }
-}
-
-QFunctionPointer QWindowsEGLContext::getProcAddress(const char *procName)
-{
- QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
-
- QFunctionPointer procAddress = nullptr;
-
- // Special logic for ANGLE extensions for blitFramebuffer and
- // renderbufferStorageMultisample. In version 2 contexts the extensions
- // must be used instead of the suffixless, version 3.0 functions.
- if (m_format.majorVersion() < 3) {
- if (!strcmp(procName, "glBlitFramebuffer") || !strcmp(procName, "glRenderbufferStorageMultisample")) {
- char extName[32 + 5 + 1];
- strcpy(extName, procName);
- strcat(extName, "ANGLE");
- procAddress = reinterpret_cast<QFunctionPointer>(QWindowsEGLStaticContext::libEGL.eglGetProcAddress(extName));
- }
- }
-
- if (!procAddress)
- procAddress = reinterpret_cast<QFunctionPointer>(QWindowsEGLStaticContext::libEGL.eglGetProcAddress(procName));
-
- // We support AllGLFunctionsQueryable, which means this function must be able to
- // return a function pointer for standard GLES2 functions too. These are not
- // guaranteed to be queryable via eglGetProcAddress().
- if (!procAddress) {
-#if defined(QT_STATIC) && !defined(QT_OPENGL_DYNAMIC)
- static struct StdFunc {
- const char *name;
- void *func;
- } standardFuncs[] = {
- { "glBindTexture", (void *) ::glBindTexture },
- { "glBlendFunc", (void *) ::glBlendFunc },
- { "glClear", (void *) ::glClear },
- { "glClearColor", (void *) ::glClearColor },
- { "glClearStencil", (void *) ::glClearStencil },
- { "glColorMask", (void *) ::glColorMask },
- { "glCopyTexImage2D", (void *) ::glCopyTexImage2D },
- { "glCopyTexSubImage2D", (void *) ::glCopyTexSubImage2D },
- { "glCullFace", (void *) ::glCullFace },
- { "glDeleteTextures", (void *) ::glDeleteTextures },
- { "glDepthFunc", (void *) ::glDepthFunc },
- { "glDepthMask", (void *) ::glDepthMask },
- { "glDisable", (void *) ::glDisable },
- { "glDrawArrays", (void *) ::glDrawArrays },
- { "glDrawElements", (void *) ::glDrawElements },
- { "glEnable", (void *) ::glEnable },
- { "glFinish", (void *) ::glFinish },
- { "glFlush", (void *) ::glFlush },
- { "glFrontFace", (void *) ::glFrontFace },
- { "glGenTextures", (void *) ::glGenTextures },
- { "glGetBooleanv", (void *) ::glGetBooleanv },
- { "glGetError", (void *) ::glGetError },
- { "glGetFloatv", (void *) ::glGetFloatv },
- { "glGetIntegerv", (void *) ::glGetIntegerv },
- { "glGetString", (void *) ::glGetString },
- { "glGetTexParameterfv", (void *) ::glGetTexParameterfv },
- { "glGetTexParameteriv", (void *) ::glGetTexParameteriv },
- { "glHint", (void *) ::glHint },
- { "glIsEnabled", (void *) ::glIsEnabled },
- { "glIsTexture", (void *) ::glIsTexture },
- { "glLineWidth", (void *) ::glLineWidth },
- { "glPixelStorei", (void *) ::glPixelStorei },
- { "glPolygonOffset", (void *) ::glPolygonOffset },
- { "glReadPixels", (void *) ::glReadPixels },
- { "glScissor", (void *) ::glScissor },
- { "glStencilFunc", (void *) ::glStencilFunc },
- { "glStencilMask", (void *) ::glStencilMask },
- { "glStencilOp", (void *) ::glStencilOp },
- { "glTexImage2D", (void *) ::glTexImage2D },
- { "glTexParameterf", (void *) ::glTexParameterf },
- { "glTexParameterfv", (void *) ::glTexParameterfv },
- { "glTexParameteri", (void *) ::glTexParameteri },
- { "glTexParameteriv", (void *) ::glTexParameteriv },
- { "glTexSubImage2D", (void *) ::glTexSubImage2D },
- { "glViewport", (void *) ::glViewport },
-
- { "glActiveTexture", (void *) ::glActiveTexture },
- { "glAttachShader", (void *) ::glAttachShader },
- { "glBindAttribLocation", (void *) ::glBindAttribLocation },
- { "glBindBuffer", (void *) ::glBindBuffer },
- { "glBindFramebuffer", (void *) ::glBindFramebuffer },
- { "glBindRenderbuffer", (void *) ::glBindRenderbuffer },
- { "glBlendColor", (void *) ::glBlendColor },
- { "glBlendEquation", (void *) ::glBlendEquation },
- { "glBlendEquationSeparate", (void *) ::glBlendEquationSeparate },
- { "glBlendFuncSeparate", (void *) ::glBlendFuncSeparate },
- { "glBufferData", (void *) ::glBufferData },
- { "glBufferSubData", (void *) ::glBufferSubData },
- { "glCheckFramebufferStatus", (void *) ::glCheckFramebufferStatus },
- { "glCompileShader", (void *) ::glCompileShader },
- { "glCompressedTexImage2D", (void *) ::glCompressedTexImage2D },
- { "glCompressedTexSubImage2D", (void *) ::glCompressedTexSubImage2D },
- { "glCreateProgram", (void *) ::glCreateProgram },
- { "glCreateShader", (void *) ::glCreateShader },
- { "glDeleteBuffers", (void *) ::glDeleteBuffers },
- { "glDeleteFramebuffers", (void *) ::glDeleteFramebuffers },
- { "glDeleteProgram", (void *) ::glDeleteProgram },
- { "glDeleteRenderbuffers", (void *) ::glDeleteRenderbuffers },
- { "glDeleteShader", (void *) ::glDeleteShader },
- { "glDetachShader", (void *) ::glDetachShader },
- { "glDisableVertexAttribArray", (void *) ::glDisableVertexAttribArray },
- { "glEnableVertexAttribArray", (void *) ::glEnableVertexAttribArray },
- { "glFramebufferRenderbuffer", (void *) ::glFramebufferRenderbuffer },
- { "glFramebufferTexture2D", (void *) ::glFramebufferTexture2D },
- { "glGenBuffers", (void *) ::glGenBuffers },
- { "glGenerateMipmap", (void *) ::glGenerateMipmap },
- { "glGenFramebuffers", (void *) ::glGenFramebuffers },
- { "glGenRenderbuffers", (void *) ::glGenRenderbuffers },
- { "glGetActiveAttrib", (void *) ::glGetActiveAttrib },
- { "glGetActiveUniform", (void *) ::glGetActiveUniform },
- { "glGetAttachedShaders", (void *) ::glGetAttachedShaders },
- { "glGetAttribLocation", (void *) ::glGetAttribLocation },
- { "glGetBufferParameteriv", (void *) ::glGetBufferParameteriv },
- { "glGetFramebufferAttachmentParameteriv", (void *) ::glGetFramebufferAttachmentParameteriv },
- { "glGetProgramiv", (void *) ::glGetProgramiv },
- { "glGetProgramInfoLog", (void *) ::glGetProgramInfoLog },
- { "glGetRenderbufferParameteriv", (void *) ::glGetRenderbufferParameteriv },
- { "glGetShaderiv", (void *) ::glGetShaderiv },
- { "glGetShaderInfoLog", (void *) ::glGetShaderInfoLog },
- { "glGetShaderPrecisionFormat", (void *) ::glGetShaderPrecisionFormat },
- { "glGetShaderSource", (void *) ::glGetShaderSource },
- { "glGetUniformfv", (void *) ::glGetUniformfv },
- { "glGetUniformiv", (void *) ::glGetUniformiv },
- { "glGetUniformLocation", (void *) ::glGetUniformLocation },
- { "glGetVertexAttribfv", (void *) ::glGetVertexAttribfv },
- { "glGetVertexAttribiv", (void *) ::glGetVertexAttribiv },
- { "glGetVertexAttribPointerv", (void *) ::glGetVertexAttribPointerv },
- { "glIsBuffer", (void *) ::glIsBuffer },
- { "glIsFramebuffer", (void *) ::glIsFramebuffer },
- { "glIsProgram", (void *) ::glIsProgram },
- { "glIsRenderbuffer", (void *) ::glIsRenderbuffer },
- { "glIsShader", (void *) ::glIsShader },
- { "glLinkProgram", (void *) ::glLinkProgram },
- { "glReleaseShaderCompiler", (void *) ::glReleaseShaderCompiler },
- { "glRenderbufferStorage", (void *) ::glRenderbufferStorage },
- { "glSampleCoverage", (void *) ::glSampleCoverage },
- { "glShaderBinary", (void *) ::glShaderBinary },
- { "glShaderSource", (void *) ::glShaderSource },
- { "glStencilFuncSeparate", (void *) ::glStencilFuncSeparate },
- { "glStencilMaskSeparate", (void *) ::glStencilMaskSeparate },
- { "glStencilOpSeparate", (void *) ::glStencilOpSeparate },
- { "glUniform1f", (void *) ::glUniform1f },
- { "glUniform1fv", (void *) ::glUniform1fv },
- { "glUniform1i", (void *) ::glUniform1i },
- { "glUniform1iv", (void *) ::glUniform1iv },
- { "glUniform2f", (void *) ::glUniform2f },
- { "glUniform2fv", (void *) ::glUniform2fv },
- { "glUniform2i", (void *) ::glUniform2i },
- { "glUniform2iv", (void *) ::glUniform2iv },
- { "glUniform3f", (void *) ::glUniform3f },
- { "glUniform3fv", (void *) ::glUniform3fv },
- { "glUniform3i", (void *) ::glUniform3i },
- { "glUniform3iv", (void *) ::glUniform3iv },
- { "glUniform4f", (void *) ::glUniform4f },
- { "glUniform4fv", (void *) ::glUniform4fv },
- { "glUniform4i", (void *) ::glUniform4i },
- { "glUniform4iv", (void *) ::glUniform4iv },
- { "glUniformMatrix2fv", (void *) ::glUniformMatrix2fv },
- { "glUniformMatrix3fv", (void *) ::glUniformMatrix3fv },
- { "glUniformMatrix4fv", (void *) ::glUniformMatrix4fv },
- { "glUseProgram", (void *) ::glUseProgram },
- { "glValidateProgram", (void *) ::glValidateProgram },
- { "glVertexAttrib1f", (void *) ::glVertexAttrib1f },
- { "glVertexAttrib1fv", (void *) ::glVertexAttrib1fv },
- { "glVertexAttrib2f", (void *) ::glVertexAttrib2f },
- { "glVertexAttrib2fv", (void *) ::glVertexAttrib2fv },
- { "glVertexAttrib3f", (void *) ::glVertexAttrib3f },
- { "glVertexAttrib3fv", (void *) ::glVertexAttrib3fv },
- { "glVertexAttrib4f", (void *) ::glVertexAttrib4f },
- { "glVertexAttrib4fv", (void *) ::glVertexAttrib4fv },
- { "glVertexAttribPointer", (void *) ::glVertexAttribPointer },
-
- { "glClearDepthf", (void *) ::glClearDepthf },
- { "glDepthRangef", (void *) ::glDepthRangef }
- };
- for (size_t i = 0; i < sizeof(standardFuncs) / sizeof(StdFunc); ++i)
- if (!qstrcmp(procName, standardFuncs[i].name))
- return reinterpret_cast<QFunctionPointer>(standardFuncs[i].func);
-#else
- procAddress = reinterpret_cast<QFunctionPointer>(QWindowsEGLStaticContext::libGLESv2.resolve(procName));
-#endif
-}
-
- if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaGl) << __FUNCTION__ << procName << QWindowsEGLStaticContext::libEGL.eglGetCurrentContext() << "returns" << procAddress;
-
- return procAddress;
-}
-
-static QVector<EGLint> createConfigAttributesFromFormat(const QSurfaceFormat &format)
-{
- int redSize = format.redBufferSize();
- int greenSize = format.greenBufferSize();
- int blueSize = format.blueBufferSize();
- int alphaSize = format.alphaBufferSize();
- int depthSize = format.depthBufferSize();
- int stencilSize = format.stencilBufferSize();
- int sampleCount = format.samples();
-
- QVector<EGLint> configAttributes;
- configAttributes.reserve(16);
-
- configAttributes.append(EGL_RED_SIZE);
- configAttributes.append(redSize > 0 ? redSize : 0);
-
- configAttributes.append(EGL_GREEN_SIZE);
- configAttributes.append(greenSize > 0 ? greenSize : 0);
-
- configAttributes.append(EGL_BLUE_SIZE);
- configAttributes.append(blueSize > 0 ? blueSize : 0);
-
- configAttributes.append(EGL_ALPHA_SIZE);
- configAttributes.append(alphaSize > 0 ? alphaSize : 0);
-
- configAttributes.append(EGL_DEPTH_SIZE);
- configAttributes.append(depthSize > 0 ? depthSize : 0);
-
- configAttributes.append(EGL_STENCIL_SIZE);
- configAttributes.append(stencilSize > 0 ? stencilSize : 0);
-
- configAttributes.append(EGL_SAMPLES);
- configAttributes.append(sampleCount > 0 ? sampleCount : 0);
-
- configAttributes.append(EGL_SAMPLE_BUFFERS);
- configAttributes.append(sampleCount > 0);
-
- return configAttributes;
-}
-
-static bool reduceConfigAttributes(QVector<EGLint> *configAttributes)
-{
- int i = -1;
-
- i = configAttributes->indexOf(EGL_SWAP_BEHAVIOR);
- if (i >= 0) {
- configAttributes->remove(i,2);
- }
-
- i = configAttributes->indexOf(EGL_BUFFER_SIZE);
- if (i >= 0) {
- if (configAttributes->at(i+1) == 16) {
- configAttributes->remove(i,2);
- return true;
- }
- }
-
- i = configAttributes->indexOf(EGL_SAMPLES);
- if (i >= 0) {
- EGLint value = configAttributes->value(i+1, 0);
- if (value > 1)
- configAttributes->replace(i+1, qMin(EGLint(16), value / 2));
- else
- configAttributes->remove(i, 2);
- return true;
- }
-
- i = configAttributes->indexOf(EGL_SAMPLE_BUFFERS);
- if (i >= 0) {
- configAttributes->remove(i,2);
- return true;
- }
-
- i = configAttributes->indexOf(EGL_ALPHA_SIZE);
- if (i >= 0) {
- configAttributes->remove(i,2);
-#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB)
- i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGBA);
- if (i >= 0) {
- configAttributes->replace(i,EGL_BIND_TO_TEXTURE_RGB);
- configAttributes->replace(i+1,true);
-
- }
-#endif
- return true;
- }
-
- i = configAttributes->indexOf(EGL_STENCIL_SIZE);
- if (i >= 0) {
- if (configAttributes->at(i + 1) > 1)
- configAttributes->replace(i + 1, 1);
- else
- configAttributes->remove(i, 2);
- return true;
- }
-
- i = configAttributes->indexOf(EGL_DEPTH_SIZE);
- if (i >= 0) {
- if (configAttributes->at(i + 1) > 1)
- configAttributes->replace(i + 1, 1);
- else
- configAttributes->remove(i, 2);
- return true;
- }
-#ifdef EGL_BIND_TO_TEXTURE_RGB
- i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGB);
- if (i >= 0) {
- configAttributes->remove(i,2);
- return true;
- }
-#endif
-
- return false;
-}
-
-EGLConfig QWindowsEGLContext::chooseConfig(const QSurfaceFormat &format)
-{
- QVector<EGLint> configureAttributes = createConfigAttributesFromFormat(format);
- configureAttributes.append(EGL_SURFACE_TYPE);
- configureAttributes.append(EGL_WINDOW_BIT);
- configureAttributes.append(EGL_RENDERABLE_TYPE);
- configureAttributes.append(EGL_OPENGL_ES2_BIT);
- configureAttributes.append(EGL_NONE);
-
- EGLDisplay display = m_staticContext->display();
- EGLConfig cfg = nullptr;
- do {
- // Get the number of matching configurations for this set of properties.
- EGLint matching = 0;
- if (!QWindowsEGLStaticContext::libEGL.eglChooseConfig(display, configureAttributes.constData(), nullptr, 0, &matching) || !matching)
- continue;
-
- // Fetch all of the matching configurations and find the
- // first that matches the pixel format we wanted.
- int i = configureAttributes.indexOf(EGL_RED_SIZE);
- int confAttrRed = configureAttributes.at(i+1);
- i = configureAttributes.indexOf(EGL_GREEN_SIZE);
- int confAttrGreen = configureAttributes.at(i+1);
- i = configureAttributes.indexOf(EGL_BLUE_SIZE);
- int confAttrBlue = configureAttributes.at(i+1);
- i = configureAttributes.indexOf(EGL_ALPHA_SIZE);
- int confAttrAlpha = i == -1 ? 0 : configureAttributes.at(i+1);
-
- QVector<EGLConfig> configs(matching);
- QWindowsEGLStaticContext::libEGL.eglChooseConfig(display, configureAttributes.constData(), configs.data(), configs.size(), &matching);
- if (!cfg && matching > 0)
- cfg = configs.constFirst();
-
- EGLint red = 0;
- EGLint green = 0;
- EGLint blue = 0;
- EGLint alpha = 0;
- for (const EGLConfig &config : configs) {
- if (confAttrRed)
- QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, config, EGL_RED_SIZE, &red);
- if (confAttrGreen)
- QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &green);
- if (confAttrBlue)
- QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blue);
- if (confAttrAlpha)
- QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alpha);
-
- if (red == confAttrRed && green == confAttrGreen
- && blue == confAttrBlue && alpha == confAttrAlpha)
- return config;
- }
- } while (reduceConfigAttributes(&configureAttributes));
-
- if (!cfg)
- qWarning("Cannot find EGLConfig, returning null config");
-
- return cfg;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
deleted file mode 100644
index d96e266159..0000000000
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ /dev/null
@@ -1,176 +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$
-**
-****************************************************************************/
-
-#ifndef QWINDOWSEGLCONTEXT_H
-#define QWINDOWSEGLCONTEXT_H
-
-#include "qwindowsopenglcontext.h"
-#include "qwindowsopengltester.h"
-#include <EGL/egl.h>
-
-QT_BEGIN_NAMESPACE
-
-struct QWindowsLibEGL
-{
- bool init();
-
- EGLint (EGLAPIENTRY * eglGetError)(void);
- EGLDisplay (EGLAPIENTRY * eglGetDisplay)(EGLNativeDisplayType display_id);
- EGLBoolean (EGLAPIENTRY * eglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
- EGLBoolean (EGLAPIENTRY * eglTerminate)(EGLDisplay dpy);
- EGLBoolean (EGLAPIENTRY * eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list,
- EGLConfig *configs, EGLint config_size,
- EGLint *num_config);
- EGLBoolean (EGLAPIENTRY * eglGetConfigAttrib)(EGLDisplay dpy, EGLConfig config,
- EGLint attribute, EGLint *value);
- EGLSurface (EGLAPIENTRY * eglCreateWindowSurface)(EGLDisplay dpy, EGLConfig config,
- EGLNativeWindowType win,
- const EGLint *attrib_list);
- EGLSurface (EGLAPIENTRY * eglCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config,
- const EGLint *attrib_list);
- EGLBoolean (EGLAPIENTRY * eglDestroySurface)(EGLDisplay dpy, EGLSurface surface);
- EGLBoolean (EGLAPIENTRY * eglBindAPI)(EGLenum api);
- EGLBoolean (EGLAPIENTRY * eglSwapInterval)(EGLDisplay dpy, EGLint interval);
- EGLContext (EGLAPIENTRY * eglCreateContext)(EGLDisplay dpy, EGLConfig config,
- EGLContext share_context,
- const EGLint *attrib_list);
- EGLBoolean (EGLAPIENTRY * eglDestroyContext)(EGLDisplay dpy, EGLContext ctx);
- EGLBoolean (EGLAPIENTRY * eglMakeCurrent)(EGLDisplay dpy, EGLSurface draw,
- EGLSurface read, EGLContext ctx);
- EGLContext (EGLAPIENTRY * eglGetCurrentContext)(void);
- EGLSurface (EGLAPIENTRY * eglGetCurrentSurface)(EGLint readdraw);
- EGLDisplay (EGLAPIENTRY * eglGetCurrentDisplay)(void);
- EGLBoolean (EGLAPIENTRY * eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
- QFunctionPointer (EGLAPIENTRY *eglGetProcAddress)(const char *procname);
-
- EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list);
-
-private:
-#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
- void *resolve(const char *name);
- HMODULE m_lib;
-#endif
-};
-
-struct QWindowsLibGLESv2
-{
- bool init();
-
-#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
- void *moduleHandle() const { return m_lib; }
-#else
- void *moduleHandle() const { return nullptr; }
-#endif
-
- const GLubyte * (APIENTRY * glGetString)(GLenum name);
-
-#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
- void *resolve(const char *name);
-private:
- HMODULE m_lib;
-#endif
-};
-
-class QWindowsEGLStaticContext : public QWindowsStaticOpenGLContext
-{
- Q_DISABLE_COPY_MOVE(QWindowsEGLStaticContext)
-
-public:
- static QWindowsEGLStaticContext *create(QWindowsOpenGLTester::Renderers preferredType);
- ~QWindowsEGLStaticContext() override;
-
- EGLDisplay display() const { return m_display; }
-
- QWindowsOpenGLContext *createContext(QOpenGLContext *context) override;
- void *moduleHandle() const override { return libGLESv2.moduleHandle(); }
- QOpenGLContext::OpenGLModuleType moduleType() const override { return QOpenGLContext::LibGLES; }
-
- void *createWindowSurface(void *nativeWindow, void *nativeConfig, int *err) override;
- void destroyWindowSurface(void *nativeSurface) override;
-
- QSurfaceFormat formatFromConfig(EGLDisplay display, EGLConfig config, const QSurfaceFormat &referenceFormat);
-
- static QWindowsLibEGL libEGL;
- static QWindowsLibGLESv2 libGLESv2;
-
-private:
- explicit QWindowsEGLStaticContext(EGLDisplay display);
- static bool initializeAngle(QWindowsOpenGLTester::Renderers preferredType, HDC dc,
- EGLDisplay *display, EGLint *major, EGLint *minor);
-
- const EGLDisplay m_display;
-};
-
-class QWindowsEGLContext : public QWindowsOpenGLContext
-{
-public:
- QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
- const QSurfaceFormat &format,
- QPlatformOpenGLContext *share);
- ~QWindowsEGLContext() override;
-
- bool makeCurrent(QPlatformSurface *surface) override;
- void doneCurrent() override;
- void swapBuffers(QPlatformSurface *surface) override;
- QFunctionPointer getProcAddress(const char *procName) override;
-
- QSurfaceFormat format() const override { return m_format; }
- bool isSharing() const override { return m_shareContext != EGL_NO_CONTEXT; }
- bool isValid() const override { return m_eglContext != EGL_NO_CONTEXT; }
-
- void *nativeContext() const override { return m_eglContext; }
- void *nativeDisplay() const override { return m_eglDisplay; }
- void *nativeConfig() const override { return m_eglConfig; }
-
-private:
- EGLConfig chooseConfig(const QSurfaceFormat &format);
-
- QWindowsEGLStaticContext *m_staticContext;
- EGLContext m_eglContext;
- EGLContext m_shareContext;
- EGLDisplay m_eglDisplay;
- EGLConfig m_eglConfig;
- QSurfaceFormat m_format;
- EGLenum m_api = EGL_OPENGL_ES_API;
- int m_swapInterval = -1;
-};
-
-QT_END_NAMESPACE
-
-#endif // QWINDOWSEGLCONTEXT_H
diff --git a/src/plugins/platforms/windows/qwindowsgdiintegration.cpp b/src/plugins/platforms/windows/qwindowsgdiintegration.cpp
index c88f669eb5..14fd03fc1f 100644
--- a/src/plugins/platforms/windows/qwindowsgdiintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsgdiintegration.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsgdiintegration.h"
#include "qwindowscontext.h"
diff --git a/src/plugins/platforms/windows/qwindowsgdiintegration.h b/src/plugins/platforms/windows/qwindowsgdiintegration.h
index 74ce3ffd49..fbb6b7460d 100644
--- a/src/plugins/platforms/windows/qwindowsgdiintegration.h
+++ b/src/plugins/platforms/windows/qwindowsgdiintegration.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSGDIINTEGRATION_H
#define QWINDOWSGDIINTEGRATION_H
diff --git a/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp b/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp
index f2418b0e60..78325c88d1 100644
--- a/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsgdinativeinterface.h"
#include "qwindowsbackingstore.h"
diff --git a/src/plugins/platforms/windows/qwindowsgdinativeinterface.h b/src/plugins/platforms/windows/qwindowsgdinativeinterface.h
index c86d3cbb47..7ef1244db3 100644
--- a/src/plugins/platforms/windows/qwindowsgdinativeinterface.h
+++ b/src/plugins/platforms/windows/qwindowsgdinativeinterface.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSGDINATIVEINTERFACE_H
#define QWINDOWSGDINATIVEINTERFACE_H
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index d9521e7e08..5ca52c2c19 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsglcontext.h"
#include "qwindowscontext.h"
@@ -44,10 +8,10 @@
#include <QtCore/qdebug.h>
#include <QtCore/qsysinfo.h>
+#include <QtGui/qcolorspace.h>
#include <QtGui/qguiapplication.h>
#include <qpa/qplatformnativeinterface.h>
-#include <QtPlatformHeaders/qwglnativecontext.h>
-
+#include <private/qsystemlibrary_p.h>
#include <algorithm>
#include <wingdi.h>
@@ -162,19 +126,25 @@ QFunctionPointer QWindowsOpengl32DLL::resolve(const char *name)
bool QWindowsOpengl32DLL::init(bool softwareRendering)
{
- const QByteArray opengl32 = QByteArrayLiteral("opengl32.dll");
- const QByteArray swopengl = QByteArrayLiteral("opengl32sw.dll");
+ const QByteArray opengl32 = QByteArrayLiteral("opengl32");
+ const QByteArray swopengl = QByteArrayLiteral("opengl32sw");
+ bool useSystemLib = false;
QByteArray openglDll = qgetenv("QT_OPENGL_DLL");
- if (openglDll.isEmpty())
+ if (openglDll.isEmpty()) {
openglDll = softwareRendering ? swopengl : opengl32;
+ useSystemLib = !softwareRendering;
+ }
openglDll = openglDll.toLower();
m_nonOpengl32 = openglDll != opengl32;
qCDebug(lcQpaGl) << "Qt: Using WGL and OpenGL from" << openglDll;
- m_lib = ::LoadLibraryA(openglDll.constData());
+ if (useSystemLib)
+ m_lib = QSystemLibrary::load((wchar_t*)(QString::fromLatin1(openglDll).utf16()));
+ else
+ m_lib = LoadLibraryA(openglDll.constData());
if (!m_lib) {
qErrnoWarning(::GetLastError(), "Failed to load %s", openglDll.constData());
return false;
@@ -184,7 +154,7 @@ bool QWindowsOpengl32DLL::init(bool softwareRendering)
// Load opengl32.dll always. GDI functions like ChoosePixelFormat do
// GetModuleHandle for opengl32.dll and behave differently (and call back into
// opengl32) when the module is present. This is fine for dummy contexts and windows.
- ::LoadLibraryA("opengl32.dll");
+ QSystemLibrary::load(L"opengl32");
}
wglCreateContext = reinterpret_cast<HGLRC (WINAPI *)(HDC)>(resolve("wglCreateContext"));
@@ -225,6 +195,11 @@ QWindowsOpenGLContext *QOpenGLStaticContext::createContext(QOpenGLContext *conte
return new QWindowsGLContext(this, context);
}
+QWindowsOpenGLContext *QOpenGLStaticContext::createContext(HGLRC context, HWND window)
+{
+ return new QWindowsGLContext(this, context, window);
+}
+
template <class MaskType, class FlagType> inline bool testFlag(MaskType mask, FlagType flag)
{
return (mask & MaskType(flag)) != 0;
@@ -569,11 +544,14 @@ static int choosePixelFormat(HDC hdc,
iAttributes[i++] = WGL_NUMBER_OVERLAYS_ARB;
iAttributes[i++] = 1;
}
+ // must be the one before the last one
const int samples = format.samples();
const bool sampleBuffersRequested = samples > 1
&& testFlag(staticContext.extensions, QOpenGLStaticContext::SampleBuffers);
+ int sampleBuffersKeyPosition = 0;
int samplesValuePosition = 0;
if (sampleBuffersRequested) {
+ sampleBuffersKeyPosition = i;
iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB;
iAttributes[i++] = TRUE;
iAttributes[i++] = WGL_SAMPLES_ARB;
@@ -584,10 +562,10 @@ static int choosePixelFormat(HDC hdc,
iAttributes[i++] = FALSE;
}
// must be the last
- bool srgbRequested = format.colorSpace() == QSurfaceFormat::sRGBColorSpace;
- int srgbValuePosition = 0;
+ bool srgbRequested = format.colorSpace() == QColorSpace::SRgb;
+ int srgbCapableKeyPosition = 0;
if (srgbRequested) {
- srgbValuePosition = i;
+ srgbCapableKeyPosition = i;
iAttributes[i++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT;
iAttributes[i++] = TRUE;
}
@@ -601,8 +579,9 @@ static int choosePixelFormat(HDC hdc,
&& numFormats >= 1;
if (valid || (!sampleBuffersRequested && !srgbRequested))
break;
+ // NB reductions must be done in reverse order (disable the last first, then move on to the one before that, etc.)
if (srgbRequested) {
- iAttributes[srgbValuePosition] = 0;
+ iAttributes[srgbCapableKeyPosition] = 0;
srgbRequested = false;
} else if (sampleBuffersRequested) {
if (iAttributes[samplesValuePosition] > 1) {
@@ -610,11 +589,8 @@ static int choosePixelFormat(HDC hdc,
} else if (iAttributes[samplesValuePosition] == 1) {
// Fallback in case it is unable to initialize with any
// samples to avoid falling back to the GDI path
- // NB: The sample attributes needs to be at the end for this
- // to work correctly
- iAttributes[samplesValuePosition - 1] = FALSE;
+ iAttributes[sampleBuffersKeyPosition] = 0;
iAttributes[samplesValuePosition] = 0;
- iAttributes[samplesValuePosition + 1] = 0;
} else {
break;
}
@@ -706,10 +682,10 @@ static QSurfaceFormat
if (hasSampleBuffers) {
result.setSamples(iValues[13]);
if (hasSrgbSupport && iValues[14])
- result.setColorSpace(QSurfaceFormat::sRGBColorSpace);
+ result.setColorSpace(QColorSpace::SRgb);
} else {
if (hasSrgbSupport && iValues[12])
- result.setColorSpace(QSurfaceFormat::sRGBColorSpace);
+ result.setColorSpace(QColorSpace::SRgb);
}
if (additionalIn) {
if (iValues[7])
@@ -802,7 +778,7 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext,
static inline HWND createDummyGLWindow()
{
return QWindowsContext::instance()->
- createDummyWindow(QStringLiteral("QtOpenGLDummyWindow"),
+ createDummyWindow(QStringLiteral("OpenGLDummyWindow"),
L"OpenGLDummyWindow", nullptr, WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
}
@@ -858,7 +834,6 @@ static inline QOpenGLContextData createDummyWindowOpenGLContextData()
context and to apply to a QSurfaceFormat.
\internal
- \ingroup qt-lighthouse-win
*/
QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current()
@@ -913,7 +888,6 @@ void QWindowsOpenGLContextFormat::apply(QSurfaceFormat *format) const
is a current GL context.
\internal
- \ingroup qt-lighthouse-win
*/
class QOpenGLTemporaryContext
@@ -946,7 +920,6 @@ QOpenGLTemporaryContext::~QOpenGLTemporaryContext()
/*!
\class QWindowsOpenGLAdditionalFormat
\brief Additional format information that is not in QSurfaceFormat
- \ingroup qt-lighthouse-win
*/
/*!
@@ -964,7 +937,6 @@ QOpenGLTemporaryContext::~QOpenGLTemporaryContext()
\sa QWindowsGLContext
\internal
- \ingroup qt-lighthouse-win
*/
#define SAMPLE_BUFFER_EXTENSION "GL_ARB_multisample"
@@ -1051,66 +1023,15 @@ QOpenGLStaticContext *QOpenGLStaticContext::create(bool softwareRendering)
QOpenGLContextData and are released in doneCurrent().
\internal
- \ingroup qt-lighthouse-win
*/
QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext,
QOpenGLContext *context) :
- m_staticContext(staticContext),
- m_context(context),
- m_renderingContext(nullptr),
- m_pixelFormat(0),
- m_extensionsUsed(false),
- m_swapInterval(-1),
- m_ownsContext(true),
- m_getGraphicsResetStatus(nullptr),
- m_lost(false)
+ m_staticContext(staticContext)
{
if (!m_staticContext) // Something went very wrong. Stop here, isValid() will return false.
return;
- QVariant nativeHandle = context->nativeHandle();
- if (!nativeHandle.isNull()) {
- // Adopt and existing context.
- if (!nativeHandle.canConvert<QWGLNativeContext>()) {
- qWarning("QWindowsGLContext: Requires a QWGLNativeContext");
- return;
- }
- auto handle = nativeHandle.value<QWGLNativeContext>();
- HGLRC wglcontext = handle.context();
- HWND wnd = handle.window();
- if (!wglcontext || !wnd) {
- qWarning("QWindowsGLContext: No context and window given");
- return;
- }
-
- HDC dc = GetDC(wnd);
- // A window with an associated pixel format is mandatory.
- // When no SetPixelFormat() call has been made, the following will fail.
- m_pixelFormat = GetPixelFormat(dc);
- bool ok = m_pixelFormat != 0;
- if (!ok)
- qWarning("QWindowsGLContext: Failed to get pixel format");
- ok = DescribePixelFormat(dc, m_pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &m_obtainedPixelFormatDescriptor);
- if (!ok) {
- qWarning("QWindowsGLContext: Failed to describe pixel format");
- } else {
- QWindowsOpenGLAdditionalFormat obtainedAdditional;
- m_obtainedFormat = GDI::qSurfaceFormatFromPixelFormat(m_obtainedPixelFormatDescriptor, &obtainedAdditional);
- m_renderingContext = wglcontext;
- ok = updateObtainedParams(dc);
- }
-
- ReleaseDC(wnd, dc);
-
- if (ok)
- m_ownsContext = false;
- else
- m_renderingContext = nullptr;
-
- return;
- }
-
QSurfaceFormat format = context->format();
if (format.renderableType() == QSurfaceFormat::DefaultRenderableType)
format.setRenderableType(QSurfaceFormat::OpenGL);
@@ -1212,11 +1133,6 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext,
} while (false);
- // Make the HGLRC retrievable via QOpenGLContext::nativeHandle().
- // Do not provide the window since it is the dummy one and it is about to disappear.
- if (m_renderingContext)
- context->setNativeHandle(QVariant::fromValue<QWGLNativeContext>(QWGLNativeContext(m_renderingContext, nullptr)));
-
if (hdc)
ReleaseDC(dummyWindow, hdc);
if (dummyWindow)
@@ -1230,6 +1146,37 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext,
<< "\n HGLRC=" << m_renderingContext;
}
+QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, HGLRC wglcontext, HWND wnd)
+ : m_staticContext(staticContext)
+{
+ if (!m_staticContext) // Something went very wrong. Stop here, isValid() will return false.
+ return;
+
+ HDC dc = GetDC(wnd);
+ // A window with an associated pixel format is mandatory.
+ // When no SetPixelFormat() call has been made, the following will fail.
+ m_pixelFormat = GetPixelFormat(dc);
+ bool ok = m_pixelFormat != 0;
+ if (!ok)
+ qWarning("QWindowsGLContext: Failed to get pixel format");
+ ok = DescribePixelFormat(dc, m_pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &m_obtainedPixelFormatDescriptor);
+ if (!ok) {
+ qWarning("QWindowsGLContext: Failed to describe pixel format");
+ } else {
+ QWindowsOpenGLAdditionalFormat obtainedAdditional;
+ m_obtainedFormat = GDI::qSurfaceFormatFromPixelFormat(m_obtainedPixelFormatDescriptor, &obtainedAdditional);
+ m_renderingContext = wglcontext;
+ ok = updateObtainedParams(dc);
+ }
+
+ ReleaseDC(wnd, dc);
+
+ if (ok)
+ m_ownsContext = false;
+ else
+ m_renderingContext = nullptr;
+}
+
QWindowsGLContext::~QWindowsGLContext()
{
if (m_renderingContext && m_ownsContext)
@@ -1315,17 +1262,19 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
// Do we already have a DC entry for that window?
auto *window = static_cast<QWindowsWindow *>(surface);
- window->aboutToMakeCurrent();
const HWND hwnd = window->handle();
if (const QOpenGLContextData *contextData = findByHWND(m_windowContexts, hwnd)) {
// Repeated calls to wglMakeCurrent when vsync is enabled in the driver will
// often result in 100% cpuload. This check is cheap and avoids the problem.
- // This is reproducable on NVidia cards and Intel onboard chips.
+ // This is reproducible on NVidia cards and Intel onboard chips.
if (QOpenGLStaticContext::opengl32.wglGetCurrentContext() == contextData->renderingContext
&& QOpenGLStaticContext::opengl32.wglGetCurrentDC() == contextData->hdc) {
return true;
}
- return QOpenGLStaticContext::opengl32.wglMakeCurrent(contextData->hdc, contextData->renderingContext);
+ const bool success = QOpenGLStaticContext::opengl32.wglMakeCurrent(contextData->hdc, contextData->renderingContext);
+ if (!success)
+ qErrnoWarning("%s: wglMakeCurrent() failed for existing context data", __FUNCTION__);
+ return success;
}
// Create a new entry.
const QOpenGLContextData newContext(m_renderingContext, hwnd, GetDC(hwnd));
@@ -1353,6 +1302,8 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
qCDebug(lcQpaGl) << "makeCurrent(): context loss detected" << this;
// Drop the surface. Will recreate on the next makeCurrent.
window->invalidateSurface();
+ } else {
+ qErrnoWarning("%s: wglMakeCurrent() failed", __FUNCTION__);
}
}
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h
index 8794368fe4..bf71959853 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsglcontext.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSGLCONTEXT_H
#define QWINDOWSGLCONTEXT_H
@@ -174,6 +138,7 @@ public:
static QByteArray getGlString(unsigned int which);
QWindowsOpenGLContext *createContext(QOpenGLContext *context) override;
+ QWindowsOpenGLContext *createContext(HGLRC context, HWND window) override;
void *moduleHandle() const override { return opengl32.moduleHandle(); }
QOpenGLContext::OpenGLModuleType moduleType() const override
{ return QOpenGLContext::LibGL; }
@@ -199,12 +164,14 @@ public:
static QWindowsOpengl32DLL opengl32;
};
-class QWindowsGLContext : public QWindowsOpenGLContext
+class QWindowsGLContext : public QWindowsOpenGLContext, public QNativeInterface::QWGLContext
{
public:
explicit QWindowsGLContext(QOpenGLStaticContext *staticContext, QOpenGLContext *context);
+ explicit QWindowsGLContext(QOpenGLStaticContext *staticContext, HGLRC context, HWND window);
+
~QWindowsGLContext() override;
- bool isSharing() const override { return m_context->shareHandle(); }
+ bool isSharing() const override { return context()->shareHandle(); }
bool isValid() const override { return m_renderingContext && !m_lost; }
QSurfaceFormat format() const override { return m_obtainedFormat; }
@@ -219,7 +186,7 @@ public:
HGLRC renderingContext() const { return m_renderingContext; }
- void *nativeContext() const override { return m_renderingContext; }
+ HGLRC nativeContext() const override { return m_renderingContext; }
private:
typedef GLenum (APIENTRY *GlGetGraphicsResetStatusArbType)();
@@ -227,18 +194,17 @@ private:
inline void releaseDCs();
bool updateObtainedParams(HDC hdc, int *obtainedSwapInterval = nullptr);
- QOpenGLStaticContext *m_staticContext;
- QOpenGLContext *m_context;
+ QOpenGLStaticContext *m_staticContext = nullptr;
QSurfaceFormat m_obtainedFormat;
- HGLRC m_renderingContext;
+ HGLRC m_renderingContext = nullptr;
std::vector<QOpenGLContextData> m_windowContexts;
PIXELFORMATDESCRIPTOR m_obtainedPixelFormatDescriptor;
- int m_pixelFormat;
- bool m_extensionsUsed;
- int m_swapInterval;
- bool m_ownsContext;
- GlGetGraphicsResetStatusArbType m_getGraphicsResetStatus;
- bool m_lost;
+ int m_pixelFormat = 0;
+ bool m_extensionsUsed = false;
+ int m_swapInterval = -1;
+ bool m_ownsContext = true;
+ GlGetGraphicsResetStatusArbType m_getGraphicsResetStatus = nullptr;
+ bool m_lost = false;
};
#endif
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsiconengine.cpp b/src/plugins/platforms/windows/qwindowsiconengine.cpp
new file mode 100644
index 0000000000..5e5ca22ec1
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsiconengine.cpp
@@ -0,0 +1,394 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwindowsiconengine.h"
+
+#include <QtCore/qoperatingsystemversion.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qpalette.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+QString QWindowsIconEngine::glyphs() const
+{
+ if (!QFontInfo(m_iconFont).exactMatch())
+ return {};
+
+ static constexpr std::pair<QLatin1StringView, QStringView> glyphMap[] = {
+ {"address-book-new"_L1, u"\ue780"},
+ {"application-exit"_L1, u"\ue8bb"},
+ {"appointment-new"_L1, u"\ue878"},
+ {"call-start"_L1, u"\uf715"},
+ {"call-stop"_L1, u"\uf405"},
+ {"contact-new"_L1, u"\ue8fa"},
+ {"document-new"_L1, u"\ue8a5"},
+ {"document-open"_L1, u"\ue8e5"},
+ {"document-open-recent"_L1, u"\ue823"},
+ {"document-page-setup"_L1, u"\ue7c3"},
+ {"document-print"_L1, u"\ue749"},
+ {"document-print-preview"_L1, u"\ue956"},
+ {"document-properties"_L1, u"\ue90f"},
+ {"document-revert"_L1, u"\ue7a7"}, // ?
+ {"document-save"_L1, u"\ue74e"}, // or e78c?
+ {"document-save-as"_L1, u"\ue792"},
+ {"document-send"_L1, u"\ue724"},
+ {"edit-clear"_L1, u"\ue894"},
+ {"edit-copy"_L1, u"\ue8c8"},
+ {"edit-cut"_L1, u"\ue8c6"},
+ {"edit-delete"_L1, u"\ue74d"},
+ {"edit-find"_L1, u"\ue721"},
+ //{"edit-find-replace"_L1, u"\u"},
+ {"edit-paste"_L1, u"\ue77f"},
+ {"edit-redo"_L1, u"\ue7a6"},
+ {"edit-select-all"_L1, u"\ue8b3"},
+ {"edit-undo"_L1, u"\ue7a7"},
+ {"folder-new"_L1, u"\ue8f4"},
+ //{"format-indent-less"_L1, u"\u"},
+ //{"format-indent-more"_L1, u"\u"},
+ {"format-justify-center"_L1, u"\ue8e3"},
+ //{"format-justify-fill"_L1, u"\ue235"},
+ {"format-justify-left"_L1, u"\ue8e4"},
+ {"format-justify-right"_L1, u"\ue8e2"},
+ //{"format-text-direction-ltr"_L1, u"\ue247"},
+ //{"format-text-direction-rtl"_L1, u"\ue248"},
+ {"format-text-bold"_L1, u"\ue8dd"},
+ {"format-text-italic"_L1, u"\ue8db"},
+ {"format-text-underline"_L1, u"\ue8dc"},
+ {"format-text-strikethrough"_L1, u"\uede0"},
+ //{"go-bottom"_L1,u"\ue258"},
+ {"go-down"_L1,u"\ue74b"},
+ //{"go-first"_L1, u"\ue5dc"},
+ {"go-home"_L1, u"\ue80f"},
+ // {"go-jump"_L1, u"\uf719"},
+ //{"go-last"_L1, u"\ue5dd"},
+ {"go-next"_L1, u"\ue893"},
+ {"go-previous"_L1, u"\ue892"},
+ //{"go-top"_L1, u"\ue25a"},
+ {"go-up"_L1, u"\ue74a"},
+ {"help-about"_L1, u"\ue946"},
+ //{"help-contents"_L1, u"\ue8de"},
+ {"help-faq"_L1, u"\ue897"},
+ {"insert-image"_L1, u"\ue946"},
+ {"insert-link"_L1, u"\ue71b"},
+ //{"insert-object"_L1, u"\u"},
+ //{"insert-text"_L1, u"\uf827"},
+ {"list-add"_L1, u"\ue710"},
+ {"list-remove"_L1, u"\ue738"},
+ {"mail-forward"_L1, u"\ue89c"},
+ //{"mail-mark-important"_L1, u"\ue937"},
+ //{"mail-mark-junk"_L1, u"\u"},
+ //{"mail-mark-notjunk"_L1, u"\u"},
+ {"mail-mark-read"_L1, u"\ue8c3"},
+ //{"mail-mark-unread"_L1, u"\ue9bc"},
+ {"mail-message-new"_L1, u"\ue70f"},
+ {"mail-reply-all"_L1, u"\ue8c2"},
+ {"mail-reply-sender"_L1, u"\ue8ca"},
+ {"mail-send"_L1, u"\ue724"},
+ //{"mail-send-receive"_L1, u"\u"},
+ {"media-eject"_L1, u"\uf847"},
+ {"media-playback-pause"_L1, u"\ue769"},
+ {"media-playback-start"_L1, u"\ue768"},
+ {"media-playback-stop"_L1, u"\ue71a"},
+ {"media-record"_L1, u"\ue7c8"},
+ {"media-seek-backward"_L1, u"\ueb9e"},
+ {"media-seek-forward"_L1, u"\ueb9d"},
+ {"media-skip-backward"_L1, u"\ue892"},
+ {"media-skip-forward"_L1, u"\ue893"},
+ //{"object-flip-horizontal"_L1, u"\u"},
+ //{"object-flip-vertical"_L1, u"\u"},
+ {"object-rotate-left"_L1, u"\ue80c"},
+ {"object-rotate-right"_L1, u"\ue80d"},
+ //{"process-stop"_L1, u"\ue5c9"},
+ {"system-lock-screen"_L1, u"\uee3f"},
+ {"system-log-out"_L1, u"\uf3b1"},
+ //{"system-run"_L1, u"\u"},
+ {"system-search"_L1, u"\ue721"},
+ {"system-reboot"_L1, u"\ue777"}, // unsure?
+ {"system-shutdown"_L1, u"\ue7e8"},
+ {"tools-check-spelling"_L1, u"\uf87b"},
+ {"view-fullscreen"_L1, u"\ue740"},
+ {"view-refresh"_L1, u"\ue72c"},
+ {"view-restore"_L1, u"\ue777"},
+ //{"view-sort-ascending"_L1, u"\ue25a"},
+ //{"view-sort-descending"_L1, u"\ue258"},
+ {"window-close"_L1, u"\ue8bb"},
+ {"window-new"_L1, u"\ue78b"},
+ {"zoom-fit-best"_L1, u"\ue9a6"},
+ {"zoom-in"_L1, u"\ue8a3"},
+ //{"zoom-original"_L1, u"\u"},
+ {"zoom-out"_L1, u"\ue71f"},
+
+ {"process-working"_L1, u"\ue9f3"},
+
+ {"accessories-calculator"_L1, u"\ue8ef"},
+ {"accessories-character-map"_L1, u"\uf2b7"},
+ {"accessories-dictionary"_L1, u"\ue82d"},
+ //{"accessories-text-editor"_L1, u"\ue262"},
+ {"help-browser"_L1, u"\ue897"},
+ {"multimedia-volume-control"_L1, u"\ue767"},
+ {"preferences-desktop-accessibility"_L1, u"\ue776"},
+ {"preferences-desktop-font"_L1, u"\ue8d2"},
+ {"preferences-desktop-keyboard"_L1, u"\ue765"},
+ {"preferences-desktop-locale"_L1, u"\uf2b7"},
+ //{"preferences-desktop-multimedia"_L1, u"\uea75"},
+ {"preferences-desktop-screensaver"_L1, u"\uf182"},
+ //{"preferences-desktop-theme"_L1, u"\uf560"},
+ //{"preferences-desktop-wallpaper"_L1, u"\ue1bc"},
+ {"system-file-manager"_L1, u"\uec50"},
+ //{"system-software-install"_L1, u"\ueb71"},
+ {"system-software-update"_L1, u"\uecc5"},
+ {"utilities-system-monitor"_L1, u"\ue7f4"},
+ //{"utilities-terminal"_L1, u"\ueb8e"},
+
+ //{"applications-accessories"_L1, u"\u"},
+ {"applications-development"_L1, u"\uec7a"},
+ //{"applications-engineering"_L1, u"\uea3d"},
+ {"applications-games"_L1, u"\ue7fc"},
+ //{"applications-graphics"_L1, u"\u"},
+ {"applications-internet"_L1, u"\ue774"},
+ {"applications-multimedia"_L1, u"\uea69"},
+ //{"applications-office"_L1, u"\u"},
+ //{"applications-other"_L1, u"\u"},
+ //{"applications-science"_L1, u"\uea4b"},
+ {"applications-system"_L1, u"\ue770"},
+ //{"applications-utilities"_L1, u"\u"},
+ //{"preferences-desktop"_L1, u"\ueb97"},
+ //{"preferences-desktop-peripherals"_L1, u"\u"},
+ //{"preferences-desktop-personal"_L1, u"\uf835"},
+ //{"preferences-other"_L1, u"\u"},
+ //{"preferences-system"_L1, u"\ue8b8"},
+ //{"preferences-system-network"_L1, u"\ue894"},
+ {"system-help"_L1, u"\ue946"},
+
+ {"audio-card"_L1, u"\ue8d6"},
+ {"audio-input-microphone"_L1, u"\ue720"},
+ {"battery"_L1, u"\ue83f"},
+ {"camera-photo"_L1, u"\ue722"},
+ {"camera-video"_L1, u"\ue714"},
+ {"camera-web"_L1, u"\ue8b8"},
+ {"computer"_L1, u"\ue7f8"}, // or e7fb?
+ {"drive-harddisk"_L1, u"\ueda2"},
+ {"drive-optical"_L1, u"\ue958"},
+ //{"drive-removable-media"_L1, u"\u"},
+ //{"input-gaming"_L1, u"\u"},
+ {"input-keyboard"_L1, u"\ue92e"},
+ {"input-mouse"_L1, u"\ue962"},
+ {"input-tablet"_L1, u"\ue70a"},
+ {"media-flash"_L1, u"\ue88e"},
+ //{"media-floppy"_L1, u"\u"},
+ {"media-optical"_L1, u"\ue958"},
+ {"media-tape"_L1, u"\ue96a"},
+ //{"modem"_L1, u"\u"},
+ //{"multimedia-player"_L1, u"\u"},
+ {"network-wired"_L1, u"\ue968"},
+ {"network-wireless"_L1, u"\ue701"},
+ //{"pda"_L1, u"\u"},
+ {"phone"_L1, u"\ue717"},
+ {"printer"_L1, u"\ue749"},
+ {"scanner"_L1, u"\ue8fe"},
+ //{"video-display"_L1, u"\uf06a"},
+
+ {"emblem-default"_L1, u"\uf56d"},
+ {"emblem-documents"_L1, u"\ue8a5"},
+ {"emblem-downloads"_L1, u"\ue896"},
+ {"emblem-favorite"_L1, u"\ue734"},
+ {"emblem-important"_L1, u"\ue8c9"},
+ {"emblem-mail"_L1, u"\ue715"},
+ {"emblem-photos"_L1, u"\ue91b"},
+ //{"emblem-readonly"_L1, u"\u"},
+ {"emblem-shared"_L1, u"\ue902"},
+ {"emblem-symbolic-link"_L1, u"\ue71b"},
+ {"emblem-synchronized"_L1, u"\uedab"},
+ {"emblem-system"_L1, u"\ue770"},
+ //{"emblem-unreadable"_L1, u"\u"},
+
+ {"folder"_L1, u"\ue8b7"},
+ //{"folder-remote"_L1, u"\u"},
+ //{"network-server"_L1, u"\ue875"},
+ //{"network-workgroup"_L1, u"\ue1a0"},
+ {"start-here"_L1, u"\ue8fc"}, // unsure
+ {"user-bookmarks"_L1, u"\ue8a4"},
+ //{"user-desktop"_L1, u"\ue30a"},
+ {"user-home"_L1, u"\ue80f"},
+ {"user-trash"_L1, u"\ue74d"},
+
+ //{"appointment-missed"_L1, u"\ue615"},
+ //{"appointment-soon"_L1, u"\uf540"},
+ {"audio-volume-high"_L1, u"\ue995"},
+ {"audio-volume-low"_L1, u"\ue993"},
+ {"audio-volume-medium"_L1, u"\ue994"},
+ {"audio-volume-muted"_L1, u"\ue992"},
+ //{"battery-caution"_L1, u"\ue19c"},
+ {"battery-low"_L1, u"\ue851"}, // ?
+ {"dialog-error"_L1, u"\ue783"},
+ {"dialog-information"_L1, u"\ue946"},
+ //{"dialog-password"_L1, u"\uf042"},
+ {"dialog-question"_L1, u"\uf142"}, // unsure
+ {"dialog-warning"_L1, u"\ue7ba"},
+ //{"folder-drag-accept"_L1, @u"\ue9a3"},
+ {"folder-open"_L1, u"\ue838"},
+ //{"folder-visiting"_L1, u"\ue8a7"},
+ //{"image-loading"_L1, u"\ue41a"},
+ //{"image-missing"_L1, u"\ue3ad"},
+ {"mail-attachment"_L1, u"\ue723"},
+ //{"mail-unread"_L1, u"\uf18a"},
+ //{"mail-read"_L1, u"\uf18c"},
+ {"mail-replied"_L1, u"\ue8ca"},
+ //{"mail-signed"_L1, u"\u"},
+ //{"mail-signed-verified"_L1, u"\u"},
+ {"media-playlist-repeat"_L1, u"\ue8ee"},
+ {"media-playlist-shuffle"_L1, u"\ue8b1"},
+ //{"network-error"_L1, u"\uead9"},
+ //{"network-idle"_L1, u"\ue51f"},
+ {"network-offline"_L1, u"\uf384"},
+ //{"network-receive"_L1, u"\ue2c0"},
+ //{"network-transmit"_L1, u"\ue2c3"},
+ //{"network-transmit-receive"_L1, u"\uca18"},
+ //{"printer-error"_L1, u"\uf7a0"},
+ //{"printer-printing"_L1, u"\uf7a1"},
+ //{"security-high"_L1, u"\ue32a"},
+ //{"security-medium"_L1, u"\ue9e0"},
+ //{"security-low"_L1, u"\uf012"},
+ //{"software-update-available"_L1, u"\ue923"},
+ //{"software-update-urgent"_L1, u"\uf05a"},
+ {"sync-error"_L1, u"\uea6a"},
+ {"sync-synchronizing"_L1, u"\ue895"},
+ //{"task-due"_L1, u"\u"},
+ //{"task-past-due"_L1, u"\u"},
+ {"user-available"_L1, u"\ue8cf"},
+ //{"user-away"_L1, u"\ue510"},
+ //{"user-idle"_L1, u"\u"},
+ //{"user-offline"_L1, u"\uf7b3"},
+ //{"user-trash-full"_L1, u"\ue872"}, //delete
+ //{"user-trash-full"_L1, u"\ue92b"}, //delete_forever
+ {"weather-clear"_L1, u"\ue706"},
+ //{"weather-clear-night"_L1, u"\uf159"},
+ //{"weather-few-clouds"_L1, u"\uf172"},
+ //{"weather-few-clouds-night"_L1, u"\uf174"},
+ //{"weather-fog"_L1, u"\ue818"},
+ {"weather-overcast"_L1, u"\ue753"},
+ //{"weather-severe-alert"_L1, u"\ue002"}, //warning
+ //{"weather-showers"_L1, u"\uf176"},
+ //{"weather-showers-scattered"_L1, u"\u"},
+ //{"weather-snow"_L1, u"\ue80f"}, //snowing
+ //{"weather-storm"_L1, u"\uf070"},
+ };
+
+ const auto it = std::find_if(std::begin(glyphMap), std::end(glyphMap), [this](const auto &c){
+ return c.first == m_iconName;
+ });
+
+ return it != std::end(glyphMap) ? it->second.toString()
+ : (m_iconName.length() == 1 ? m_iconName : QString());
+}
+
+namespace {
+auto iconFontFamily()
+{
+ static const bool isWindows11 = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11;
+ return isWindows11 ? u"Segoe Fluent Icons"_s
+ : u"Segoe MDL2 Assets"_s;
+}
+}
+
+QWindowsIconEngine::QWindowsIconEngine(const QString &iconName)
+ : m_iconName(iconName), m_iconFont(iconFontFamily())
+ , m_glyphs(glyphs())
+{
+}
+
+QWindowsIconEngine::~QWindowsIconEngine()
+{}
+
+QIconEngine *QWindowsIconEngine::clone() const
+{
+ return new QWindowsIconEngine(m_iconName);
+}
+
+QString QWindowsIconEngine::key() const
+{
+ return u"QWindowsIconEngine"_s;
+}
+
+QString QWindowsIconEngine::iconName()
+{
+ return m_iconName;
+}
+
+bool QWindowsIconEngine::isNull()
+{
+ if (m_glyphs.isEmpty())
+ return true;
+
+ const QChar c0 = m_glyphs.at(0);
+ const QFontMetrics fontMetrics(m_iconFont);
+ if (c0.category() == QChar::Other_Surrogate && m_glyphs.size() > 1)
+ return !fontMetrics.inFontUcs4(QChar::surrogateToUcs4(c0, m_glyphs.at(1)));
+ return !fontMetrics.inFont(c0);
+}
+
+QList<QSize> QWindowsIconEngine::availableSizes(QIcon::Mode, QIcon::State)
+{
+ return {{16, 16}, {24, 24}, {48, 48}, {128, 128}};
+}
+
+QSize QWindowsIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ return QIconEngine::actualSize(size, mode, state);
+}
+
+QPixmap QWindowsIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ return scaledPixmap(size, mode, state, 1.0);
+}
+
+QPixmap QWindowsIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
+{
+ const quint64 cacheKey = calculateCacheKey(mode, state);
+ if (cacheKey != m_cacheKey || m_pixmap.size() != size || m_pixmap.devicePixelRatio() != scale) {
+ m_pixmap = QPixmap(size * scale);
+ m_pixmap.fill(Qt::transparent);
+ m_pixmap.setDevicePixelRatio(scale);
+
+ QPainter painter(&m_pixmap);
+ paint(&painter, QRect(QPoint(), size), mode, state);
+
+ m_cacheKey = cacheKey;
+ }
+
+ return m_pixmap;
+}
+
+void QWindowsIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
+{
+ Q_UNUSED(state);
+
+ painter->save();
+ QFont renderFont(m_iconFont);
+ renderFont.setPixelSize(rect.height());
+ painter->setFont(renderFont);
+
+ QPalette palette;
+ switch (mode) {
+ case QIcon::Active:
+ painter->setPen(palette.color(QPalette::Active, QPalette::Text));
+ break;
+ case QIcon::Normal:
+ painter->setPen(palette.color(QPalette::Active, QPalette::Text));
+ break;
+ case QIcon::Disabled:
+ painter->setPen(palette.color(QPalette::Disabled, QPalette::Text));
+ break;
+ case QIcon::Selected:
+ painter->setPen(palette.color(QPalette::Active, QPalette::HighlightedText));
+ break;
+ }
+
+ painter->drawText(rect, Qt::AlignCenter, m_glyphs);
+ painter->restore();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsiconengine.h b/src/plugins/platforms/windows/qwindowsiconengine.h
new file mode 100644
index 0000000000..3c6cbddb8b
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsiconengine.h
@@ -0,0 +1,47 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWINDOWSICONENGINE_H
+#define QWINDOWSICONENGINE_H
+
+#include <QtCore/qt_windows.h>
+
+#include <QtGui/qfont.h>
+#include <QtGui/qiconengine.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsIconEngine : public QIconEngine
+{
+public:
+ QWindowsIconEngine(const QString &iconName);
+ ~QWindowsIconEngine();
+ QIconEngine *clone() const override;
+ QString key() const override;
+ QString iconName() override;
+ bool isNull() override;
+
+ QList<QSize> availableSizes(QIcon::Mode, QIcon::State) override;
+ QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+ QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override;
+ void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
+
+private:
+ static constexpr quint64 calculateCacheKey(QIcon::Mode mode, QIcon::State state)
+ {
+ return (quint64(mode) << 32) | state;
+ }
+
+ QString glyphs() const;
+
+ const QString m_iconName;
+ const QFont m_iconFont;
+ const QString m_glyphs;
+ mutable QPixmap m_pixmap;
+ mutable quint64 m_cacheKey = {};
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSICONENGINE_H
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 19d632dc10..0281025b5b 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsinputcontext.h"
#include "qwindowscontext.h"
@@ -47,7 +11,6 @@
#include <QtCore/qobject.h>
#include <QtCore/qrect.h>
#include <QtCore/qtextboundaryfinder.h>
-#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/qevent.h>
#include <QtGui/qtextformat.h>
@@ -160,7 +123,6 @@ Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id); // from qlocale_win.cpp
needs to be checked (mouse grab might interfere with candidate window).
\internal
- \ingroup qt-lighthouse-win
*/
@@ -199,7 +161,6 @@ bool QWindowsInputContext::hasCapability(Capability capability) const
void QWindowsInputContext::reset()
{
- QPlatformInputContext::reset();
if (!m_compositionContext.hwnd)
return;
qCDebug(lcQpaInputMethods) << __FUNCTION__;
@@ -276,24 +237,9 @@ void QWindowsInputContext::showInputPanel()
if (!m_caretCreated && m_transparentBitmap)
m_caretCreated = CreateCaret(platformWindow->handle(), m_transparentBitmap, 0, 0);
- // For some reason, the on-screen keyboard is only triggered on the Surface
- // with Windows 10 if the Windows IME is (re)enabled _after_ the caret is shown.
if (m_caretCreated) {
cursorRectChanged();
- // We only call ShowCaret() on Windows 10 after 1703 as in earlier versions
- // the caret would actually be visible (QTBUG-74492) and the workaround for
- // the Surface seems unnecessary there anyway. But leave it hidden for IME.
- // Only trigger the native OSK if the Qt OSK is not in use.
- static bool imModuleEmpty = qEnvironmentVariableIsEmpty("QT_IM_MODULE");
- if (imModuleEmpty
- && QOperatingSystemVersion::current()
- >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 16299)) {
- ShowCaret(platformWindow->handle());
- } else {
- HideCaret(platformWindow->handle());
- }
- setWindowsImeEnabled(platformWindow, false);
- setWindowsImeEnabled(platformWindow, true);
+ ShowCaret(platformWindow->handle());
}
}
@@ -338,7 +284,6 @@ void QWindowsInputContext::update(Qt::InputMethodQueries queries)
{
if (queries & Qt::ImEnabled)
updateEnabled();
- QPlatformInputContext::update(queries);
}
void QWindowsInputContext::cursorRectChanged()
@@ -731,7 +676,7 @@ int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv)
reconv->dwTargetStrOffset = reconv->dwCompStrOffset;
auto *pastReconv = reinterpret_cast<ushort *>(reconv + 1);
std::copy(surroundingText.utf16(), surroundingText.utf16() + surroundingText.size(),
- QT_MAKE_UNCHECKED_ARRAY_ITERATOR(pastReconv));
+ pastReconv);
return memSize;
}
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h
index 857706bcb9..e7eafb9ea5 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.h
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSINPUTCONTEXT_H
#define QWINDOWSINPUTCONTEXT_H
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 09117f663d..aa6be266da 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsintegration.h"
#include "qwindowswindow.h"
@@ -48,9 +12,14 @@
#include "qwindowsscreen.h"
#include "qwindowstheme.h"
#include "qwindowsservices.h"
+#include <QtGui/private/qtgui-config_p.h>
+#if QT_CONFIG(directwrite3)
+#include <QtGui/private/qwindowsdirectwritefontdatabase_p.h>
+#endif
#ifndef QT_NO_FREETYPE
-# include <QtFontDatabaseSupport/private/qwindowsfontdatabase_ft_p.h>
+# include <QtGui/private/qwindowsfontdatabase_ft_p.h>
#endif
+#include <QtGui/private/qwindowsfontdatabase_p.h>
#if QT_CONFIG(clipboard)
# include "qwindowsclipboard.h"
# if QT_CONFIG(draganddrop)
@@ -68,28 +37,40 @@
#if QT_CONFIG(sessionmanager)
# include "qwindowssessionmanager.h"
#endif
-#include <QtGui/qtouchdevice.h>
+#include <QtGui/qpointingdevice.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/qpa/qplatforminputcontextfactory_p.h>
#include <QtGui/qpa/qplatformcursor.h>
-#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
+#include <QtGui/private/qwindowsguieventdispatcher_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qvariant.h>
+#include <QtCore/qoperatingsystemversion.h>
+#include <QtCore/private/qfunctions_win_p.h>
+
+#include <wrl.h>
+
#include <limits.h>
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-# include "qwindowseglcontext.h"
-#endif
-#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
+#if !defined(QT_NO_OPENGL)
# include "qwindowsglcontext.h"
#endif
#include "qwindowsopengltester.h"
+#if QT_CONFIG(cpp_winrt)
+# include <QtCore/private/qt_winrtbase_p.h>
+# include <winrt/Windows.UI.Notifications.h>
+# include <winrt/Windows.Data.Xml.Dom.h>
+# include <winrt/Windows.Foundation.h>
+# include <winrt/Windows.UI.ViewManagement.h>
+#endif
+
+#include <memory>
+
static inline void initOpenGlBlacklistResources()
{
Q_INIT_RESOURCE(openglblacklists);
@@ -97,46 +78,16 @@ static inline void initOpenGlBlacklistResources()
QT_BEGIN_NAMESPACE
-/*!
- \class QWindowsIntegration
- \brief QPlatformIntegration implementation for Windows.
- \internal
-
- \section1 Programming Considerations
-
- The platform plugin should run on Desktop Windows from Windows XP onwards
- and Windows Embedded.
-
- It should compile with:
- \list
- \li Microsoft Visual Studio 2013 or later (using the Microsoft Windows SDK,
- (\c Q_CC_MSVC).
- \li Stock \l{http://mingw.org/}{MinGW} (\c Q_CC_MINGW).
- This version ships with headers that are missing a lot of WinAPI.
- \li MinGW distributions using GCC 4.7 or higher and a recent MinGW-w64 runtime API,
- such as \l{http://tdm-gcc.tdragon.net/}{TDM-GCC}, or
- \l{http://mingwbuilds.sourceforge.net/}{MinGW-builds}
- (\c Q_CC_MINGW and \c __MINGW64_VERSION_MAJOR indicating the version).
- MinGW-w64 provides more complete headers (compared to stock MinGW from mingw.org),
- including a considerable part of the Windows SDK.
- \endlist
-
- When using a function from the WinAPI, the minimum supported Windows version
- and Windows Embedded support should be checked. If the function is not supported
- on Windows XP or is not present in the MinGW-headers, it should be dynamically
- resolved. For this purpose, QWindowsContext has static structs like
- QWindowsUser32DLL and QWindowsShell32DLL. All function pointers should go to
- these structs to avoid lookups in several places.
-
- \ingroup qt-lighthouse-win
-*/
+using namespace Qt::StringLiterals;
struct QWindowsIntegrationPrivate
{
Q_DISABLE_COPY_MOVE(QWindowsIntegrationPrivate)
- explicit QWindowsIntegrationPrivate(const QStringList &paramList);
+ explicit QWindowsIntegrationPrivate() = default;
~QWindowsIntegrationPrivate();
+ void parseOptions(QWindowsIntegration *q, const QStringList &paramList);
+
unsigned m_options = 0;
QWindowsContext m_context;
QPlatformFontDatabase *m_fontDatabase = nullptr;
@@ -158,17 +109,17 @@ struct QWindowsIntegrationPrivate
};
template <typename IntType>
-bool parseIntOption(const QString &parameter,const QLatin1String &option,
+bool parseIntOption(const QString &parameter,const QLatin1StringView &option,
IntType minimumValue, IntType maximumValue, IntType *target)
{
const int valueLength = parameter.size() - option.size() - 1;
- if (valueLength < 1 || !parameter.startsWith(option) || parameter.at(option.size()) != QLatin1Char('='))
+ if (valueLength < 1 || !parameter.startsWith(option) || parameter.at(option.size()) != u'=')
return false;
bool ok;
- const QStringRef valueRef = parameter.rightRef(valueLength);
+ const auto valueRef = QStringView{parameter}.right(valueLength);
const int value = valueRef.toInt(&ok);
if (ok) {
- if (value >= minimumValue && value <= maximumValue)
+ if (value >= int(minimumValue) && value <= int(maximumValue))
*target = static_cast<IntType>(value);
else {
qWarning() << "Value" << value << "for option" << option << "out of range"
@@ -180,45 +131,60 @@ bool parseIntOption(const QString &parameter,const QLatin1String &option,
return true;
}
+using DarkModeHandlingFlag = QNativeInterface::Private::QWindowsApplication::DarkModeHandlingFlag;
+using DarkModeHandling = QNativeInterface::Private::QWindowsApplication::DarkModeHandling;
+
static inline unsigned parseOptions(const QStringList &paramList,
int *tabletAbsoluteRange,
- QtWindows::ProcessDpiAwareness *dpiAwareness)
+ QtWindows::DpiAwareness *dpiAwareness,
+ DarkModeHandling *darkModeHandling)
{
unsigned options = 0;
for (const QString &param : paramList) {
- if (param.startsWith(QLatin1String("fontengine="))) {
- if (param.endsWith(QLatin1String("freetype"))) {
+ if (param.startsWith(u"fontengine=")) {
+ if (param.endsWith(u"gdi")) {
+ options |= QWindowsIntegration::FontDatabaseGDI;
+ } else if (param.endsWith(u"freetype")) {
options |= QWindowsIntegration::FontDatabaseFreeType;
- } else if (param.endsWith(QLatin1String("native"))) {
+ } else if (param.endsWith(u"native")) {
options |= QWindowsIntegration::FontDatabaseNative;
}
- } else if (param.startsWith(QLatin1String("dialogs="))) {
- if (param.endsWith(QLatin1String("xp"))) {
+ } else if (param.startsWith(u"dialogs=")) {
+ if (param.endsWith(u"xp")) {
options |= QWindowsIntegration::XpNativeDialogs;
- } else if (param.endsWith(QLatin1String("none"))) {
+ } else if (param.endsWith(u"none")) {
options |= QWindowsIntegration::NoNativeDialogs;
}
- } else if (param == QLatin1String("altgr")) {
+ } else if (param == u"altgr") {
options |= QWindowsIntegration::DetectAltGrModifier;
- } else if (param == QLatin1String("gl=gdi")) {
+ } else if (param == u"gl=gdi") {
options |= QWindowsIntegration::DisableArb;
- } else if (param == QLatin1String("nodirectwrite")) {
+ } else if (param == u"nodirectwrite") {
options |= QWindowsIntegration::DontUseDirectWriteFonts;
- } else if (param == QLatin1String("nocolorfonts")) {
+ } else if (param == u"nocolorfonts") {
options |= QWindowsIntegration::DontUseColorFonts;
- } else if (param == QLatin1String("nomousefromtouch")) {
+ } else if (param == u"nomousefromtouch") {
options |= QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch;
- } else if (parseIntOption(param, QLatin1String("verbose"), 0, INT_MAX, &QWindowsContext::verbose)
- || parseIntOption(param, QLatin1String("tabletabsoluterange"), 0, INT_MAX, tabletAbsoluteRange)
- || parseIntOption(param, QLatin1String("dpiawareness"), QtWindows::ProcessDpiUnaware, QtWindows::ProcessPerMonitorDpiAware, dpiAwareness)) {
- } else if (param == QLatin1String("menus=native")) {
+ } else if (parseIntOption(param, "verbose"_L1, 0, INT_MAX, &QWindowsContext::verbose)
+ || parseIntOption(param, "tabletabsoluterange"_L1, 0, INT_MAX, tabletAbsoluteRange)
+ || parseIntOption(param, "dpiawareness"_L1, QtWindows::DpiAwareness::Invalid,
+ QtWindows::DpiAwareness::PerMonitorVersion2, dpiAwareness)) {
+ } else if (param == u"menus=native") {
options |= QWindowsIntegration::AlwaysUseNativeMenus;
- } else if (param == QLatin1String("menus=none")) {
+ } else if (param == u"menus=none") {
options |= QWindowsIntegration::NoNativeMenus;
- } else if (param == QLatin1String("nowmpointer")) {
+ } else if (param == u"nowmpointer") {
options |= QWindowsIntegration::DontUseWMPointer;
- } else if (param == QLatin1String("reverse")) {
+ } else if (param == u"reverse") {
options |= QWindowsIntegration::RtlEnabled;
+ } else if (param == u"darkmode=0") {
+ *darkModeHandling = {};
+ } else if (param == u"darkmode=1") {
+ darkModeHandling->setFlag(DarkModeHandlingFlag::DarkModeWindowFrames);
+ darkModeHandling->setFlag(DarkModeHandlingFlag::DarkModeStyle, false);
+ } else if (param == u"darkmode=2") {
+ darkModeHandling->setFlag(DarkModeHandlingFlag::DarkModeWindowFrames);
+ darkModeHandling->setFlag(DarkModeHandlingFlag::DarkModeStyle);
} else {
qWarning() << "Unknown option" << param;
}
@@ -226,31 +192,33 @@ static inline unsigned parseOptions(const QStringList &paramList,
return options;
}
-QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramList)
+void QWindowsIntegrationPrivate::parseOptions(QWindowsIntegration *q, const QStringList &paramList)
{
initOpenGlBlacklistResources();
static bool dpiAwarenessSet = false;
+ // Default to per-monitor-v2 awareness (if available)
+ QtWindows::DpiAwareness dpiAwareness = QtWindows::DpiAwareness::PerMonitorVersion2;
+
int tabletAbsoluteRange = -1;
- // Default to per-monitor awareness to avoid being scaled when monitors with different DPI
- // are connected to Windows 8.1
- QtWindows::ProcessDpiAwareness dpiAwareness = QtWindows::ProcessPerMonitorDpiAware;
- m_options = parseOptions(paramList, &tabletAbsoluteRange, &dpiAwareness);
+ DarkModeHandling darkModeHandling = DarkModeHandlingFlag::DarkModeWindowFrames
+ | DarkModeHandlingFlag::DarkModeStyle;
+ m_options = ::parseOptions(paramList, &tabletAbsoluteRange, &dpiAwareness, &darkModeHandling);
+ q->setDarkModeHandling(darkModeHandling);
QWindowsFontDatabase::setFontOptions(m_options);
+ if (tabletAbsoluteRange >= 0)
+ QWindowsContext::setTabletAbsoluteRange(tabletAbsoluteRange);
- if (m_context.initPointer(m_options)) {
+ if (m_context.initPointer(m_options))
QCoreApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents);
- } else {
- m_context.initTablet(m_options);
- if (tabletAbsoluteRange >= 0)
- m_context.setTabletAbsoluteRange(tabletAbsoluteRange);
- }
+ else
+ m_context.initTablet();
+ QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
if (!dpiAwarenessSet) { // Set only once in case of repeated instantiations of QGuiApplication.
if (!QCoreApplication::testAttribute(Qt::AA_PluginApplication)) {
m_context.setProcessDpiAwareness(dpiAwareness);
- qCDebug(lcQpaWindows)
- << __FUNCTION__ << "DpiAwareness=" << dpiAwareness
+ qCDebug(lcQpaWindow) << "DpiAwareness=" << dpiAwareness
<< "effective process DPI awareness=" << QWindowsContext::processDpiAwareness();
}
dpiAwarenessSet = true;
@@ -270,13 +238,14 @@ QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
QWindowsIntegration *QWindowsIntegration::m_instance = nullptr;
QWindowsIntegration::QWindowsIntegration(const QStringList &paramList) :
- d(new QWindowsIntegrationPrivate(paramList))
+ d(new QWindowsIntegrationPrivate)
{
m_instance = this;
+ d->parseOptions(this, paramList);
#if QT_CONFIG(clipboard)
d->m_clipboard.registerViewer();
#endif
- d->m_context.screenManager().handleScreenChanges();
+ d->m_context.screenManager().initialize();
d->m_context.setDetectAltGrModifier((d->m_options & DetectAltGrModifier) != 0);
}
@@ -287,9 +256,9 @@ QWindowsIntegration::~QWindowsIntegration()
void QWindowsIntegration::initialize()
{
- QString icStr = QPlatformInputContextFactory::requested();
- icStr.isNull() ? d->m_inputContext.reset(new QWindowsInputContext)
- : d->m_inputContext.reset(QPlatformInputContextFactory::create(icStr));
+ auto icStrs = QPlatformInputContextFactory::requested();
+ icStrs.isEmpty() ? d->m_inputContext.reset(new QWindowsInputContext)
+ : d->m_inputContext.reset(QPlatformInputContextFactory::create(icStrs));
}
bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
@@ -317,6 +286,8 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co
return true;
case SwitchableWidgetComposition:
return false; // QTBUG-68329 QTBUG-53515 QTBUG-54734
+ case BackingStoreStaticContents:
+ return true;
default:
return QPlatformIntegration::hasCapability(cap);
}
@@ -327,23 +298,27 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
{
if (window->type() == Qt::Desktop) {
auto *result = new QWindowsDesktopWindow(window);
- qCDebug(lcQpaWindows) << "Desktop window:" << window
+ qCDebug(lcQpaWindow) << "Desktop window:" << window
<< Qt::showbase << Qt::hex << result->winId() << Qt::noshowbase << Qt::dec << result->geometry();
return result;
}
QWindowsWindowData requested;
requested.flags = window->flags();
- requested.geometry = QHighDpi::toNativePixels(window->geometry(), window);
- // Apply custom margins (see QWindowsWindow::setCustomMargins())).
- const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
- if (customMarginsV.isValid())
- requested.customMargins = qvariant_cast<QMargins>(customMarginsV);
+ requested.geometry = window->isTopLevel()
+ ? QHighDpi::toNativePixels(window->geometry(), window)
+ : QHighDpi::toNativeLocalPosition(window->geometry(), window);
+ if (!(requested.flags & Qt::FramelessWindowHint)) {
+ // Apply custom margins (see QWindowsWindow::setCustomMargins())).
+ const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
+ if (customMarginsV.isValid())
+ requested.customMargins = qvariant_cast<QMargins>(customMarginsV);
+ }
QWindowsWindowData obtained =
QWindowsWindowData::create(window, requested,
QWindowsWindow::formatWindowTitle(window->title()));
- qCDebug(lcQpaWindows).nospace()
+ qCDebug(lcQpaWindow).nospace()
<< __FUNCTION__ << ' ' << window
<< "\n Requested: " << requested.geometry << " frame incl.="
<< QWindowsGeometryHint::positionIncludesFrame(window)
@@ -380,7 +355,7 @@ QPlatformWindow *QWindowsIntegration::createForeignWindow(QWindow *window, WId n
screen = pScreen->screen();
if (screen && screen != window->screen())
window->setScreen(screen);
- qCDebug(lcQpaWindows) << "Foreign window:" << window << Qt::showbase << Qt::hex
+ qCDebug(lcQpaWindow) << "Foreign window:" << window << Qt::showbase << Qt::hex
<< result->winId() << Qt::noshowbase << Qt::dec << obtainedGeometry << screen;
return result;
}
@@ -408,13 +383,6 @@ QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate()
}
qCWarning(lcQpaGl, "System OpenGL failed. Falling back to Software OpenGL.");
return QOpenGLStaticContext::create(true);
- // If ANGLE is requested, use it, don't try anything else.
- case QWindowsOpenGLTester::AngleRendererD3d9:
- case QWindowsOpenGLTester::AngleRendererD3d11:
- case QWindowsOpenGLTester::AngleRendererD3d11Warp:
- return QWindowsEGLStaticContext::create(requestedRenderer);
- case QWindowsOpenGLTester::Gles:
- return QWindowsEGLStaticContext::create(requestedRenderer);
case QWindowsOpenGLTester::SoftwareRasterizer:
if (QWindowsStaticOpenGLContext *swCtx = QOpenGLStaticContext::create(true))
return swCtx;
@@ -440,17 +408,8 @@ QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate()
return glCtx;
}
}
- if (QWindowsOpenGLTester::Renderers glesRenderers = supportedRenderers & QWindowsOpenGLTester::GlesMask) {
- if (QWindowsEGLStaticContext *eglCtx = QWindowsEGLStaticContext::create(glesRenderers))
- return eglCtx;
- }
return QOpenGLStaticContext::create(true);
-#elif defined(QT_OPENGL_ES_2)
- QWindowsOpenGLTester::Renderers glesRenderers = QWindowsOpenGLTester::requestedGlesRenderer();
- if (glesRenderers == QWindowsOpenGLTester::InvalidRenderer)
- glesRenderers = QWindowsOpenGLTester::supportedRenderers(QWindowsOpenGLTester::AngleRendererD3d11);
- return QWindowsEGLStaticContext::create(glesRenderers);
-#elif !defined(QT_NO_OPENGL)
+#else
return QOpenGLStaticContext::create();
#endif
}
@@ -464,18 +423,16 @@ QPlatformOpenGLContext *QWindowsIntegration::createPlatformOpenGLContext(QOpenGL
{
qCDebug(lcQpaGl) << __FUNCTION__ << context->format();
if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) {
- QScopedPointer<QWindowsOpenGLContext> result(staticOpenGLContext->createContext(context));
+ std::unique_ptr<QWindowsOpenGLContext> result(staticOpenGLContext->createContext(context));
if (result->isValid())
- return result.take();
+ return result.release();
}
return nullptr;
}
QOpenGLContext::OpenGLModuleType QWindowsIntegration::openGLModuleType()
{
-#if defined(QT_OPENGL_ES_2)
- return QOpenGLContext::LibGLES;
-#elif !defined(QT_OPENGL_DYNAMIC)
+#if !defined(QT_OPENGL_DYNAMIC)
return QOpenGLContext::LibGL;
#else
if (const QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext())
@@ -484,6 +441,33 @@ QOpenGLContext::OpenGLModuleType QWindowsIntegration::openGLModuleType()
#endif
}
+HMODULE QWindowsIntegration::openGLModuleHandle() const
+{
+ if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext())
+ return static_cast<HMODULE>(staticOpenGLContext->moduleHandle());
+
+ return nullptr;
+}
+
+QOpenGLContext *QWindowsIntegration::createOpenGLContext(HGLRC ctx, HWND window, QOpenGLContext *shareContext) const
+{
+ if (!ctx || !window)
+ return nullptr;
+
+ if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) {
+ std::unique_ptr<QWindowsOpenGLContext> result(staticOpenGLContext->createContext(ctx, window));
+ if (result->isValid()) {
+ auto *context = new QOpenGLContext;
+ context->setShareContext(shareContext);
+ auto *contextPrivate = QOpenGLContextPrivate::get(context);
+ contextPrivate->adopt(result.release());
+ return context;
+ }
+ }
+
+ return nullptr;
+}
+
QWindowsStaticOpenGLContext *QWindowsIntegration::staticOpenGLContext()
{
QWindowsIntegration *integration = QWindowsIntegration::instance();
@@ -500,14 +484,17 @@ QWindowsStaticOpenGLContext *QWindowsIntegration::staticOpenGLContext()
QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
{
if (!d->m_fontDatabase) {
-#ifdef QT_NO_FREETYPE
- d->m_fontDatabase = new QWindowsFontDatabase();
-#else // QT_NO_FREETYPE
+#ifndef QT_NO_FREETYPE
if (d->m_options & QWindowsIntegration::FontDatabaseFreeType)
d->m_fontDatabase = new QWindowsFontDatabaseFT;
else
- d->m_fontDatabase = new QWindowsFontDatabase;
#endif // QT_NO_FREETYPE
+#if QT_CONFIG(directwrite3)
+ if (!(d->m_options & (QWindowsIntegration::FontDatabaseGDI | QWindowsIntegration::DontUseDirectWriteFonts)))
+ d->m_fontDatabase = new QWindowsDirectWriteFontDatabase;
+ else
+#endif
+ d->m_fontDatabase = new QWindowsFontDatabase;
}
return d->m_fontDatabase;
}
@@ -555,14 +542,9 @@ QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) co
return QPlatformIntegration::styleHint(hint);
}
-Qt::KeyboardModifiers QWindowsIntegration::queryKeyboardModifiers() const
+QPlatformKeyMapper *QWindowsIntegration::keyMapper() const
{
- return QWindowsKeyMapper::queryKeyboardModifiers();
-}
-
-QList<int> QWindowsIntegration::possibleKeys(const QKeyEvent *e) const
-{
- return d->m_context.possibleKeys(e);
+ return d->m_context.keyMapper();
}
#if QT_CONFIG(clipboard)
@@ -609,12 +591,12 @@ QAbstractEventDispatcher * QWindowsIntegration::createEventDispatcher() const
QStringList QWindowsIntegration::themeNames() const
{
- return QStringList(QLatin1String(QWindowsTheme::name));
+ return QStringList(QLatin1StringView(QWindowsTheme::name));
}
QPlatformTheme *QWindowsIntegration::createPlatformTheme(const QString &name) const
{
- if (name == QLatin1String(QWindowsTheme::name))
+ if (name == QLatin1StringView(QWindowsTheme::name))
return new QWindowsTheme;
return QPlatformIntegration::createPlatformTheme(name);
}
@@ -629,6 +611,161 @@ void QWindowsIntegration::beep() const
MessageBeep(MB_OK); // For QApplication
}
+void QWindowsIntegration::setApplicationBadge(qint64 number)
+{
+ // Clamp to positive numbers, as the Windows API doesn't support negative numbers
+ number = qMax(0, number);
+
+ // Persist, so we can re-apply it on setting changes and Explorer restart
+ m_applicationBadgeNumber = number;
+
+ static const bool isWindows11 = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11;
+
+#if QT_CONFIG(cpp_winrt)
+ // We prefer the native BadgeUpdater API, that allows us to set a number directly,
+ // but it requires that the application has a package identity, and also doesn't
+ // seem to work in all cases on < Windows 11.
+ QT_TRY {
+ if (isWindows11 && qt_win_hasPackageIdentity()) {
+ using namespace winrt::Windows::UI::Notifications;
+ auto badgeXml = BadgeUpdateManager::GetTemplateContent(BadgeTemplateType::BadgeNumber);
+ badgeXml.SelectSingleNode(L"//badge/@value").NodeValue(winrt::box_value(winrt::to_hstring(number)));
+ BadgeUpdateManager::CreateBadgeUpdaterForApplication().Update(BadgeNotification(badgeXml));
+ return;
+ }
+ } QT_CATCH(...) {
+ // fall back to win32 implementation
+ }
+#endif
+
+ // Fallback for non-packaged apps, Windows 10, or Qt builds without WinRT/C++ support
+
+ if (!number) {
+ // Clear badge
+ setApplicationBadge(QImage());
+ return;
+ }
+
+ const bool isDarkMode = QWindowsTheme::instance()->colorScheme()
+ == Qt::ColorScheme::Dark;
+
+ QColor badgeColor;
+ QColor textColor;
+
+#if QT_CONFIG(cpp_winrt)
+ if (isWindows11) {
+ // Match colors used by BadgeUpdater
+ static const auto fromUIColor = [](winrt::Windows::UI::Color &&color) {
+ return QColor(color.R, color.G, color.B, color.A);
+ };
+ using namespace winrt::Windows::UI::ViewManagement;
+ const auto settings = UISettings();
+ badgeColor = fromUIColor(settings.GetColorValue(isDarkMode ?
+ UIColorType::AccentLight2 : UIColorType::Accent));
+ textColor = fromUIColor(settings.GetColorValue(UIColorType::Background));
+ }
+#endif
+
+ if (!badgeColor.isValid()) {
+ // Fall back to basic badge colors, based on Windows 10 look
+ badgeColor = isDarkMode ? Qt::black : QColor(220, 220, 220);
+ badgeColor.setAlphaF(0.5f);
+ textColor = isDarkMode ? Qt::white : Qt::black;
+ }
+
+ const auto devicePixelRatio = qApp->devicePixelRatio();
+
+ static const QSize iconBaseSize(16, 16);
+ QImage image(iconBaseSize * devicePixelRatio,
+ QImage::Format_ARGB32_Premultiplied);
+ image.fill(Qt::transparent);
+
+ QPainter painter(&image);
+
+ QRect badgeRect = image.rect();
+ QPen badgeBorderPen = Qt::NoPen;
+ if (!isWindows11) {
+ QColor badgeBorderColor = textColor;
+ badgeBorderColor.setAlphaF(0.5f);
+ badgeBorderPen = badgeBorderColor;
+ badgeRect.adjust(1, 1, -1, -1);
+ }
+ painter.setBrush(badgeColor);
+ painter.setPen(badgeBorderPen);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.drawEllipse(badgeRect);
+
+ auto pixelSize = qCeil(10.5 * devicePixelRatio);
+ // Unlike the BadgeUpdater API we're limited by a square
+ // badge, so adjust the font size when above two digits.
+ const bool textOverflow = number > 99;
+ if (textOverflow)
+ pixelSize *= 0.8;
+
+ QFont font = painter.font();
+ font.setPixelSize(pixelSize);
+ font.setWeight(isWindows11 ? QFont::Medium : QFont::DemiBold);
+ painter.setFont(font);
+
+ painter.setRenderHint(QPainter::TextAntialiasing, devicePixelRatio > 1);
+ painter.setPen(textColor);
+
+ auto text = textOverflow ? u"99+"_s : QString::number(number);
+ painter.translate(textOverflow ? 1 : 0, textOverflow ? 0 : -1);
+ painter.drawText(image.rect(), Qt::AlignCenter, text);
+
+ painter.end();
+
+ setApplicationBadge(image);
+}
+
+void QWindowsIntegration::setApplicationBadge(const QImage &image)
+{
+ QComHelper comHelper;
+
+ using Microsoft::WRL::ComPtr;
+
+ ComPtr<ITaskbarList3> taskbarList;
+ CoCreateInstance(CLSID_TaskbarList, nullptr,
+ CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&taskbarList));
+ if (!taskbarList) {
+ // There may not be any windows with a task bar button yet,
+ // in which case we'll apply the badge once a window with
+ // a button has been created.
+ return;
+ }
+
+ const auto hIcon = image.toHICON();
+
+ // Apply the icon to all top level windows, since the badge is
+ // set on an application level. If one of the windows go away
+ // the other windows will take over in showing the badge.
+ const auto topLevelWindows = QGuiApplication::topLevelWindows();
+ for (auto *topLevelWindow : topLevelWindows) {
+ if (!topLevelWindow->handle())
+ continue;
+ auto hwnd = reinterpret_cast<HWND>(topLevelWindow->winId());
+ taskbarList->SetOverlayIcon(hwnd, hIcon, L"");
+ }
+
+ DestroyIcon(hIcon);
+
+ // FIXME: Update icon when the application scale factor changes.
+ // Doing so in response to screen DPI changes is too soon, as the
+ // task bar is not yet ready for an updated icon, and will just
+ // result in a blurred icon even if our icon is high-DPI.
+}
+
+void QWindowsIntegration::updateApplicationBadge()
+{
+ // The system color settings have changed, or we are reacting
+ // to a task bar button being created for the fist time or after
+ // Explorer had crashed and re-started. In any case, re-apply the
+ // badge so that everything is up to date.
+ if (m_applicationBadgeNumber)
+ setApplicationBadge(m_applicationBadgeNumber);
+}
+
#if QT_CONFIG(vulkan)
QPlatformVulkanInstance *QWindowsIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
{
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index b49d21022b..c271207741 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -1,49 +1,19 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSINTEGRATION_H
#define QWINDOWSINTEGRATION_H
+#include "qwindowsapplication.h"
+
#include <qpa/qplatformintegration.h>
#include <QtCore/qscopedpointer.h>
-#include <QtFontDatabaseSupport/private/qwindowsfontdatabase_p.h>
+#include <QtGui/private/qwindowsfontdatabase_p.h>
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qopenglcontext_p.h>
+#endif
+#include <qpa/qplatformopenglcontext.h>
QT_BEGIN_NAMESPACE
@@ -53,6 +23,10 @@ class QWindowsWindow;
class QWindowsStaticOpenGLContext;
class QWindowsIntegration : public QPlatformIntegration
+#ifndef QT_NO_OPENGL
+ , public QNativeInterface::Private::QWindowsGLIntegration
+#endif
+ , public QWindowsApplication
{
Q_DISABLE_COPY_MOVE(QWindowsIntegration)
public:
@@ -70,7 +44,8 @@ public:
NoNativeMenus = 0x200,
DontUseWMPointer = 0x400,
DetectAltGrModifier = 0x800,
- RtlEnabled = 0x1000
+ RtlEnabled = 0x1000,
+ FontDatabaseGDI = 0x2000
};
explicit QWindowsIntegration(const QStringList &paramList);
@@ -84,6 +59,10 @@ public:
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
QOpenGLContext::OpenGLModuleType openGLModuleType() override;
static QWindowsStaticOpenGLContext *staticOpenGLContext();
+
+ HMODULE openGLModuleHandle() const override;
+ QOpenGLContext *createOpenGLContext(HGLRC context, HWND window,
+ QOpenGLContext *shareContext) const override;
#endif
QAbstractEventDispatcher *createEventDispatcher() const override;
void initialize() override;
@@ -103,8 +82,7 @@ public:
QPlatformServices *services() const override;
QVariant styleHint(StyleHint hint) const override;
- Qt::KeyboardModifiers queryKeyboardModifiers() const override;
- QList<int> possibleKeys(const QKeyEvent *e) const override;
+ QPlatformKeyMapper *keyMapper() const override;
static QWindowsIntegration *instance() { return m_instance; }
@@ -112,6 +90,10 @@ public:
void beep() const override;
+ void setApplicationBadge(qint64 number) override;
+ void setApplicationBadge(const QImage &image);
+ void updateApplicationBadge();
+
#if QT_CONFIG(sessionmanager)
QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const override;
#endif
@@ -127,6 +109,8 @@ private:
QScopedPointer<QWindowsIntegrationPrivate> d;
static QWindowsIntegration *m_instance;
+
+ qint64 m_applicationBadgeNumber = 0;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp b/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp
index 44b7523fa6..0542473a4b 100644
--- a/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp
+++ b/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp
@@ -1,46 +1,12 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsinternalmimedata.h"
#include "qwindowscontext.h"
-#include "qwindowsmime.h"
+#include "qwindowsmimeregistry.h"
#include <QtCore/qdebug.h>
+#include <QtCore/qvariant.h>
+
/*!
\class QWindowsInternalMimeDataBase
\brief Base for implementations of QInternalMimeData using a IDataObject COM object.
@@ -56,11 +22,10 @@
The base class introduces new virtuals to obtain and release
the instances IDataObject from the clipboard or Drag and Drop and
- does conversion using QWindowsMime classes.
+ does conversion using QWindowsMimeConverter classes.
- \sa QInternalMimeData, QWindowsMime, QWindowsMimeConverter
+ \sa QInternalMimeData, QWindowsMimeConverter, QWindowsMimeRegistry
\internal
- \ingroup qt-lighthouse-win
*/
bool QWindowsInternalMimeData::hasFormat_sys(const QString &mime) const
@@ -69,7 +34,7 @@ bool QWindowsInternalMimeData::hasFormat_sys(const QString &mime) const
if (!pDataObj)
return false;
- const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter();
+ const QWindowsMimeRegistry &mc = QWindowsContext::instance()->mimeConverter();
const bool has = mc.converterToMime(mime, pDataObj) != nullptr;
releaseDataObject(pDataObj);
qCDebug(lcQpaMime) << __FUNCTION__ << mime << has;
@@ -82,29 +47,28 @@ QStringList QWindowsInternalMimeData::formats_sys() const
if (!pDataObj)
return QStringList();
- const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter();
+ const QWindowsMimeRegistry &mc = QWindowsContext::instance()->mimeConverter();
const QStringList fmts = mc.allMimesForFormats(pDataObj);
releaseDataObject(pDataObj);
qCDebug(lcQpaMime) << __FUNCTION__ << fmts;
return fmts;
}
-QVariant QWindowsInternalMimeData::retrieveData_sys(const QString &mimeType,
- QVariant::Type type) const
+QVariant QWindowsInternalMimeData::retrieveData_sys(const QString &mimeType, QMetaType type) const
{
IDataObject *pDataObj = retrieveDataObject();
if (!pDataObj)
return QVariant();
QVariant result;
- const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter();
- if (const QWindowsMime *converter = mc.converterToMime(mimeType, pDataObj))
+ const QWindowsMimeRegistry &mc = QWindowsContext::instance()->mimeConverter();
+ if (auto converter = mc.converterToMime(mimeType, pDataObj))
result = converter->convertToMime(mimeType, pDataObj, type);
releaseDataObject(pDataObj);
if (QWindowsContext::verbose) {
- qCDebug(lcQpaMime) <<__FUNCTION__ << ' ' << mimeType << ' ' << type
- << " returns " << result.type()
- << (result.type() != QVariant::ByteArray ? result.toString() : QStringLiteral("<data>"));
+ qCDebug(lcQpaMime) <<__FUNCTION__ << ' ' << mimeType << ' ' << type.name()
+ << " returns " << result.metaType().name()
+ << (result.metaType().id() != QMetaType::QByteArray ? result.toString() : QStringLiteral("<data>"));
}
return result;
}
diff --git a/src/plugins/platforms/windows/qwindowsinternalmimedata.h b/src/plugins/platforms/windows/qwindowsinternalmimedata.h
index dbc1ea3922..64d4ceabdf 100644
--- a/src/plugins/platforms/windows/qwindowsinternalmimedata.h
+++ b/src/plugins/platforms/windows/qwindowsinternalmimedata.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSINTERNALMIME_H
#define QWINDOWSINTERNALMIME_H
@@ -54,7 +18,7 @@ class QWindowsInternalMimeData : public QInternalMimeData {
public:
bool hasFormat_sys(const QString &mimetype) const override;
QStringList formats_sys() const override;
- QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const override;
+ QVariant retrieveData_sys(const QString &mimetype, QMetaType preferredType) const override;
protected:
virtual IDataObject *retrieveDataObject() const = 0;
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index e3edf7e81e..ba76cda40b 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowskeymapper.h"
#include "qwindowscontext.h"
@@ -49,8 +13,9 @@
#include <private/qguiapplication_p.h>
#include <private/qhighdpiscaling_p.h>
#include <QtGui/qevent.h>
-#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
+#include <QtGui/private/qwindowsguieventdispatcher_p.h>
#include <QtCore/private/qdebug_p.h>
+#include <QtCore/private/qtools_p.h>
#if defined(WM_APPCOMMAND)
# ifndef FAPPCOMMAND_MOUSE
@@ -88,7 +53,6 @@ QT_BEGIN_NAMESPACE
\class QWindowsKeyMapper
\brief Translates Windows keys to QWindowSystemInterface events.
\internal
- \ingroup qt-lighthouse-win
In addition, handles some special keys to display system menus, etc.
The code originates from \c qkeymapper_win.cpp.
@@ -124,9 +88,17 @@ QWindowsKeyMapper::~QWindowsKeyMapper()= default;
#define VK_OEM_3 0xC0
#endif
-// We not only need the scancode itself but also the extended bit of key messages. Thus we need
-// the additional bit when masking the scancode.
-enum { scancodeBitmask = 0x1ff };
+// Get scancode from the given message
+static constexpr quint32 getScancode(const MSG &msg)
+{
+ const auto keyFlags = HIWORD(msg.lParam);
+ quint32 scancode = LOBYTE(keyFlags);
+ // if extended-key flag is on, the scan code consists of a sequence of two bytes,
+ // where the first byte has a value of 0xe0.
+ if ((keyFlags & KF_EXTENDED) != 0)
+ scancode |= 0xE000;
+ return scancode;
+}
// Key recorder ------------------------------------------------------------------------[ start ] --
struct KeyRecord {
@@ -390,7 +362,8 @@ static const uint KeyTbl[] = { // Keyboard mapping table
Qt::Key_MediaNext, // 176 0xB0 VK_MEDIA_NEXT_TRACK | Next Track key
Qt::Key_MediaPrevious, //177 0xB1 VK_MEDIA_PREV_TRACK | Previous Track key
Qt::Key_MediaStop, // 178 0xB2 VK_MEDIA_STOP | Stop Media key
- Qt::Key_MediaPlay, // 179 0xB3 VK_MEDIA_PLAY_PAUSE | Play/Pause Media key
+ Qt::Key_MediaTogglePlayPause,
+ // 179 0xB3 VK_MEDIA_PLAY_PAUSE | Play/Pause Media key
Qt::Key_LaunchMail, // 180 0xB4 VK_LAUNCH_MAIL | Start Mail key
Qt::Key_LaunchMedia,// 181 0xB5 VK_LAUNCH_MEDIA_SELECT Select Media key
Qt::Key_Launch0, // 182 0xB6 VK_LAUNCH_APP1 | Start Application 1 key
@@ -541,7 +514,7 @@ static const Qt::KeyboardModifiers ModsTbl[] = {
Qt::NoModifier, // Fall-back to raw Key_*
};
static const size_t NumMods = sizeof ModsTbl / sizeof *ModsTbl;
-Q_STATIC_ASSERT((NumMods == KeyboardLayoutItem::NumQtKeys));
+static_assert((NumMods == KeyboardLayoutItem::NumQtKeys));
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const KeyboardLayoutItem &k)
@@ -567,33 +540,6 @@ QDebug operator<<(QDebug d, const KeyboardLayoutItem &k)
d << ')';
return d;
}
-
-// Helpers to format a list of int as Qt key sequence
-class formatKeys
-{
-public:
- explicit formatKeys(const QList<int> &keys) : m_keys(keys) {}
-
-private:
- friend QDebug operator<<(QDebug d, const formatKeys &keys);
- const QList<int> &m_keys;
-};
-
-QDebug operator<<(QDebug d, const formatKeys &k)
-{
- QDebugStateSaver saver(d);
- d.nospace();
- d << '(';
- for (int i =0, size = k.m_keys.size(); i < size; ++i) {
- if (i)
- d << ", ";
- d << QKeySequence(k.m_keys.at(i));
- }
- d << ')';
- return d;
-}
-#else // !QT_NO_DEBUG_STREAM
-static int formatKeys(const QList<int> &) { return 0; }
#endif // QT_NO_DEBUG_STREAM
/**
@@ -635,8 +581,7 @@ static inline quint32 toKeyOrUnicode(quint32 vk, quint32 scancode, unsigned char
static inline int asciiToKeycode(char a, int state)
{
- if (a >= 'a' && a <= 'z')
- a = toupper(a);
+ a = QtMiscUtils::toAsciiUpper(a);
if ((state & Qt::ControlModifier) != 0) {
if (a >= 0 && a <= 31) // Ctrl+@..Ctrl+A..CTRL+Z..Ctrl+_
a += '@'; // to @..A..Z.._
@@ -692,7 +637,7 @@ void QWindowsKeyMapper::updateKeyMap(const MSG &msg)
{
unsigned char kbdBuffer[256]; // Will hold the complete keyboard state
GetKeyboardState(kbdBuffer);
- const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
+ const quint32 scancode = getScancode(msg);
updatePossibleKeyCodes(kbdBuffer, scancode, quint32(msg.wParam));
}
@@ -785,6 +730,27 @@ static inline QString messageKeyText(const MSG &msg)
return ch.isNull() ? QString() : QString(ch);
}
+[[nodiscard]] static inline int getTitleBarHeight(const HWND hwnd)
+{
+ const UINT dpi = GetDpiForWindow(hwnd);
+ const int captionHeight = GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
+ if (IsZoomed(hwnd))
+ return captionHeight;
+ // The frame height should also be taken into account if the window
+ // is not maximized.
+ const int frameHeight = GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
+ + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
+ return captionHeight + frameHeight;
+}
+
+[[nodiscard]] static inline bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags)
+{
+ static constexpr const Qt::WindowFlags titleBarHints =
+ Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint;
+ return (flags & Qt::WindowSystemMenuHint) && (flags & Qt::WindowTitleHint) && !(flags & titleBarHints)
+ && (flags & (Qt::FramelessWindowHint | Qt::CustomizeWindowHint));
+}
+
static void showSystemMenu(QWindow* w)
{
QWindow *topLevel = QWindowsWindow::topLevelOf(w);
@@ -793,41 +759,49 @@ static void showSystemMenu(QWindow* w)
if (!menu)
return; // no menu for this window
-#define enabled (MF_BYCOMMAND | MF_ENABLED)
-#define disabled (MF_BYCOMMAND | MF_GRAYED)
+#define enabled (MF_BYCOMMAND | MFS_ENABLED)
+#define disabled (MF_BYCOMMAND | MFS_GRAYED)
- EnableMenuItem(menu, SC_MINIMIZE, (topLevel->flags() & Qt::WindowMinimizeButtonHint)?enabled:disabled);
- bool maximized = IsZoomed(topLevelHwnd);
+ EnableMenuItem(menu, SC_MINIMIZE, (topLevel->flags() & Qt::WindowMinimizeButtonHint) ? enabled : disabled);
+ const bool maximized = IsZoomed(topLevelHwnd);
- EnableMenuItem(menu, SC_MAXIMIZE, ! (topLevel->flags() & Qt::WindowMaximizeButtonHint) || maximized?disabled:enabled);
- EnableMenuItem(menu, SC_RESTORE, maximized?enabled:disabled);
+ EnableMenuItem(menu, SC_MAXIMIZE, !(topLevel->flags() & Qt::WindowMaximizeButtonHint) || maximized ? disabled : enabled);
// We should _not_ check with the setFixedSize(x,y) case here, since Windows is not able to check
// this and our menu here would be out-of-sync with the menu produced by mouse-click on the
// System Menu, or right-click on the title bar.
- EnableMenuItem(menu, SC_SIZE, (topLevel->flags() & Qt::MSWindowsFixedSizeDialogHint) || maximized?disabled:enabled);
- EnableMenuItem(menu, SC_MOVE, maximized?disabled:enabled);
+ EnableMenuItem(menu, SC_SIZE, (topLevel->flags() & Qt::MSWindowsFixedSizeDialogHint) || maximized ? disabled : enabled);
+ EnableMenuItem(menu, SC_MOVE, maximized ? disabled : enabled);
EnableMenuItem(menu, SC_CLOSE, enabled);
+ EnableMenuItem(menu, SC_RESTORE, maximized ? enabled : disabled);
+
+ // Highlight the first entry in the menu, this is what native Win32 applications usually do.
+ HiliteMenuItem(topLevelHwnd, menu, SC_RESTORE, MF_BYCOMMAND | MFS_HILITE);
+
// Set bold on close menu item
- MENUITEMINFO closeItem;
- closeItem.cbSize = sizeof(MENUITEMINFO);
- closeItem.fMask = MIIM_STATE;
- closeItem.fState = MFS_DEFAULT;
- SetMenuItemInfo(menu, SC_CLOSE, FALSE, &closeItem);
+ SetMenuDefaultItem(menu, SC_CLOSE, FALSE);
#undef enabled
#undef disabled
+
const QPoint pos = QHighDpi::toNativePixels(topLevel->geometry().topLeft(), topLevel);
+ const int titleBarOffset = isSystemMenuOffsetNeeded(topLevel->flags()) ? getTitleBarHeight(topLevelHwnd) : 0;
const int ret = TrackPopupMenuEx(menu,
- TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
- pos.x(), pos.y(),
+ TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
+ pos.x(), pos.y() + titleBarOffset,
topLevelHwnd,
nullptr);
+
+ // Remove the highlight of the restore menu item, otherwise when the user right-clicks
+ // on the title bar, the popuped system menu will also highlight the restore item, which
+ // is not appropriate, it should only be highlighted if the menu is brought up by keyboard.
+ HiliteMenuItem(topLevelHwnd, menu, SC_RESTORE, MF_BYCOMMAND | MFS_UNHILITE);
+
if (ret)
qWindowsWndProc(topLevelHwnd, WM_SYSCOMMAND, WPARAM(ret), 0);
}
-static inline void sendExtendedPressRelease(QWindow *w, int k,
+static inline void sendExtendedPressRelease(QWindow *w, unsigned long timestamp, int k,
Qt::KeyboardModifiers mods,
quint32 nativeScanCode,
quint32 nativeVirtualKey,
@@ -836,8 +810,8 @@ static inline void sendExtendedPressRelease(QWindow *w, int k,
bool autorep = false,
ushort count = 1)
{
- QWindowSystemInterface::handleExtendedKeyEvent(w, QEvent::KeyPress, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
- QWindowSystemInterface::handleExtendedKeyEvent(w, QEvent::KeyRelease, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
+ QWindowSystemInterface::handleExtendedKeyEvent(w, timestamp, QEvent::KeyPress, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
+ QWindowSystemInterface::handleExtendedKeyEvent(w, timestamp, QEvent::KeyRelease, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
}
/*!
@@ -904,11 +878,11 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con
const int qtKey = int(CmdTbl[cmd]);
if (!skipPressRelease)
- sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0);
+ sendExtendedPressRelease(receiver, msg.time, qtKey, Qt::KeyboardModifier(state), 0, 0, 0);
// QTBUG-43343: Make sure to return false if Qt does not handle the key, otherwise,
// the keys are not passed to the active media player.
# if QT_CONFIG(shortcut)
- const QKeySequence sequence(Qt::Modifier(state) + qtKey);
+ const QKeySequence sequence(Qt::Modifier(state) | Qt::Key(qtKey));
return QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(sequence);
# else
return false;
@@ -949,7 +923,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
m_seenAltGr = true;
const UINT msgType = msg.message;
- const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
+ const quint32 scancode = getScancode(msg);
auto vk_key = quint32(msg.wParam);
quint32 nModifiers = 0;
@@ -984,7 +958,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
// A multi-character key or a Input method character
// not found by our look-ahead
if (msgType == WM_CHAR || msgType == WM_IME_CHAR) {
- sendExtendedPressRelease(receiver, 0, Qt::KeyboardModifier(state), scancode, vk_key, nModifiers, messageKeyText(msg), false);
+ sendExtendedPressRelease(receiver, msg.time, 0, Qt::KeyboardModifier(state), scancode, 0, nModifiers, messageKeyText(msg), false);
return true;
}
@@ -1019,14 +993,14 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
if (dirStatus == VK_LSHIFT
&& ((msg.wParam == VK_SHIFT && GetKeyState(VK_LCONTROL))
|| (msg.wParam == VK_CONTROL && GetKeyState(VK_LSHIFT)))) {
- sendExtendedPressRelease(receiver, Qt::Key_Direction_L, {},
+ sendExtendedPressRelease(receiver, msg.time, Qt::Key_Direction_L, {},
scancode, vk_key, nModifiers, QString(), false);
result = true;
dirStatus = 0;
} else if (dirStatus == VK_RSHIFT
&& ( (msg.wParam == VK_SHIFT && GetKeyState(VK_RCONTROL))
|| (msg.wParam == VK_CONTROL && GetKeyState(VK_RSHIFT)))) {
- sendExtendedPressRelease(receiver, Qt::Key_Direction_R, {},
+ sendExtendedPressRelease(receiver, msg.time, Qt::Key_Direction_R, {},
scancode, vk_key, nModifiers, QString(), false);
result = true;
dirStatus = 0;
@@ -1220,7 +1194,6 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
switch (code) {
case Qt::Key_Escape:
case Qt::Key_Tab:
- case Qt::Key_Enter:
case Qt::Key_F4:
return false; // Send the event on to Windows
case Qt::Key_Space:
@@ -1240,9 +1213,9 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
// so, we have an auto-repeating key
if (rec) {
if (code < Qt::Key_Shift || code > Qt::Key_ScrollLock) {
- QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyRelease, code,
+ QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyRelease, code,
Qt::KeyboardModifier(state), scancode, quint32(msg.wParam), nModifiers, rec->text, true);
- QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyPress, code,
+ QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyPress, code,
Qt::KeyboardModifier(state), scancode, quint32(msg.wParam), nModifiers, rec->text, true);
result = true;
}
@@ -1256,7 +1229,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
#ifndef QT_NO_SHORTCUT
// Is Qt interested in the context menu key?
if (modifiers == Qt::SHIFT && code == Qt::Key_F10
- && !QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(QKeySequence(Qt::SHIFT + Qt::Key_F10))) {
+ && !QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(QKeySequence(Qt::SHIFT | Qt::Key_F10))) {
return false;
}
#endif // !QT_NO_SHORTCUT
@@ -1268,7 +1241,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
if (msg.wParam == VK_PACKET)
code = asciiToKeycode(char(uch.cell()), state);
- QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyPress, code,
+ QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyPress, code,
modifiers, scancode, quint32(msg.wParam), nModifiers, text, false);
result =true;
bool store = true;
@@ -1310,10 +1283,10 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
if ((msg.lParam & 0x40000000) == 0 &&
Qt::KeyboardModifier(state) == Qt::NoModifier &&
((code == Qt::Key_F18) || (code == Qt::Key_F19) || (code == Qt::Key_F20))) {
- QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyPress, code,
+ QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyPress, code,
Qt::MetaModifier, scancode,
quint32(msg.wParam), MetaLeft);
- QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyRelease, code,
+ QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyRelease, code,
Qt::NoModifier, scancode,
quint32(msg.wParam), 0);
result = true;
@@ -1325,7 +1298,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
// Map SHIFT + Tab to SHIFT + BackTab, QShortcutMap knows about this translation
if (code == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier)
code = Qt::Key_Backtab;
- QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyRelease, code,
+ QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyRelease, code,
Qt::KeyboardModifier(state), scancode, quint32(msg.wParam),
nModifiers,
(rec ? rec->text : QString()), false);
@@ -1347,7 +1320,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
return result;
}
-Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers()
+Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers() const
{
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
if (GetKeyState(VK_SHIFT) < 0)
@@ -1361,9 +1334,9 @@ Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers()
return modifiers;
}
-QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
+QList<QKeyCombination> QWindowsKeyMapper::possibleKeyCombinations(const QKeyEvent *e) const
{
- QList<int> result;
+ QList<QKeyCombination> result;
const quint32 nativeVirtualKey = e->nativeVirtualKey();
@@ -1377,31 +1350,34 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
quint32 baseKey = kbItem.qtKey[0];
Qt::KeyboardModifiers keyMods = e->modifiers();
if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) {
- result << int(Qt::Key_Enter + keyMods);
+ result << (Qt::Key_Enter | keyMods);
return result;
}
- result << int(baseKey + keyMods); // The base key is _always_ valid, of course
+
+ // The base key is _always_ valid, of course
+ result << QKeyCombination::fromCombined(int(baseKey) + int(keyMods));
for (size_t i = 1; i < NumMods; ++i) {
Qt::KeyboardModifiers neededMods = ModsTbl[i];
quint32 key = kbItem.qtKey[i];
if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) {
const Qt::KeyboardModifiers missingMods = keyMods & ~neededMods;
- const int matchedKey = int(key) + missingMods;
- const auto it =
- std::find_if(result.begin(), result.end(),
- [key] (int k) { return (k & ~Qt::KeyboardModifierMask) == key; });
+ const auto matchedKey = QKeyCombination::fromCombined(int(key) + int(missingMods));
+ const auto it = std::find_if(result.begin(), result.end(),
+ [key](auto keyCombination) {
+ return keyCombination.key() == key;
+ });
// QTBUG-67200: Use the match with the least modifiers (prefer
// Shift+9 over Alt + Shift + 9) resulting in more missing modifiers.
if (it == result.end())
result << matchedKey;
- else if (missingMods > (*it & Qt::KeyboardModifierMask))
+ else if (missingMods > it->keyboardModifiers())
*it = matchedKey;
}
}
qCDebug(lcQpaEvents) << __FUNCTION__ << e << "nativeVirtualKey="
<< Qt::showbase << Qt::hex << e->nativeVirtualKey() << Qt::dec << Qt::noshowbase
- << e->modifiers() << kbItem << "\n returns" << formatKeys(result);
+ << e->modifiers() << kbItem << "\n returns" << result;
return result;
}
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.h b/src/plugins/platforms/windows/qwindowskeymapper.h
index b1ada1d373..72b2536ad7 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.h
+++ b/src/plugins/platforms/windows/qwindowskeymapper.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSKEYMAPPER_H
#define QWINDOWSKEYMAPPER_H
@@ -44,6 +8,8 @@
#include <QtCore/qlocale.h>
+#include <qpa/qplatformkeymapper.h>
+
QT_BEGIN_NAMESPACE
class QKeyEvent;
@@ -69,7 +35,7 @@ struct KeyboardLayoutItem {
quint32 qtKey[NumQtKeys]; // Can by any Qt::Key_<foo>, or unicode character
};
-class QWindowsKeyMapper
+class QWindowsKeyMapper : public QPlatformKeyMapper
{
Q_DISABLE_COPY_MOVE(QWindowsKeyMapper)
public:
@@ -89,8 +55,8 @@ public:
QWindow *keyGrabber() const { return m_keyGrabber; }
void setKeyGrabber(QWindow *w) { m_keyGrabber = w; }
- static Qt::KeyboardModifiers queryKeyboardModifiers();
- QList<int> possibleKeys(const QKeyEvent *e) const;
+ Qt::KeyboardModifiers queryKeyboardModifiers() const override;
+ QList<QKeyCombination> possibleKeyCombinations(const QKeyEvent *e) const override;
private:
bool translateKeyEventInternal(QWindow *receiver, MSG msg, bool grab, LRESULT *lResult);
diff --git a/src/plugins/platforms/windows/qwindowsmenu.cpp b/src/plugins/platforms/windows/qwindowsmenu.cpp
index d20edd685e..79deeeaea2 100644
--- a/src/plugins/platforms/windows/qwindowsmenu.cpp
+++ b/src/plugins/platforms/windows/qwindowsmenu.cpp
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsmenu.h"
#include "qwindowscontext.h"
#include "qwindowswindow.h"
#include <QtGui/qwindow.h>
+#include <QtGui/private/qpixmap_win_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qvariant.h>
#include <QtCore/qmetaobject.h>
@@ -56,7 +21,7 @@ QT_BEGIN_NAMESPACE
\brief Windows native menu bar
\list
- \li \l{https://msdn.microsoft.com/de-de/library/windows/desktop/ms647553(v=vs.85).aspx#_win32_Menu_Creation_Functions},
+ \li \l{https://docs.microsoft.com/en-us/windows/win32/menurc/about-menus},
\e{About Menus}
\endlist
@@ -65,15 +30,14 @@ QT_BEGIN_NAMESPACE
Qt Widgets, either the containers or the items might be deleted first.
\internal
- \ingroup qt-lighthouse-win
*/
static uint nextId = 1;
-// Find a QPlatformMenu[Item]* in a vector of QWindowsMenu[Item], where
-// QVector::indexOf() cannot be used since it wants a QWindowsMenu[Item]*
+// Find a QPlatformMenu[Item]* in a list of QWindowsMenu[Item], where
+// QList::indexOf() cannot be used since it wants a QWindowsMenu[Item]*
template <class Derived, class Needle>
-static int indexOf(const QVector<Derived *> &v, const Needle *needle)
+static int indexOf(const QList<Derived *> &v, const Needle *needle)
{
for (int i = 0, size = v.size(); i < size; ++i) {
if (v.at(i) == needle)
@@ -82,9 +46,9 @@ static int indexOf(const QVector<Derived *> &v, const Needle *needle)
return -1;
}
-// Helper for inserting a QPlatformMenu[Item]* into a vector of QWindowsMenu[Item].
+// Helper for inserting a QPlatformMenu[Item]* into a list of QWindowsMenu[Item].
template <class Derived, class Base>
-static int insertBefore(QVector<Derived *> *v, Base *newItemIn, const Base *before = nullptr)
+static int insertBefore(QList<Derived *> *v, Base *newItemIn, const Base *before = nullptr)
{
int index = before ? indexOf(*v, before) : -1;
if (index != -1) {
@@ -176,7 +140,7 @@ static QWindowsMenu *findMenuByHandle(const Menu *menu, HMENU hMenu)
}
template <class MenuType>
-static int findNextVisibleEntry(const QVector<MenuType *> &entries, int pos)
+static int findNextVisibleEntry(const QList<MenuType *> &entries, int pos)
{
for (int i = pos, size = entries.size(); i < size; ++i) {
if (entries.at(i)->isVisible())
@@ -266,8 +230,6 @@ void QWindowsMenuItem::setIcon(const QIcon &icon)
updateBitmap();
}
-Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0);
-
void QWindowsMenuItem::updateBitmap()
{
freeBitmap();
@@ -445,7 +407,7 @@ QString QWindowsMenuItem::nativeText() const
QString result = m_text;
#if QT_CONFIG(shortcut)
if (!m_shortcut.isEmpty()) {
- result += QLatin1Char('\t');
+ result += u'\t';
result += m_shortcut.toString(QKeySequence::NativeText);
}
#endif
@@ -794,20 +756,13 @@ QWindowsMenuBar *QWindowsMenuBar::menuBarOf(const QWindow *notYetCreatedWindow)
? qobject_cast<QWindowsMenuBar *>(menuBarV.value<QObject *>()) : nullptr;
}
-static inline void forceNcCalcSize(HWND hwnd)
-{
- // Force WM_NCCALCSIZE to adjust margin: Does not appear to work?
- SetWindowPos(hwnd, nullptr, 0, 0, 0, 0,
- SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
-}
-
void QWindowsMenuBar::install(QWindowsWindow *window)
{
const HWND hwnd = window->handle();
const BOOL result = SetMenu(hwnd, m_hMenuBar);
if (result) {
window->setMenuBar(this);
- forceNcCalcSize(hwnd);
+ QWindowsContext::forceNcCalcSize(hwnd);
}
}
@@ -817,7 +772,7 @@ void QWindowsMenuBar::removeFromWindow()
const HWND hwnd = window->handle();
SetMenu(hwnd, nullptr);
window->setMenuBar(nullptr);
- forceNcCalcSize(hwnd);
+ QWindowsContext::forceNcCalcSize(hwnd);
}
}
@@ -870,7 +825,7 @@ void QWindowsMenuBar::redraw() const
#ifndef QT_NO_DEBUG_STREAM
template <class M> /* Menu[Item] */
-static void formatTextSequence(QDebug &d, const QVector<M *> &v)
+static void formatTextSequence(QDebug &d, const QList<M *> &v)
{
if (const int size = v.size()) {
d << '[' << size << "](";
diff --git a/src/plugins/platforms/windows/qwindowsmenu.h b/src/plugins/platforms/windows/qwindowsmenu.h
index aa36846ec0..6f66180d82 100644
--- a/src/plugins/platforms/windows/qwindowsmenu.h
+++ b/src/plugins/platforms/windows/qwindowsmenu.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSMENU_H
#define QWINDOWSMENU_H
@@ -44,8 +8,7 @@
#include <qpa/qplatformmenu.h>
-#include <QtCore/qvector.h>
-#include <QtCore/qpair.h>
+#include <QtCore/qlist.h>
QT_BEGIN_NAMESPACE
@@ -120,7 +83,7 @@ class QWindowsMenu : public QPlatformMenu
{
Q_OBJECT
public:
- using MenuItems = QVector<QWindowsMenuItem *>;
+ using MenuItems = QList<QWindowsMenuItem *>;
QWindowsMenu();
~QWindowsMenu();
@@ -196,7 +159,7 @@ class QWindowsMenuBar : public QPlatformMenuBar
{
Q_OBJECT
public:
- using Menus = QVector<QWindowsMenu *>;
+ using Menus = QList<QWindowsMenu *>;
QWindowsMenuBar();
~QWindowsMenuBar() override;
diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h
deleted file mode 100644
index f8708f1259..0000000000
--- a/src/plugins/platforms/windows/qwindowsmime.h
+++ /dev/null
@@ -1,108 +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$
-**
-****************************************************************************/
-
-#ifndef QWINDOWSMIME_H
-#define QWINDOWSMIME_H
-
-#include <QtCore/qt_windows.h>
-
-#include <QtCore/qvector.h>
-#include <QtCore/qvariant.h>
-
-QT_BEGIN_NAMESPACE
-
-class QDebug;
-class QMimeData;
-
-class QWindowsMime
-{
- Q_DISABLE_COPY_MOVE(QWindowsMime)
-public:
- QWindowsMime();
- virtual ~QWindowsMime();
-
- // for converting from Qt
- virtual bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const = 0;
- virtual bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const = 0;
- virtual QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const = 0;
-
- // for converting to Qt
- virtual bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const = 0;
- virtual QVariant convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const = 0;
- virtual QString mimeForFormat(const FORMATETC &formatetc) const = 0;
-
- static int registerMimeType(const QString &mime);
-};
-
-class QWindowsMimeConverter
-{
- Q_DISABLE_COPY_MOVE(QWindowsMimeConverter)
-public:
- QWindowsMimeConverter();
- ~QWindowsMimeConverter();
-
- QWindowsMime *converterToMime(const QString &mimeType, IDataObject *pDataObj) const;
- QStringList allMimesForFormats(IDataObject *pDataObj) const;
- QWindowsMime *converterFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
- QVector<FORMATETC> allFormatsForMime(const QMimeData *mimeData) const;
-
- // Convenience.
- QVariant convertToMime(const QStringList &mimeTypes, IDataObject *pDataObj, QVariant::Type preferredType,
- QString *format = nullptr) const;
-
- void registerMime(QWindowsMime *mime);
- void unregisterMime(QWindowsMime *mime) { m_mimes.removeOne(mime); }
-
- static QString clipboardFormatName(int cf);
-
-private:
- void ensureInitialized() const;
-
- mutable QVector<QWindowsMime *> m_mimes;
- mutable int m_internalMimeCount = 0;
-};
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug, const FORMATETC &);
-QDebug operator<<(QDebug d, IDataObject *);
-#endif
-
-QT_END_NAMESPACE
-
-#endif // QWINDOWSMIME_H
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmimeregistry.cpp
index 1c6c999f05..8d147e8fa0 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmimeregistry.cpp
@@ -1,48 +1,11 @@
-/****************************************************************************
-**
-** 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 "qwindowsmime.h"
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwindowsmimeregistry.h"
#include "qwindowscontext.h"
#include <QtGui/private/qinternalmimedata_p.h>
#include <QtCore/qbytearraymatcher.h>
-#include <QtCore/qtextcodec.h>
#include <QtCore/qmap.h>
#include <QtCore/qurl.h>
#include <QtCore/qdir.h>
@@ -56,6 +19,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/* The MSVC compilers allows multi-byte characters, that has the behavior of
* that each character gets shifted into position. 0x73524742 below is for MSVC
* equivalent to doing 'sRGB', but this does of course not work
@@ -97,7 +62,6 @@ struct BMP_BITMAPV5HEADER {
DWORD bV5ProfileSize;
DWORD bV5Reserved;
};
-static const int BMP_BITFIELDS = 3;
static const char dibFormatC[] = "dib";
@@ -115,16 +79,15 @@ static inline QByteArray msgConversionError(const char *func, const char *format
return msg;
}
-static inline QImage readDib(QByteArray data)
+static inline bool readDib(QBuffer &buffer, QImage &img)
{
- QBuffer buffer(&data);
- buffer.open(QIODevice::ReadOnly);
QImageReader reader(&buffer, dibFormatC);
if (!reader.canRead()) {
- qWarning("%s", msgConversionError(__FUNCTION__, dibFormatC).constData());
- return QImage();
+ qWarning("%s", msgConversionError(__FUNCTION__, dibFormatC).constData());
+ return false;
}
- return reader.read();
+ img = reader.read();
+ return true;
}
static QByteArray writeDib(const QImage &img)
@@ -149,7 +112,10 @@ static bool qt_write_dibv5(QDataStream &s, QImage image)
return false;
//depth will be always 32
- int bpl_bmp = image.width()*4;
+ qsizetype bpl_bmp = qsizetype(image.width()) * 4;
+ qsizetype size = bpl_bmp * image.height();
+ if (qsizetype(DWORD(size)) != size)
+ return false;
BMP_BITMAPV5HEADER bi;
ZeroMemory(&bi, sizeof(bi));
@@ -175,8 +141,20 @@ static bool qt_write_dibv5(QDataStream &s, QImage image)
if (s.status() != QDataStream::Ok)
return false;
+ d->write(reinterpret_cast<const char *>(&bi.bV5RedMask), sizeof(bi.bV5RedMask));
+ if (s.status() != QDataStream::Ok)
+ return false;
+
+ d->write(reinterpret_cast<const char *>(&bi.bV5GreenMask), sizeof(bi.bV5GreenMask));
+ if (s.status() != QDataStream::Ok)
+ return false;
+
+ d->write(reinterpret_cast<const char *>(&bi.bV5BlueMask), sizeof(bi.bV5BlueMask));
+ if (s.status() != QDataStream::Ok)
+ return false;
+
if (image.format() != QImage::Format_ARGB32)
- image = image.convertToFormat(QImage::Format_ARGB32);
+ image = std::move(image).convertToFormat(QImage::Format_ARGB32);
auto *buf = new uchar[bpl_bmp];
@@ -211,94 +189,6 @@ static bool qt_write_dibv5(QDataStream &s, QImage image)
return true;
}
-static int calc_shift(int mask)
-{
- int result = 0;
- while (!(mask & 1)) {
- result++;
- mask >>= 1;
- }
- return result;
-}
-
-//Supports only 32 bit DIBV5
-static bool qt_read_dibv5(QDataStream &s, QImage &image)
-{
- BMP_BITMAPV5HEADER bi;
- QIODevice* d = s.device();
- if (d->atEnd())
- return false;
-
- d->read(reinterpret_cast<char *>(&bi), sizeof(bi)); // read BITMAPV5HEADER header
- if (s.status() != QDataStream::Ok)
- return false;
-
- const int nbits = bi.bV5BitCount;
- if (nbits != 32 || bi.bV5Planes != 1 || bi.bV5Compression != BMP_BITFIELDS)
- return false; //Unsupported DIBV5 format
-
- const int w = bi.bV5Width;
- int h = bi.bV5Height;
- const int red_mask = int(bi.bV5RedMask);
- const int green_mask = int(bi.bV5GreenMask);
- const int blue_mask = int(bi.bV5BlueMask);
- const int alpha_mask = int(bi.bV5AlphaMask);
-
- const QImage::Format format = QImage::Format_ARGB32;
-
- if (bi.bV5Height < 0)
- h = -h; // support images with negative height
- if (image.size() != QSize(w, h) || image.format() != format) {
- image = QImage(w, h, format);
- if (image.isNull()) // could not create image
- return false;
- }
- image.setDotsPerMeterX(bi.bV5XPelsPerMeter);
- image.setDotsPerMeterY(bi.bV5YPelsPerMeter);
-
- const int red_shift = calc_shift(red_mask);
- const int green_shift = calc_shift(green_mask);
- const int blue_shift = calc_shift(blue_mask);
- const int alpha_shift = alpha_mask ? calc_shift(alpha_mask) : 0u;
-
- const int bpl = image.bytesPerLine();
- uchar *data = image.bits();
-
- auto *buf24 = new uchar[bpl];
- const int bpl24 = ((w * nbits + 31) / 32) * 4;
-
- while (--h >= 0) {
- QRgb *p = reinterpret_cast<QRgb *>(data + h * bpl);
- QRgb *end = p + w;
- if (d->read(reinterpret_cast<char *>(buf24), bpl24) != bpl24)
- break;
- const uchar *b = buf24;
- while (p < end) {
- const int c = *b | (*(b + 1)) << 8 | (*(b + 2)) << 16 | (*(b + 3)) << 24;
- *p++ = qRgba(((c & red_mask) >> red_shift) ,
- ((c & green_mask) >> green_shift),
- ((c & blue_mask) >> blue_shift),
- ((c & alpha_mask) >> alpha_shift));
- b += 4;
- }
- }
- delete[] buf24;
-
- if (bi.bV5Height < 0) {
- // Flip the image
- auto *buf = new uchar[bpl];
- h = -bi.bV5Height;
- for (int y = 0; y < h/2; ++y) {
- memcpy(buf, data + y * bpl, size_t(bpl));
- memcpy(data + y*bpl, data + (h - y -1) * bpl, size_t(bpl));
- memcpy(data + (h - y -1 ) * bpl, buf, size_t(bpl));
- }
- delete [] buf;
- }
-
- return true;
-}
-
// helpers for using global memory
static int getCf(const FORMATETC &formatetc)
@@ -410,7 +300,7 @@ QDebug operator<<(QDebug d, const FORMATETC &tc)
d << "CF_ENHMETAFILE";
break;
default:
- d << QWindowsMimeConverter::clipboardFormatName(tc.cfFormat);
+ d << QWindowsMimeRegistry::clipboardFormatName(tc.cfFormat);
break;
}
d << ", dwAspect=" << tc.dwAspect << ", lindex=" << tc.lindex
@@ -443,145 +333,21 @@ QDebug operator<<(QDebug d, IDataObject *dataObj)
}
#endif // !QT_NO_DEBUG_STREAM
-/*!
- \class QWindowsMime
- \brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats.
- \internal
- \ingroup qt-lighthouse-win
-
- Qt's drag-and-drop and clipboard facilities use the MIME standard.
- On X11, this maps trivially to the Xdnd protocol, but on Windows
- although some applications use MIME types to describe clipboard
- formats, others use arbitrary non-standardized naming conventions,
- or unnamed built-in formats of Windows.
-
- By instantiating subclasses of QWindowsMime that provide conversions
- between Windows Clipboard and MIME formats, you can convert
- proprietary clipboard formats to MIME formats.
-
- Qt has predefined support for the following Windows Clipboard formats:
-
- \table
- \header \li Windows Format \li Equivalent MIME type
- \row \li \c CF_UNICODETEXT \li \c text/plain
- \row \li \c CF_TEXT \li \c text/plain
- \row \li \c CF_DIB \li \c{image/xyz}, where \c xyz is
- a \l{QImageWriter::supportedImageFormats()}{Qt image format}
- \row \li \c CF_HDROP \li \c text/uri-list
- \row \li \c CF_INETURL \li \c text/uri-list
- \row \li \c CF_HTML \li \c text/html
- \endtable
-
- An example use of this class would be to map the Windows Metafile
- clipboard format (\c CF_METAFILEPICT) to and from the MIME type
- \c{image/x-wmf}. This conversion might simply be adding or removing
- a header, or even just passing on the data. See \l{Drag and Drop}
- for more information on choosing and definition MIME types.
-
- You can check if a MIME type is convertible using canConvertFromMime() and
- can perform conversions with convertToMime() and convertFromMime().
-
- \sa QWindowsMimeConverter
-*/
-
-/*!
-Constructs a new conversion object, adding it to the globally accessed
-list of available converters.
-*/
-QWindowsMime::QWindowsMime() = default;
-
-/*!
-Destroys a conversion object, removing it from the global
-list of available converters.
-*/
-QWindowsMime::~QWindowsMime() = default;
-
-/*!
- Registers the MIME type \a mime, and returns an ID number
- identifying the format on Windows.
-*/
-int QWindowsMime::registerMimeType(const QString &mime)
-{
- const UINT f = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (mime.utf16()));
- if (!f)
- qErrnoWarning("QWindowsMime::registerMimeType: Failed to register clipboard format");
-
- return int(f);
-}
-
-/*!
-\fn bool QWindowsMime::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
-
- Returns \c true if the converter can convert from the \a mimeData to
- the format specified in \a formatetc.
-
- All subclasses must reimplement this pure virtual function.
-*/
-
-/*!
- \fn bool QWindowsMime::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
-
- Returns \c true if the converter can convert to the \a mimeType from
- the available formats in \a pDataObj.
-
- All subclasses must reimplement this pure virtual function.
-*/
-
-/*!
-\fn QString QWindowsMime::mimeForFormat(const FORMATETC &formatetc) const
-
- Returns the mime type that will be created form the format specified
- in \a formatetc, or an empty string if this converter does not support
- \a formatetc.
-
- All subclasses must reimplement this pure virtual function.
-*/
-
-/*!
-\fn QVector<FORMATETC> QWindowsMime::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
-
- Returns a QVector of FORMATETC structures representing the different windows clipboard
- formats that can be provided for the \a mimeType from the \a mimeData.
-
- All subclasses must reimplement this pure virtual function.
-*/
-
-/*!
- \fn QVariant QWindowsMime::convertToMime(const QString &mimeType, IDataObject *pDataObj,
- QVariant::Type preferredType) const
-
- Returns a QVariant containing the converted data for \a mimeType from \a pDataObj.
- If possible the QVariant should be of the \a preferredType to avoid needless conversions.
-
- All subclasses must reimplement this pure virtual function.
-*/
-
-/*!
-\fn bool QWindowsMime::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
-
- Convert the \a mimeData to the format specified in \a formatetc.
- The converted data should then be placed in \a pmedium structure.
-
- Return true if the conversion was successful.
-
- All subclasses must reimplement this pure virtual function.
-*/
-
-class QWindowsMimeText : public QWindowsMime
+class QWindowsMimeText : public QWindowsMimeConverter
{
public:
bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const override;
- QVariant convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const override;
+ QVariant convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QMetaType preferredType) const override;
QString mimeForFormat(const FORMATETC &formatetc) const override;
bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const override;
bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const override;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
+ QList<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
};
bool QWindowsMimeText::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
{
int cf = getCf(formatetc);
- return (cf == CF_UNICODETEXT || cf == CF_TEXT) && mimeData->hasText();
+ return (cf == CF_UNICODETEXT || (cf == CF_TEXT && GetACP() != CP_UTF8)) && mimeData->hasText();
}
/*
@@ -635,11 +401,11 @@ bool QWindowsMimeText::convertFromMime(const FORMATETC &formatetc, const QMimeDa
int ri = 0;
bool cr = false;
for (int i=0; i < s; ++i) {
- if (*u == QLatin1Char('\r'))
+ if (*u == u'\r')
cr = true;
else {
- if (*u == QLatin1Char('\n') && !cr)
- res[ri++] = QLatin1Char('\r');
+ if (*u == u'\n' && !cr)
+ res[ri++] = u'\r';
cr = false;
}
res[ri++] = *u;
@@ -663,7 +429,7 @@ bool QWindowsMimeText::convertFromMime(const FORMATETC &formatetc, const QMimeDa
bool QWindowsMimeText::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
{
- return mimeType.startsWith(QLatin1String("text/plain"))
+ return mimeType.startsWith(u"text/plain")
&& (canGetData(CF_UNICODETEXT, pDataObj)
|| canGetData(CF_TEXT, pDataObj));
}
@@ -672,22 +438,23 @@ QString QWindowsMimeText::mimeForFormat(const FORMATETC &formatetc) const
{
int cf = getCf(formatetc);
if (cf == CF_UNICODETEXT || cf == CF_TEXT)
- return QStringLiteral("text/plain");
+ return u"text/plain"_s;
return QString();
}
-QVector<FORMATETC> QWindowsMimeText::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
+QList<FORMATETC> QWindowsMimeText::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
{
- QVector<FORMATETC> formatics;
- if (mimeType.startsWith(QLatin1String("text/plain")) && mimeData->hasText()) {
+ QList<FORMATETC> formatics;
+ if (mimeType.startsWith(u"text/plain") && mimeData->hasText()) {
formatics += setCf(CF_UNICODETEXT);
- formatics += setCf(CF_TEXT);
+ if (GetACP() != CP_UTF8)
+ formatics += setCf(CF_TEXT);
}
return formatics;
}
-QVariant QWindowsMimeText::convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const
+QVariant QWindowsMimeText::convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QMetaType preferredType) const
{
QVariant ret;
@@ -696,12 +463,12 @@ QVariant QWindowsMimeText::convertToMime(const QString &mime, LPDATAOBJECT pData
QByteArray data = getData(CF_UNICODETEXT, pDataObj);
if (!data.isEmpty()) {
str = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()));
- str.replace(QLatin1String("\r\n"), QLatin1String("\n"));
+ str.replace("\r\n"_L1, "\n"_L1);
} else {
data = getData(CF_TEXT, pDataObj);
if (!data.isEmpty()) {
const char* d = data.data();
- const unsigned s = qstrlen(d);
+ const unsigned s = unsigned(qstrlen(d));
QByteArray r(data.size()+1, '\0');
char* o = r.data();
int j=0;
@@ -714,7 +481,7 @@ QVariant QWindowsMimeText::convertToMime(const QString &mime, LPDATAOBJECT pData
str = QString::fromLocal8Bit(r);
}
}
- if (preferredType == QVariant::String)
+ if (preferredType.id() == QMetaType::QString)
ret = str;
else
ret = std::move(str).toUtf8();
@@ -723,16 +490,16 @@ QVariant QWindowsMimeText::convertToMime(const QString &mime, LPDATAOBJECT pData
return ret;
}
-class QWindowsMimeURI : public QWindowsMime
+class QWindowsMimeURI : public QWindowsMimeConverter
{
public:
QWindowsMimeURI();
bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const override;
- QVariant convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const override;
+ QVariant convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QMetaType preferredType) const override;
QString mimeForFormat(const FORMATETC &formatetc) const override;
bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const override;
bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const override;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
+ QList<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
private:
int CF_INETURL_W; // wide char version
int CF_INETURL;
@@ -740,8 +507,8 @@ private:
QWindowsMimeURI::QWindowsMimeURI()
{
- CF_INETURL_W = QWindowsMime::registerMimeType(QStringLiteral("UniformResourceLocatorW"));
- CF_INETURL = QWindowsMime::registerMimeType(QStringLiteral("UniformResourceLocator"));
+ CF_INETURL_W = registerMimeType(u"UniformResourceLocatorW"_s);
+ CF_INETURL = registerMimeType(u"UniformResourceLocator"_s);
}
bool QWindowsMimeURI::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
@@ -762,7 +529,7 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat
if (getCf(formatetc) == CF_HDROP) {
const auto &urls = mimeData->urls();
QStringList fileNames;
- int size = sizeof(DROPFILES)+2;
+ size_t size = sizeof(DROPFILES) + 2;
for (const QUrl &url : urls) {
const QString fn = QDir::toNativeSeparators(url.toLocalFile());
if (!fn.isEmpty()) {
@@ -771,7 +538,7 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat
}
}
- QByteArray result(size, '\0');
+ QByteArray result(int(size), '\0');
auto* d = reinterpret_cast<DROPFILES *>(result.data());
d->pFiles = sizeof(DROPFILES);
GetCursorPos(&d->pt); // try
@@ -782,7 +549,7 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat
auto *f = reinterpret_cast<wchar_t *>(files);
for (int i=0; i<fileNames.size(); i++) {
const auto l = size_t(fileNames.at(i).length());
- memcpy(f, fileNames.at(i).utf16(), l * sizeof(ushort));
+ memcpy(f, fileNames.at(i).data(), l * sizeof(ushort));
f += l;
*f++ = 0;
}
@@ -794,8 +561,8 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat
const auto urls = mimeData->urls();
QByteArray result;
if (!urls.isEmpty()) {
- QString url = urls.at(0).toString();
- result = QByteArray(reinterpret_cast<const char *>(url.utf16()),
+ const QString url = urls.at(0).toString();
+ result = QByteArray(reinterpret_cast<const char *>(url.data()),
url.length() * int(sizeof(ushort)));
}
result.append('\0');
@@ -816,7 +583,7 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat
bool QWindowsMimeURI::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
{
- return mimeType == QLatin1String("text/uri-list")
+ return mimeType == u"text/uri-list"
&& (canGetData(CF_HDROP, pDataObj) || canGetData(CF_INETURL_W, pDataObj) || canGetData(CF_INETURL, pDataObj));
}
@@ -824,14 +591,14 @@ QString QWindowsMimeURI::mimeForFormat(const FORMATETC &formatetc) const
{
QString format;
if (getCf(formatetc) == CF_HDROP || getCf(formatetc) == CF_INETURL_W || getCf(formatetc) == CF_INETURL)
- format = QStringLiteral("text/uri-list");
+ format = u"text/uri-list"_s;
return format;
}
-QVector<FORMATETC> QWindowsMimeURI::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
+QList<FORMATETC> QWindowsMimeURI::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
{
- QVector<FORMATETC> formatics;
- if (mimeType == QLatin1String("text/uri-list")) {
+ QList<FORMATETC> formatics;
+ if (mimeType == u"text/uri-list") {
if (canConvertFromMime(setCf(CF_HDROP), mimeData))
formatics += setCf(CF_HDROP);
if (canConvertFromMime(setCf(CF_INETURL_W), mimeData))
@@ -842,9 +609,9 @@ QVector<FORMATETC> QWindowsMimeURI::formatsForMime(const QString &mimeType, cons
return formatics;
}
-QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const
+QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pDataObj, QMetaType preferredType) const
{
- if (mimeType == QLatin1String("text/uri-list")) {
+ if (mimeType == u"text/uri-list") {
if (canGetData(CF_HDROP, pDataObj)) {
QList<QVariant> urls;
@@ -870,7 +637,7 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD
}
}
- if (preferredType == QVariant::Url && urls.size() == 1)
+ if (preferredType.id() == QMetaType::QUrl && urls.size() == 1)
return urls.at(0);
if (!urls.isEmpty())
return urls;
@@ -889,7 +656,7 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD
return QVariant();
}
-class QWindowsMimeHtml : public QWindowsMime
+class QWindowsMimeHtml : public QWindowsMimeConverter
{
public:
QWindowsMimeHtml();
@@ -897,11 +664,11 @@ public:
// for converting from Qt
bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const override;
bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const override;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
+ QList<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
// for converting to Qt
bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const override;
- QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const override;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QMetaType preferredType) const override;
QString mimeForFormat(const FORMATETC &formatetc) const override;
private:
@@ -910,13 +677,13 @@ private:
QWindowsMimeHtml::QWindowsMimeHtml()
{
- CF_HTML = QWindowsMime::registerMimeType(QStringLiteral("HTML Format"));
+ CF_HTML = registerMimeType(u"HTML Format"_s);
}
-QVector<FORMATETC> QWindowsMimeHtml::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
+QList<FORMATETC> QWindowsMimeHtml::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
{
- QVector<FORMATETC> formatetcs;
- if (mimeType == QLatin1String("text/html") && (!mimeData->html().isEmpty()))
+ QList<FORMATETC> formatetcs;
+ if (mimeType == u"text/html" && (!mimeData->html().isEmpty()))
formatetcs += setCf(CF_HTML);
return formatetcs;
}
@@ -924,13 +691,13 @@ QVector<FORMATETC> QWindowsMimeHtml::formatsForMime(const QString &mimeType, con
QString QWindowsMimeHtml::mimeForFormat(const FORMATETC &formatetc) const
{
if (getCf(formatetc) == CF_HTML)
- return QStringLiteral("text/html");
+ return u"text/html"_s;
return QString();
}
bool QWindowsMimeHtml::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
{
- return mimeType == QLatin1String("text/html") && canGetData(CF_HTML, pDataObj);
+ return mimeType == u"text/html" && canGetData(CF_HTML, pDataObj);
}
@@ -951,14 +718,14 @@ in bytes). Charset used is mostly utf8, but can be different, ie. we have to loo
...html...
*/
-QVariant QWindowsMimeHtml::convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const
+QVariant QWindowsMimeHtml::convertToMime(const QString &mime, IDataObject *pDataObj, QMetaType preferredType) const
{
Q_UNUSED(preferredType);
QVariant result;
if (canConvertToMime(mime, pDataObj)) {
QByteArray html = getData(CF_HTML, pDataObj);
- static Q_RELAXED_CONSTEXPR auto startMatcher = qMakeStaticByteArrayMatcher("StartHTML:");
- static Q_RELAXED_CONSTEXPR auto endMatcher = qMakeStaticByteArrayMatcher("EndHTML:");
+ static constexpr auto startMatcher = qMakeStaticByteArrayMatcher("StartHTML:");
+ static constexpr auto endMatcher = qMakeStaticByteArrayMatcher("EndHTML:");
qCDebug(lcQpaMime) << __FUNCTION__ << "raw:" << html;
int start = startMatcher.indexIn(html);
int end = endMatcher.indexIn(html);
@@ -1001,8 +768,8 @@ bool QWindowsMimeHtml::convertFromMime(const FORMATETC &formatetc, const QMimeDa
"StartFragment:0000000000\r\n" // 56-81
"EndFragment:0000000000\r\n\r\n"; // 82-107
- static Q_RELAXED_CONSTEXPR auto startFragmentMatcher = qMakeStaticByteArrayMatcher("<!--StartFragment-->");
- static Q_RELAXED_CONSTEXPR auto endFragmentMatcher = qMakeStaticByteArrayMatcher("<!--EndFragment-->");
+ static constexpr auto startFragmentMatcher = qMakeStaticByteArrayMatcher("<!--StartFragment-->");
+ static constexpr auto endFragmentMatcher = qMakeStaticByteArrayMatcher("<!--EndFragment-->");
if (startFragmentMatcher.indexIn(data) == -1)
result += "<!--StartFragment-->";
@@ -1027,18 +794,18 @@ bool QWindowsMimeHtml::convertFromMime(const FORMATETC &formatetc, const QMimeDa
#ifndef QT_NO_IMAGEFORMAT_BMP
-class QWindowsMimeImage : public QWindowsMime
+class QWindowsMimeImage : public QWindowsMimeConverter
{
public:
QWindowsMimeImage();
// for converting from Qt
bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const override;
bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const override;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
+ QList<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
// for converting to Qt
bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const override;
- QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const override;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QMetaType preferredType) const override;
QString mimeForFormat(const FORMATETC &formatetc) const override;
private:
bool hasOriginalDIBV5(IDataObject *pDataObj) const;
@@ -1050,10 +817,10 @@ QWindowsMimeImage::QWindowsMimeImage()
CF_PNG = RegisterClipboardFormat(L"PNG");
}
-QVector<FORMATETC> QWindowsMimeImage::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
+QList<FORMATETC> QWindowsMimeImage::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
{
- QVector<FORMATETC> formatetcs;
- if (mimeData->hasImage() && mimeType == QLatin1String("application/x-qt-image")) {
+ QList<FORMATETC> formatetcs;
+ if (mimeData->hasImage() && mimeType == u"application/x-qt-image") {
//add DIBV5 if image has alpha channel. Do not add CF_PNG here as it will confuse MS Office (QTBUG47656).
auto image = qvariant_cast<QImage>(mimeData->imageData());
if (!image.isNull() && image.hasAlphaChannel())
@@ -1069,13 +836,13 @@ QString QWindowsMimeImage::mimeForFormat(const FORMATETC &formatetc) const
{
int cf = getCf(formatetc);
if (cf == CF_DIB || cf == CF_DIBV5 || cf == int(CF_PNG))
- return QStringLiteral("application/x-qt-image");
+ return u"application/x-qt-image"_s;
return QString();
}
bool QWindowsMimeImage::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
{
- return mimeType == QLatin1String("application/x-qt-image")
+ return mimeType == u"application/x-qt-image"
&& (canGetData(CF_DIB, pDataObj) || canGetData(CF_PNG, pDataObj));
}
@@ -1103,7 +870,7 @@ bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeD
QByteArray ba;
if (cf == CF_DIB) {
if (img.format() > QImage::Format_ARGB32)
- img = img.convertToFormat(QImage::Format_RGB32);
+ img = std::move(img).convertToFormat(QImage::Format_RGB32);
const QByteArray ba = writeDib(img);
if (!ba.isEmpty())
return setData(ba, pmedium);
@@ -1116,7 +883,7 @@ bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeD
} else {
QDataStream s(&ba, QIODevice::WriteOnly);
s.setByteOrder(QDataStream::LittleEndian);// Intel byte order ####
- if (qt_write_dibv5(s, img))
+ if (qt_write_dibv5(s, std::move(img)))
return setData(ba, pmedium);
}
}
@@ -1136,7 +903,7 @@ bool QWindowsMimeImage::hasOriginalDIBV5(IDataObject *pDataObj) const
if (fc.cfFormat == CF_DIB)
break;
if (fc.cfFormat == CF_DIBV5) {
- isSynthesized = false;
+ isSynthesized = false;
break;
}
}
@@ -1145,25 +912,28 @@ bool QWindowsMimeImage::hasOriginalDIBV5(IDataObject *pDataObj) const
return !isSynthesized;
}
-QVariant QWindowsMimeImage::convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const
+QVariant QWindowsMimeImage::convertToMime(const QString &mimeType, IDataObject *pDataObj, QMetaType preferredType) const
{
Q_UNUSED(preferredType);
QVariant result;
- if (mimeType != QLatin1String("application/x-qt-image"))
+ if (mimeType != u"application/x-qt-image")
return result;
- //Try to convert from a format which has more data
- //DIBV5, use only if its is not synthesized
- if (canGetData(CF_DIBV5, pDataObj) && hasOriginalDIBV5(pDataObj)) {
+ // Try to convert from DIBV5 as it is the most widespread format that supports transparency,
+ // but avoid synthesizing it, as that typically loses transparency, e.g. from Office
+ const bool canGetDibV5 = canGetData(CF_DIBV5, pDataObj);
+ const bool hasOrigDibV5 = canGetDibV5 ? hasOriginalDIBV5(pDataObj) : false;
+ qCDebug(lcQpaMime) << "canGetDibV5:" << canGetDibV5 << "hasOrigDibV5:" << hasOrigDibV5;
+ if (hasOrigDibV5) {
+ qCDebug(lcQpaMime) << "Decoding DIBV5";
QImage img;
QByteArray data = getData(CF_DIBV5, pDataObj);
- QDataStream s(&data, QIODevice::ReadOnly);
- s.setByteOrder(QDataStream::LittleEndian);
- if (qt_read_dibv5(s, img)) { // #### supports only 32bit DIBV5
+ QBuffer buffer(&data);
+ if (readDib(buffer, img))
return img;
- }
}
//PNG, MS Office place this (undocumented)
if (canGetData(CF_PNG, pDataObj)) {
+ qCDebug(lcQpaMime) << "Decoding PNG";
QImage img;
QByteArray data = getData(CF_PNG, pDataObj);
if (img.loadFromData(data, "PNG")) {
@@ -1172,8 +942,11 @@ QVariant QWindowsMimeImage::convertToMime(const QString &mimeType, IDataObject *
}
//Fallback to DIB
if (canGetData(CF_DIB, pDataObj)) {
- const QImage img = readDib(getData(CF_DIB, pDataObj));
- if (!img.isNull())
+ qCDebug(lcQpaMime) << "Decoding DIB";
+ QImage img;
+ QByteArray data = getData(CF_DIBV5, pDataObj);
+ QBuffer buffer(&data);
+ if (readDib(buffer, img))
return img;
}
// Failed
@@ -1181,7 +954,7 @@ QVariant QWindowsMimeImage::convertToMime(const QString &mimeType, IDataObject *
}
#endif
-class QBuiltInMimes : public QWindowsMime
+class QBuiltInMimes : public QWindowsMimeConverter
{
public:
QBuiltInMimes();
@@ -1189,11 +962,11 @@ public:
// for converting from Qt
bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const override;
bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const override;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
+ QList<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
// for converting to Qt
bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const override;
- QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const override;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QMetaType preferredType) const override;
QString mimeForFormat(const FORMATETC &formatetc) const override;
private:
@@ -1202,10 +975,10 @@ private:
};
QBuiltInMimes::QBuiltInMimes()
-: QWindowsMime()
+: QWindowsMimeConverter()
{
- outFormats.insert(QWindowsMime::registerMimeType(QStringLiteral("application/x-color")), QStringLiteral("application/x-color"));
- inFormats.insert(QWindowsMime::registerMimeType(QStringLiteral("application/x-color")), QStringLiteral("application/x-color"));
+ outFormats.insert(registerMimeType(u"application/x-color"_s), u"application/x-color"_s);
+ inFormats.insert(registerMimeType(u"application/x-color"_s), u"application/x-color"_s);
}
bool QBuiltInMimes::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
@@ -1220,7 +993,7 @@ bool QBuiltInMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData
{
if (canConvertFromMime(formatetc, mimeData)) {
QByteArray data;
- if (outFormats.value(getCf(formatetc)) == QLatin1String("text/html")) {
+ if (outFormats.value(getCf(formatetc)) == u"text/html") {
// text/html is in wide chars on windows (compatible with mozillia)
QString html = mimeData->html();
// same code as in the text converter up above
@@ -1232,11 +1005,11 @@ bool QBuiltInMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData
int ri = 0;
bool cr = false;
for (int i=0; i < s; ++i) {
- if (*u == QLatin1Char('\r'))
+ if (*u == u'\r')
cr = true;
else {
- if (*u == QLatin1Char('\n') && !cr)
- res[ri++] = QLatin1Char('\r');
+ if (*u == u'\n' && !cr)
+ res[ri++] = u'\r';
cr = false;
}
res[ri++] = *u;
@@ -1263,9 +1036,9 @@ bool QBuiltInMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData
return false;
}
-QVector<FORMATETC> QBuiltInMimes::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
+QList<FORMATETC> QBuiltInMimes::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
{
- QVector<FORMATETC> formatetcs;
+ QList<FORMATETC> formatetcs;
const auto mit = std::find(outFormats.cbegin(), outFormats.cend(), mimeType);
if (mit != outFormats.cend() && mimeData->formats().contains(mimeType))
formatetcs += setCf(mit.key());
@@ -1278,14 +1051,14 @@ bool QBuiltInMimes::canConvertToMime(const QString &mimeType, IDataObject *pData
return mit != inFormats.cend() && canGetData(mit.key(), pDataObj);
}
-QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const
+QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDataObj, QMetaType preferredType) const
{
QVariant val;
if (canConvertToMime(mimeType, pDataObj)) {
QByteArray data = getData(inFormats.key(mimeType), pDataObj);
if (!data.isEmpty()) {
qCDebug(lcQpaMime) << __FUNCTION__;
- if (mimeType == QLatin1String("text/html") && preferredType == QVariant::String) {
+ if (mimeType == u"text/html" && preferredType == QMetaType(QMetaType::QString)) {
// text/html is in wide chars on windows (compatible with Mozilla)
val = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()));
} else {
@@ -1302,7 +1075,7 @@ QString QBuiltInMimes::mimeForFormat(const FORMATETC &formatetc) const
}
-class QLastResortMimes : public QWindowsMime
+class QLastResortMimes : public QWindowsMimeConverter
{
public:
@@ -1310,11 +1083,11 @@ public:
// for converting from Qt
bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const override;
bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const override;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
+ QList<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
// for converting to Qt
bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const override;
- QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const override;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QMetaType preferredType) const override;
QString mimeForFormat(const FORMATETC &formatetc) const override;
private:
@@ -1330,25 +1103,25 @@ QLastResortMimes::QLastResortMimes()
{
//MIME Media-Types
if (ianaTypes.isEmpty()) {
- ianaTypes.append(QStringLiteral("application/"));
- ianaTypes.append(QStringLiteral("audio/"));
- ianaTypes.append(QStringLiteral("example/"));
- ianaTypes.append(QStringLiteral("image/"));
- ianaTypes.append(QStringLiteral("message/"));
- ianaTypes.append(QStringLiteral("model/"));
- ianaTypes.append(QStringLiteral("multipart/"));
- ianaTypes.append(QStringLiteral("text/"));
- ianaTypes.append(QStringLiteral("video/"));
+ ianaTypes.append(u"application/"_s);
+ ianaTypes.append(u"audio/"_s);
+ ianaTypes.append(u"example/"_s);
+ ianaTypes.append(u"image/"_s);
+ ianaTypes.append(u"message/"_s);
+ ianaTypes.append(u"model/"_s);
+ ianaTypes.append(u"multipart/"_s);
+ ianaTypes.append(u"text/"_s);
+ ianaTypes.append(u"video/"_s);
}
//Types handled by other classes
if (excludeList.isEmpty()) {
- excludeList.append(QStringLiteral("HTML Format"));
- excludeList.append(QStringLiteral("UniformResourceLocator"));
- excludeList.append(QStringLiteral("text/html"));
- excludeList.append(QStringLiteral("text/plain"));
- excludeList.append(QStringLiteral("text/uri-list"));
- excludeList.append(QStringLiteral("application/x-qt-image"));
- excludeList.append(QStringLiteral("application/x-color"));
+ excludeList.append(u"HTML Format"_s);
+ excludeList.append(u"UniformResourceLocator"_s);
+ excludeList.append(u"text/html"_s);
+ excludeList.append(u"text/plain"_s);
+ excludeList.append(u"text/uri-list"_s);
+ excludeList.append(u"application/x-qt-image"_s);
+ excludeList.append(u"application/x-color"_s);
}
}
@@ -1380,13 +1153,13 @@ bool QLastResortMimes::convertFromMime(const FORMATETC &formatetc, const QMimeDa
#endif // QT_CONFIG(draganddrop)
}
-QVector<FORMATETC> QLastResortMimes::formatsForMime(const QString &mimeType, const QMimeData * /*mimeData*/) const
+QList<FORMATETC> QLastResortMimes::formatsForMime(const QString &mimeType, const QMimeData * /*mimeData*/) const
{
- QVector<FORMATETC> formatetcs;
+ QList<FORMATETC> formatetcs;
auto mit = std::find(formats.begin(), formats.end(), mimeType);
// register any other available formats
if (mit == formats.end() && !excludeList.contains(mimeType, Qt::CaseInsensitive))
- mit = formats.insert(QWindowsMime::registerMimeType(mimeType), mimeType);
+ mit = formats.insert(registerMimeType(mimeType), mimeType);
if (mit != formats.end())
formatetcs += setCf(mit.key());
@@ -1398,21 +1171,21 @@ static const char x_qt_windows_mime[] = "application/x-qt-windows-mime;value=\""
static bool isCustomMimeType(const QString &mimeType)
{
- return mimeType.startsWith(QLatin1String(x_qt_windows_mime), Qt::CaseInsensitive);
+ return mimeType.startsWith(QLatin1StringView(x_qt_windows_mime), Qt::CaseInsensitive);
}
static QString customMimeType(const QString &mimeType, int *lindex = nullptr)
{
int len = sizeof(x_qt_windows_mime) - 1;
- int n = mimeType.lastIndexOf(QLatin1Char('\"')) - len;
+ int n = mimeType.lastIndexOf(u'\"') - len;
QString ret = mimeType.mid(len, n);
- const int beginPos = mimeType.indexOf(QLatin1String(";index="));
+ const int beginPos = mimeType.indexOf(u";index=");
if (beginPos > -1) {
- const int endPos = mimeType.indexOf(QLatin1Char(';'), beginPos + 1);
+ const int endPos = mimeType.indexOf(u';', beginPos + 1);
const int indexStartPos = beginPos + 7;
if (lindex)
- *lindex = mimeType.midRef(indexStartPos, endPos == -1 ? endPos : endPos - indexStartPos).toInt();
+ *lindex = QStringView{mimeType}.mid(indexStartPos, endPos == -1 ? endPos : endPos - indexStartPos).toInt();
} else {
if (lindex)
*lindex = -1;
@@ -1430,11 +1203,11 @@ bool QLastResortMimes::canConvertToMime(const QString &mimeType, IDataObject *pD
}
// if it is not in there then register it and see if we can get it
const auto mit = std::find(formats.cbegin(), formats.cend(), mimeType);
- const int cf = mit != formats.cend() ? mit.key() : QWindowsMime::registerMimeType(mimeType);
+ const int cf = mit != formats.cend() ? mit.key() : registerMimeType(mimeType);
return canGetData(cf, pDataObj);
}
-QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const
+QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *pDataObj, QMetaType preferredType) const
{
Q_UNUSED(preferredType);
QVariant val;
@@ -1447,7 +1220,7 @@ QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *p
data = getData(int(cf), pDataObj, lindex);
} else {
const auto mit = std::find(formats.cbegin(), formats.cend(), mimeType);
- const int cf = mit != formats.cend() ? mit.key() : QWindowsMime::registerMimeType(mimeType);
+ const int cf = mit != formats.cend() ? mit.key() : registerMimeType(mimeType);
data = getData(cf, pDataObj);
}
if (!data.isEmpty())
@@ -1462,12 +1235,12 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const
if (!format.isEmpty())
return format;
- const QString clipFormat = QWindowsMimeConverter::clipboardFormatName(getCf(formatetc));
+ const QString clipFormat = QWindowsMimeRegistry::clipboardFormatName(getCf(formatetc));
if (!clipFormat.isEmpty()) {
#if QT_CONFIG(draganddrop)
if (QInternalMimeData::canReadData(clipFormat))
format = clipFormat;
- else if((formatetc.cfFormat >= 0xC000)){
+ else if ((formatetc.cfFormat >= 0xC000)){
//create the mime as custom. not registered.
if (!excludeList.contains(clipFormat, Qt::CaseInsensitive)) {
//check if this is a mime type
@@ -1480,7 +1253,7 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const
}
}
if (!ianaType)
- format = QLatin1String(x_qt_windows_mime) + clipFormat + QLatin1Char('\"');
+ format = QLatin1StringView(x_qt_windows_mime) + clipFormat + u'"';
else
format = clipFormat;
}
@@ -1492,21 +1265,20 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const
}
/*!
- \class QWindowsMimeConverter
- \brief Manages the list of QWindowsMime instances.
+ \class QWindowsMimeRegistry
+ \brief Manages the list of QWindowsMimeConverter instances.
\internal
- \ingroup qt-lighthouse-win
- \sa QWindowsMime
+ \sa QWindowsMimeConverter
*/
-QWindowsMimeConverter::QWindowsMimeConverter() = default;
+QWindowsMimeRegistry::QWindowsMimeRegistry() = default;
-QWindowsMimeConverter::~QWindowsMimeConverter()
+QWindowsMimeRegistry::~QWindowsMimeRegistry()
{
qDeleteAll(m_mimes.begin(), m_mimes.begin() + m_internalMimeCount);
}
-QWindowsMime * QWindowsMimeConverter::converterToMime(const QString &mimeType, IDataObject *pDataObj) const
+QWindowsMimeRegistry::QWindowsMimeConverter *QWindowsMimeRegistry::converterToMime(const QString &mimeType, IDataObject *pDataObj) const
{
ensureInitialized();
for (int i = m_mimes.size()-1; i >= 0; --i) {
@@ -1516,9 +1288,9 @@ QWindowsMime * QWindowsMimeConverter::converterToMime(const QString &mimeType, I
return nullptr;
}
-QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) const
+QStringList QWindowsMimeRegistry::allMimesForFormats(IDataObject *pDataObj) const
{
- qCDebug(lcQpaMime) << "QWindowsMime::allMimesForFormats()";
+ qCDebug(lcQpaMime) << "QWindowsMimeConverter::allMimesForFormats()";
ensureInitialized();
QStringList formats;
LPENUMFORMATETC FAR fmtenum;
@@ -1545,7 +1317,7 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con
return formats;
}
-QWindowsMime * QWindowsMimeConverter::converterFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
+QWindowsMimeRegistry::QWindowsMimeConverter *QWindowsMimeRegistry::converterFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
{
ensureInitialized();
qCDebug(lcQpaMime) << __FUNCTION__ << formatetc;
@@ -1556,10 +1328,10 @@ QWindowsMime * QWindowsMimeConverter::converterFromMime(const FORMATETC &formate
return nullptr;
}
-QVector<FORMATETC> QWindowsMimeConverter::allFormatsForMime(const QMimeData *mimeData) const
+QList<FORMATETC> QWindowsMimeRegistry::allFormatsForMime(const QMimeData *mimeData) const
{
ensureInitialized();
- QVector<FORMATETC> formatics;
+ QList<FORMATETC> formatics;
#if !QT_CONFIG(draganddrop)
Q_UNUSED(mimeData);
#else
@@ -1573,34 +1345,37 @@ QVector<FORMATETC> QWindowsMimeConverter::allFormatsForMime(const QMimeData *mim
return formatics;
}
-void QWindowsMimeConverter::ensureInitialized() const
+void QWindowsMimeRegistry::ensureInitialized() const
{
- if (m_mimes.isEmpty()) {
- m_mimes
+ if (m_internalMimeCount == 0) {
+ m_internalMimeCount = -1; // prevent reentrancy when types register themselves
#ifndef QT_NO_IMAGEFORMAT_BMP
- << new QWindowsMimeImage
+ (void)new QWindowsMimeImage;
#endif //QT_NO_IMAGEFORMAT_BMP
- << new QLastResortMimes
- << new QWindowsMimeText << new QWindowsMimeURI
- << new QWindowsMimeHtml << new QBuiltInMimes;
+ (void)new QLastResortMimes;
+ (void)new QWindowsMimeText;
+ (void)new QWindowsMimeURI;
+ (void)new QWindowsMimeHtml;
+ (void)new QBuiltInMimes;
m_internalMimeCount = m_mimes.size();
+ Q_ASSERT(m_internalMimeCount > 0);
}
}
-QString QWindowsMimeConverter::clipboardFormatName(int cf)
+QString QWindowsMimeRegistry::clipboardFormatName(int cf)
{
wchar_t buf[256] = {0};
return GetClipboardFormatName(UINT(cf), buf, 255)
? QString::fromWCharArray(buf) : QString();
}
-QVariant QWindowsMimeConverter::convertToMime(const QStringList &mimeTypes,
+QVariant QWindowsMimeRegistry::convertToMime(const QStringList &mimeTypes,
IDataObject *pDataObj,
- QVariant::Type preferredType,
+ QMetaType preferredType,
QString *formatIn /* = 0 */) const
{
for (const QString &format : mimeTypes) {
- if (const QWindowsMime *converter = converterToMime(format, pDataObj)) {
+ if (const QWindowsMimeConverter *converter = converterToMime(format, pDataObj)) {
if (converter->canConvertToMime(format, pDataObj)) {
const QVariant dataV = converter->convertToMime(format, pDataObj, preferredType);
if (dataV.isValid()) {
@@ -1613,14 +1388,33 @@ QVariant QWindowsMimeConverter::convertToMime(const QStringList &mimeTypes,
}
}
}
- qCDebug(lcQpaMime) << __FUNCTION__ << "fails" << mimeTypes << pDataObj << preferredType;
+ qCDebug(lcQpaMime) << __FUNCTION__ << "fails" << mimeTypes << pDataObj << preferredType.id();
return QVariant();
}
-void QWindowsMimeConverter::registerMime(QWindowsMime *mime)
+void QWindowsMimeRegistry::registerMime(QWindowsMimeConverter *mime)
{
ensureInitialized();
m_mimes.append(mime);
}
+/*!
+ Registers the MIME type \a mime, and returns an ID number
+ identifying the format on Windows.
+
+ A mime type \c {application/x-qt-windows-mime;value="WindowsType"} will be
+ registered as the clipboard format for \c WindowsType.
+*/
+int QWindowsMimeRegistry::registerMimeType(const QString &mime)
+{
+ const QString mimeType = isCustomMimeType(mime) ? customMimeType(mime) : mime;
+ const UINT f = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (mimeType.utf16()));
+ if (!f) {
+ qErrnoWarning("QWindowsMimeRegistry::registerMimeType: Failed to register clipboard format "
+ "for %s", qPrintable(mime));
+ }
+
+ return int(f);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsmimeregistry.h b/src/plugins/platforms/windows/qwindowsmimeregistry.h
new file mode 100644
index 0000000000..a0f4b4c60a
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsmimeregistry.h
@@ -0,0 +1,58 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWINDOWSMIMEREGISTRY_H
+#define QWINDOWSMIMEREGISTRY_H
+
+
+#include <QtCore/qt_windows.h>
+
+#include <QtGui/qwindowsmimeconverter.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDebug;
+class QMimeData;
+
+class QWindowsMimeRegistry
+{
+ Q_DISABLE_COPY_MOVE(QWindowsMimeRegistry)
+public:
+ using QWindowsMimeConverter = QWindowsMimeConverter;
+
+ QWindowsMimeRegistry();
+ ~QWindowsMimeRegistry();
+
+ QWindowsMimeConverter *converterToMime(const QString &mimeType, IDataObject *pDataObj) const;
+ QStringList allMimesForFormats(IDataObject *pDataObj) const;
+ QWindowsMimeConverter *converterFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
+ QList<FORMATETC> allFormatsForMime(const QMimeData *mimeData) const;
+
+ // Convenience.
+ QVariant convertToMime(const QStringList &mimeTypes, IDataObject *pDataObj, QMetaType preferredType,
+ QString *format = nullptr) const;
+
+ void registerMime(QWindowsMimeConverter *mime);
+ void unregisterMime(QWindowsMimeConverter *mime) { m_mimes.removeOne(mime); }
+
+ static int registerMimeType(const QString &mime);
+
+ static QString clipboardFormatName(int cf);
+
+private:
+ void ensureInitialized() const;
+
+ mutable QList<QWindowsMimeConverter *> m_mimes;
+ mutable int m_internalMimeCount = 0;
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug, const FORMATETC &);
+QDebug operator<<(QDebug d, IDataObject *);
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSMIMEREGISTRY_H
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index b776efc942..9af9fba408 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsmousehandler.h"
#include "qwindowskeymapper.h"
@@ -47,12 +11,13 @@
#include <qpa/qwindowsysteminterface.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qscreen.h>
-#include <QtGui/qtouchdevice.h>
+#include <QtGui/qpointingdevice.h>
#include <QtGui/qwindow.h>
#include <QtGui/qcursor.h>
#include <QtCore/qdebug.h>
-#include <QtCore/qscopedpointer.h>
+
+#include <memory>
#include <windowsx.h>
@@ -117,27 +82,6 @@ static inline void compressMouseMove(MSG *msg)
}
}
-static inline QTouchDevice *createTouchDevice()
-{
- const int digitizers = GetSystemMetrics(SM_DIGITIZER);
- if (!(digitizers & (NID_INTEGRATED_TOUCH | NID_EXTERNAL_TOUCH)))
- return nullptr;
- const int tabletPc = GetSystemMetrics(SM_TABLETPC);
- const int maxTouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES);
- qCDebug(lcQpaEvents) << "Digitizers:" << Qt::hex << Qt::showbase << (digitizers & ~NID_READY)
- << "Ready:" << (digitizers & NID_READY) << Qt::dec << Qt::noshowbase
- << "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints;
- auto *result = new QTouchDevice;
- result->setType(digitizers & NID_INTEGRATED_TOUCH
- ? QTouchDevice::TouchScreen : QTouchDevice::TouchPad);
- QTouchDevice::Capabilities capabilities = QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition;
- if (result->type() == QTouchDevice::TouchPad)
- capabilities |= QTouchDevice::MouseEmulation;
- result->setCapabilities(capabilities);
- result->setMaximumTouchPoints(maxTouchPoints);
- return result;
-}
-
/*!
\class QWindowsMouseHandler
\brief Windows mouse handler
@@ -145,16 +89,16 @@ static inline QTouchDevice *createTouchDevice()
Dispatches mouse and touch events. Separate for code cleanliness.
\internal
- \ingroup qt-lighthouse-win
*/
QWindowsMouseHandler::QWindowsMouseHandler() = default;
-QTouchDevice *QWindowsMouseHandler::ensureTouchDevice()
+const QPointingDevice *QWindowsMouseHandler::primaryMouse()
{
- if (!m_touchDevice)
- m_touchDevice = createTouchDevice();
- return m_touchDevice;
+ static QPointer<const QPointingDevice> result;
+ if (!result)
+ result = QPointingDevice::primaryPointingDevice();
+ return result;
}
void QWindowsMouseHandler::clearEvents()
@@ -172,7 +116,7 @@ Qt::MouseButtons QWindowsMouseHandler::queryMouseButtons()
if (GetAsyncKeyState(VK_RBUTTON) < 0)
result |= mouseSwapped ? Qt::LeftButton : Qt::RightButton;
if (GetAsyncKeyState(VK_MBUTTON) < 0)
- result |= Qt::MidButton;
+ result |= Qt::MiddleButton;
if (GetAsyncKeyState(VK_XBUTTON1) < 0)
result |= Qt::XButton1;
if (GetAsyncKeyState(VK_XBUTTON2) < 0)
@@ -180,7 +124,7 @@ Qt::MouseButtons QWindowsMouseHandler::queryMouseButtons()
return result;
}
-static QPoint lastMouseMovePos;
+Q_CONSTINIT static QPoint lastMouseMovePos;
namespace {
struct MouseEvent {
@@ -216,11 +160,11 @@ static inline MouseEvent eventFromMsg(const MSG &msg)
case WM_LBUTTONDBLCLK: // Qt QPA does not handle double clicks, send as press
return {QEvent::MouseButtonPress, Qt::LeftButton};
case WM_MBUTTONDOWN:
- return {QEvent::MouseButtonPress, Qt::MidButton};
+ return {QEvent::MouseButtonPress, Qt::MiddleButton};
case WM_MBUTTONUP:
- return {QEvent::MouseButtonRelease, Qt::MidButton};
+ return {QEvent::MouseButtonRelease, Qt::MiddleButton};
case WM_MBUTTONDBLCLK:
- return {QEvent::MouseButtonPress, Qt::MidButton};
+ return {QEvent::MouseButtonPress, Qt::MiddleButton};
case WM_RBUTTONDOWN:
return {QEvent::MouseButtonPress, Qt::RightButton};
case WM_RBUTTONUP:
@@ -242,11 +186,11 @@ static inline MouseEvent eventFromMsg(const MSG &msg)
case WM_NCLBUTTONDBLCLK:
return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton};
case WM_NCMBUTTONDOWN:
- return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton};
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::MiddleButton};
case WM_NCMBUTTONUP:
- return {QEvent::NonClientAreaMouseButtonRelease, Qt::MidButton};
+ return {QEvent::NonClientAreaMouseButtonRelease, Qt::MiddleButton};
case WM_NCMBUTTONDBLCLK:
- return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton};
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::MiddleButton};
case WM_NCRBUTTONDOWN:
return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton};
case WM_NCRBUTTONUP:
@@ -281,8 +225,13 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
globalPosition = winEventPosition;
clientPosition = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPosition);
} else {
- clientPosition = winEventPosition;
globalPosition = QWindowsGeometryHint::mapToGlobal(hwnd, winEventPosition);
+ auto targetHwnd = hwnd;
+ if (auto *pw = window->handle())
+ targetHwnd = HWND(pw->winId());
+ clientPosition = targetHwnd == hwnd
+ ? winEventPosition
+ : QWindowsGeometryHint::mapFromGlobal(targetHwnd, globalPosition);
}
// Windows sends a mouse move with no buttons pressed to signal "Enter"
@@ -299,6 +248,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
+ const QPointingDevice *device = primaryMouse();
+
// Check for events synthesized from touch. Lower byte is touch index, 0 means pen.
static const bool passSynthesizedMouseEvents =
!(QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch);
@@ -310,12 +261,15 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
if ((extraInfo & signatureMask) == miWpSignature) {
if (extraInfo & 0x80) { // Bit 7 indicates touch event, else tablet pen.
source = Qt::MouseEventSynthesizedBySystem;
+ if (!m_touchDevice.isNull())
+ device = m_touchDevice.data();
if (!passSynthesizedMouseEvents)
return false;
}
}
- const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
+ const auto *keyMapper = QWindowsContext::instance()->keyMapper();
+ const Qt::KeyboardModifiers keyModifiers = keyMapper->queryKeyboardModifiers();
const MouseEvent mouseEvent = eventFromMsg(msg);
Qt::MouseButtons buttons;
@@ -333,19 +287,16 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
if (m_lastEventType == QEvent::NonClientAreaMouseButtonPress
&& (mouseEvent.type == QEvent::NonClientAreaMouseMove || mouseEvent.type == QEvent::MouseMove)
&& (m_lastEventButton & buttons) == 0) {
- if (mouseEvent.type == QEvent::NonClientAreaMouseMove) {
- QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition, globalPosition, buttons, m_lastEventButton,
- QEvent::NonClientAreaMouseButtonRelease, keyModifiers, source);
- } else {
- QWindowSystemInterface::handleMouseEvent(window, clientPosition, globalPosition, buttons, m_lastEventButton,
- QEvent::MouseButtonRelease, keyModifiers, source);
- }
+ auto releaseType = mouseEvent.type == QEvent::NonClientAreaMouseMove ?
+ QEvent::NonClientAreaMouseButtonRelease : QEvent::MouseButtonRelease;
+ QWindowSystemInterface::handleMouseEvent(window, msg.time, device, clientPosition, globalPosition, buttons, m_lastEventButton,
+ releaseType, keyModifiers, source);
}
m_lastEventType = mouseEvent.type;
m_lastEventButton = mouseEvent.button;
if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) {
- QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition,
+ QWindowSystemInterface::handleMouseEvent(window, msg.time, device, clientPosition,
globalPosition, buttons,
mouseEvent.button, mouseEvent.type,
keyModifiers, source);
@@ -372,7 +323,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
auto *platformWindow = static_cast<QWindowsWindow *>(window->handle());
- // If the window was recently resized via mouse doubleclick on the frame or title bar,
+ // If the window was recently resized via mouse double-click on the frame or title bar,
// we don't get WM_LBUTTONDOWN or WM_LBUTTONDBLCLK for the second click,
// but we will get at least one WM_MOUSEMOVE with left button down and the WM_LBUTTONUP,
// which will result undesired mouse press and release events.
@@ -495,7 +446,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
}
if (!discardEvent && mouseEvent.type != QEvent::None) {
- QWindowSystemInterface::handleMouseEvent(window, winEventPosition, globalPosition, buttons,
+ QWindowSystemInterface::handleMouseEvent(window, msg.time, device, clientPosition, globalPosition, buttons,
mouseEvent.button, mouseEvent.type,
keyModifiers, source);
}
@@ -519,7 +470,7 @@ static bool isValidWheelReceiver(QWindow *candidate)
return false;
}
-static void redirectWheelEvent(QWindow *window, const QPoint &globalPos, int delta,
+static void redirectWheelEvent(QWindow *window, unsigned long timestamp, const QPoint &globalPos, int delta,
Qt::Orientation orientation, Qt::KeyboardModifiers mods)
{
// Redirect wheel event to one of the following, in order of preference:
@@ -540,6 +491,7 @@ static void redirectWheelEvent(QWindow *window, const QPoint &globalPos, int del
if (handleEvent) {
const QPoint point = (orientation == Qt::Vertical) ? QPoint(0, delta) : QPoint(delta, 0);
QWindowSystemInterface::handleWheelEvent(receiver,
+ timestamp,
QWindowsGeometryHint::mapFromGlobal(receiver, globalPos),
globalPos, QPoint(), point, mods);
}
@@ -568,7 +520,7 @@ bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND,
delta = -delta;
const QPoint globalPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
- redirectWheelEvent(window, globalPos, delta, orientation, mods);
+ redirectWheelEvent(window, msg.time, globalPos, delta, orientation, mods);
return true;
}
@@ -599,7 +551,7 @@ bool QWindowsMouseHandler::translateScrollEvent(QWindow *window, HWND,
return false;
}
- redirectWheelEvent(window, QCursor::pos(), delta, Qt::Horizontal, Qt::NoModifier);
+ redirectWheelEvent(window, msg.time, QCursor::pos(), delta, Qt::Horizontal, Qt::NoModifier);
return true;
}
@@ -625,15 +577,14 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
const QRect screenGeometry = screen->geometry();
const int winTouchPointCount = int(msg.wParam);
- QScopedArrayPointer<TOUCHINPUT> winTouchInputs(new TOUCHINPUT[winTouchPointCount]);
- memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * size_t(winTouchPointCount));
+ const auto winTouchInputs = std::make_unique<TOUCHINPUT[]>(winTouchPointCount);
QTouchPointList touchPoints;
touchPoints.reserve(winTouchPointCount);
- Qt::TouchPointStates allStates;
+ QEventPoint::States allStates;
GetTouchInputInfo(reinterpret_cast<HTOUCHINPUT>(msg.lParam),
- UINT(msg.wParam), winTouchInputs.data(), sizeof(TOUCHINPUT));
+ UINT(msg.wParam), winTouchInputs.get(), sizeof(TOUCHINPUT));
for (int i = 0; i < winTouchPointCount; ++i) {
const TOUCHINPUT &winTouchInput = winTouchInputs[i];
int id = m_touchInputIDToTouchPointID.value(winTouchInput.dwID, -1);
@@ -657,15 +608,15 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
touchPoint.normalPosition = normalPosition;
if (winTouchInput.dwFlags & TOUCHEVENTF_DOWN) {
- touchPoint.state = Qt::TouchPointPressed;
+ touchPoint.state = QEventPoint::State::Pressed;
m_lastTouchPositions.insert(id, touchPoint.normalPosition);
} else if (winTouchInput.dwFlags & TOUCHEVENTF_UP) {
- touchPoint.state = Qt::TouchPointReleased;
+ touchPoint.state = QEventPoint::State::Released;
m_lastTouchPositions.remove(id);
} else {
touchPoint.state = (stationaryTouchPoint
- ? Qt::TouchPointStationary
- : Qt::TouchPointMoved);
+ ? QEventPoint::State::Stationary
+ : QEventPoint::State::Updated);
m_lastTouchPositions.insert(id, touchPoint.normalPosition);
}
@@ -677,13 +628,15 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
CloseTouchInputHandle(reinterpret_cast<HTOUCHINPUT>(msg.lParam));
// all touch points released, forget the ids we've seen, they may not be reused
- if (allStates == Qt::TouchPointReleased)
+ if (allStates == QEventPoint::State::Released)
m_touchInputIDToTouchPointID.clear();
+ const auto *keyMapper = QWindowsContext::instance()->keyMapper();
QWindowSystemInterface::handleTouchEvent(window,
- m_touchDevice,
+ msg.time,
+ m_touchDevice.data(),
touchPoints,
- QWindowsKeyMapper::queryKeyboardModifiers());
+ keyMapper->queryKeyboardModifiers());
return true;
}
@@ -691,9 +644,9 @@ bool QWindowsMouseHandler::translateGestureEvent(QWindow *window, HWND hwnd,
QtWindows::WindowsEventType,
MSG msg, LRESULT *)
{
- Q_UNUSED(window)
- Q_UNUSED(hwnd)
- Q_UNUSED(msg)
+ Q_UNUSED(window);
+ Q_UNUSED(hwnd);
+ Q_UNUSED(msg);
return false;
}
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h
index 1d3d1f4761..7fde349f58 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.h
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSMOUSEHANDLER_H
#define QWINDOWSMOUSEHANDLER_H
@@ -45,21 +9,24 @@
#include <QtCore/qpointer.h>
#include <QtCore/qhash.h>
+#include <QtCore/qsharedpointer.h>
#include <QtGui/qevent.h>
QT_BEGIN_NAMESPACE
class QWindow;
-class QTouchDevice;
+class QPointingDevice;
class QWindowsMouseHandler
{
Q_DISABLE_COPY_MOVE(QWindowsMouseHandler)
public:
+ using QPointingDevicePtr = QSharedPointer<QPointingDevice>;
+
QWindowsMouseHandler();
- QTouchDevice *touchDevice() const { return m_touchDevice; }
- QTouchDevice *ensureTouchDevice();
+ const QPointingDevicePtr &touchDevice() const { return m_touchDevice; }
+ void setTouchDevice(const QPointingDevicePtr &d) { m_touchDevice = d; }
bool translateMouseEvent(QWindow *widget, HWND hwnd,
QtWindows::WindowsEventType t, MSG msg,
@@ -82,6 +49,8 @@ public:
void clearWindowUnderMouse() { m_windowUnderMouse = nullptr; }
void clearEvents();
+ static const QPointingDevice *primaryMouse();
+
private:
inline bool translateMouseWheelEvent(QWindow *window, HWND hwnd,
MSG msg, LRESULT *result);
@@ -90,7 +59,7 @@ private:
QPointer<QWindow> m_trackedWindow;
QHash<DWORD, int> m_touchInputIDToTouchPointID;
QHash<int, QPointF> m_lastTouchPositions;
- QTouchDevice *m_touchDevice = nullptr;
+ QPointingDevicePtr m_touchDevice;
bool m_leftButtonDown = false;
QWindow *m_previousCaptureWindow = nullptr;
QEvent::Type m_lastEventType = QEvent::None;
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index d1d181d66e..e709123097 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -1,67 +1,25 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsnativeinterface.h"
-#include "qwindowsclipboard.h"
#include "qwindowswindow.h"
#include "qwindowsscreen.h"
#include "qwindowscontext.h"
#include "qwindowscursor.h"
#include "qwindowsopenglcontext.h"
-#include "qwindowsopengltester.h"
#include "qwindowsintegration.h"
-#include "qwindowsmime.h"
+#include "qwindowstheme.h"
#include "qwin10helpers.h"
#include <QtGui/qwindow.h>
#include <QtGui/qopenglcontext.h>
#include <QtGui/qscreen.h>
#include <qpa/qplatformscreen.h>
-#include <QtFontDatabaseSupport/private/qwindowsfontdatabase_p.h>
QT_BEGIN_NAMESPACE
enum ResourceType {
RenderingContextType,
- EglContextType,
- EglDisplayType,
- EglConfigType,
HandleType,
GlHandleType,
GetDCType,
@@ -73,9 +31,6 @@ static int resourceType(const QByteArray &key)
{
static const char *names[] = { // match ResourceType
"renderingcontext",
- "eglcontext",
- "egldisplay",
- "eglconfig",
"handle",
"glhandle",
"getdc",
@@ -89,9 +44,6 @@ static int resourceType(const QByteArray &key)
return int(result - names);
}
-QWindowsWindowFunctions::WindowActivationBehavior QWindowsNativeInterface::m_windowActivationBehavior =
- QWindowsWindowFunctions::DefaultActivateWindow;
-
void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
{
if (!window || !window->handle()) {
@@ -153,41 +105,10 @@ void *QWindowsNativeInterface::nativeResourceForCursor(const QByteArray &resourc
}
#endif // !QT_NO_CURSOR
-static const char customMarginPropertyC[] = "WindowsCustomMargins";
-
-QVariant QWindowsNativeInterface::windowProperty(QPlatformWindow *window, const QString &name) const
-{
- auto *platformWindow = static_cast<QWindowsWindow *>(window);
- if (name == QLatin1String(customMarginPropertyC))
- return QVariant::fromValue(platformWindow->customMargins());
- return QVariant();
-}
-
-QVariant QWindowsNativeInterface::windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const
-{
- const QVariant result = windowProperty(window, name);
- return result.isValid() ? result : defaultValue;
-}
-
-void QWindowsNativeInterface::setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value)
-{
- auto *platformWindow = static_cast<QWindowsWindow *>(window);
- if (name == QLatin1String(customMarginPropertyC))
- platformWindow->setCustomMargins(qvariant_cast<QMargins>(value));
-}
-
-QVariantMap QWindowsNativeInterface::windowProperties(QPlatformWindow *window) const
-{
- QVariantMap result;
- const QString customMarginProperty = QLatin1String(customMarginPropertyC);
- result.insert(customMarginProperty, windowProperty(window, customMarginProperty));
- return result;
-}
-
void *QWindowsNativeInterface::nativeResourceForIntegration(const QByteArray &resource)
{
#ifdef QT_NO_OPENGL
- Q_UNUSED(resource)
+ Q_UNUSED(resource);
#else
if (resourceType(resource) == GlHandleType) {
if (const QWindowsStaticOpenGLContext *sc = QWindowsIntegration::staticOpenGLContext())
@@ -206,114 +127,9 @@ void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resour
return nullptr;
}
- auto *glcontext = static_cast<QWindowsOpenGLContext *>(context->handle());
- switch (resourceType(resource)) {
- case RenderingContextType: // Fall through.
- case EglContextType:
- return glcontext->nativeContext();
- case EglDisplayType:
- return glcontext->nativeDisplay();
- case EglConfigType:
- return glcontext->nativeConfig();
- default:
- break;
- }
-
qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
return nullptr;
}
#endif // !QT_NO_OPENGL
-/*!
- \brief Creates a non-visible window handle for filtering messages.
-*/
-
-void *QWindowsNativeInterface::createMessageWindow(const QString &classNameTemplate,
- const QString &windowName,
- void *eventProc) const
-{
- QWindowsContext *ctx = QWindowsContext::instance();
- const HWND hwnd = ctx->createDummyWindow(classNameTemplate,
- (wchar_t*)windowName.utf16(),
- (WNDPROC)eventProc);
- return hwnd;
-}
-
-/*!
- \brief Registers a unique window class with a callback function based on \a classNameIn.
-*/
-
-QString QWindowsNativeInterface::registerWindowClass(const QString &classNameIn, void *eventProc) const
-{
- return QWindowsContext::instance()->registerWindowClass(classNameIn, (WNDPROC)eventProc);
-}
-
-bool QWindowsNativeInterface::asyncExpose() const
-{
- return QWindowsContext::instance()->asyncExpose();
-}
-
-void QWindowsNativeInterface::setAsyncExpose(bool value)
-{
- QWindowsContext::instance()->setAsyncExpose(value);
-}
-
-void QWindowsNativeInterface::registerWindowsMime(void *mimeIn)
-{
- QWindowsContext::instance()->mimeConverter().registerMime(reinterpret_cast<QWindowsMime *>(mimeIn));
-}
-
-void QWindowsNativeInterface::unregisterWindowsMime(void *mimeIn)
-{
- QWindowsContext::instance()->mimeConverter().unregisterMime(reinterpret_cast<QWindowsMime *>(mimeIn));
-}
-
-int QWindowsNativeInterface::registerMimeType(const QString &mimeType)
-{
- return QWindowsMime::registerMimeType(mimeType);
-}
-
-QFont QWindowsNativeInterface::logFontToQFont(const void *logFont, int verticalDpi)
-{
- return QWindowsFontDatabase::LOGFONT_to_QFont(*reinterpret_cast<const LOGFONT *>(logFont), verticalDpi);
-}
-
-bool QWindowsNativeInterface::isTabletMode()
-{
-#if QT_CONFIG(clipboard)
- if (const QWindowsClipboard *clipboard = QWindowsClipboard::instance())
- return qt_windowsIsTabletMode(clipboard->clipboardViewer());
-#endif
- return false;
-}
-
-QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &function) const
-{
- if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier())
- return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic);
- if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier())
- return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic);
- if (function == QWindowsWindowFunctions::setHasBorderInFullScreenDefaultIdentifier())
- return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenDefault);
- if (function == QWindowsWindowFunctions::setWindowActivationBehaviorIdentifier())
- return QFunctionPointer(QWindowsNativeInterface::setWindowActivationBehavior);
- if (function == QWindowsWindowFunctions::isTabletModeIdentifier())
- return QFunctionPointer(QWindowsNativeInterface::isTabletMode);
- return nullptr;
-}
-
-QVariant QWindowsNativeInterface::gpu() const
-{
- return GpuDescription::detect().toVariant();
-}
-
-QVariant QWindowsNativeInterface::gpuList() const
-{
- QVariantList result;
- const auto gpus = GpuDescription::detectAll();
- for (const auto &gpu : gpus)
- result.append(gpu.toVariant());
- return result;
-}
-
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h
index ce395dc5a4..a123c2b242 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.h
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h
@@ -1,48 +1,11 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSNATIVEINTERFACE_H
#define QWINDOWSNATIVEINTERFACE_H
#include <QtGui/qfont.h>
#include <QtGui/qpa/qplatformnativeinterface.h>
-#include <QtPlatformHeaders/qwindowswindowfunctions.h>
QT_BEGIN_NAMESPACE
@@ -58,15 +21,11 @@ QT_BEGIN_NAMESPACE
\endlist
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsNativeInterface : public QPlatformNativeInterface
{
Q_OBJECT
- Q_PROPERTY(bool asyncExpose READ asyncExpose WRITE setAsyncExpose)
- Q_PROPERTY(QVariant gpu READ gpu STORED false)
- Q_PROPERTY(QVariant gpuList READ gpuList STORED false)
public:
void *nativeResourceForIntegration(const QByteArray &resource) override;
@@ -78,39 +37,6 @@ public:
#ifndef QT_NO_CURSOR
void *nativeResourceForCursor(const QByteArray &resource, const QCursor &cursor) override;
#endif
- Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate,
- const QString &windowName,
- void *eventProc) const;
-
- Q_INVOKABLE QString registerWindowClass(const QString &classNameIn, void *eventProc) const;
-
- Q_INVOKABLE void registerWindowsMime(void *mimeIn);
- Q_INVOKABLE void unregisterWindowsMime(void *mime);
- Q_INVOKABLE int registerMimeType(const QString &mimeType);
- Q_INVOKABLE QFont logFontToQFont(const void *logFont, int verticalDpi);
-
- bool asyncExpose() const;
- void setAsyncExpose(bool value);
-
- QVariant gpu() const;
- QVariant gpuList() const;
-
- QVariantMap windowProperties(QPlatformWindow *window) const override;
- QVariant windowProperty(QPlatformWindow *window, const QString &name) const override;
- QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const override;
- void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value) override;
-
- static QWindowsWindowFunctions::WindowActivationBehavior windowActivationBehavior()
- { return QWindowsNativeInterface::m_windowActivationBehavior; }
- static void setWindowActivationBehavior(QWindowsWindowFunctions::WindowActivationBehavior b)
- { QWindowsNativeInterface::m_windowActivationBehavior = b; }
-
- static bool isTabletMode();
-
- QFunctionPointer platformFunction(const QByteArray &function) const override;
-
-private:
- static QWindowsWindowFunctions::WindowActivationBehavior m_windowActivationBehavior;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp
index f3450e2806..c01f716054 100644
--- a/src/plugins/platforms/windows/qwindowsole.cpp
+++ b/src/plugins/platforms/windows/qwindowsole.cpp
@@ -1,44 +1,8 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsole.h"
-#include "qwindowsmime.h"
+#include "qwindowsmimeregistry.h"
#include "qwindowscontext.h"
\
#include <QtGui/qevent.h>
@@ -70,7 +34,6 @@ QT_BEGIN_NAMESPACE
\endlist
\internal
- \ingroup qt-lighthouse-win
*/
QWindowsOleDataObject::QWindowsOleDataObject(QMimeData *mimeData) :
@@ -103,8 +66,8 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
HRESULT hr = ResultFromScode(DATA_E_FORMATETC);
if (data) {
- const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter();
- if (QWindowsMime *converter = mc.converterFromMime(*pformatetc, data))
+ const QWindowsMimeRegistry &mc = QWindowsContext::instance()->mimeConverter();
+ if (auto converter = mc.converterFromMime(*pformatetc, data))
if (converter->convertFromMime(*pformatetc, data, pmedium))
hr = ResultFromScode(S_OK);
}
@@ -130,7 +93,7 @@ QWindowsOleDataObject::QueryGetData(LPFORMATETC pformatetc)
qCDebug(lcQpaMime) << __FUNCTION__;
if (data) {
- const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter();
+ const QWindowsMimeRegistry &mc = QWindowsContext::instance()->mimeConverter();
hr = mc.converterFromMime(*pformatetc, data) ?
ResultFromScode(S_OK) : ResultFromScode(S_FALSE);
}
@@ -179,9 +142,9 @@ QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppe
SCODE sc = S_OK;
- QVector<FORMATETC> fmtetcs;
+ QList<FORMATETC> fmtetcs;
if (dwDirection == DATADIR_GET) {
- QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter();
+ QWindowsMimeRegistry &mc = QWindowsContext::instance()->mimeConverter();
fmtetcs = mc.allFormatsForMime(data);
} else {
FORMATETC formatetc;
@@ -228,10 +191,9 @@ QWindowsOleDataObject::EnumDAdvise(LPENUMSTATDATA FAR*)
\class QWindowsOleEnumFmtEtc
\brief Enumerates the FORMATETC structures supported by QWindowsOleDataObject.
\internal
- \ingroup qt-lighthouse-win
*/
-QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs)
+QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QList<FORMATETC> &fmtetcs)
{
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaMime) << __FUNCTION__ << fmtetcs;
@@ -248,7 +210,7 @@ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs)
}
}
-QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<LPFORMATETC> &lpfmtetcs)
+QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QList<LPFORMATETC> &lpfmtetcs)
{
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaMime) << __FUNCTION__;
diff --git a/src/plugins/platforms/windows/qwindowsole.h b/src/plugins/platforms/windows/qwindowsole.h
index 6940657e88..016f9dd04c 100644
--- a/src/plugins/platforms/windows/qwindowsole.h
+++ b/src/plugins/platforms/windows/qwindowsole.h
@@ -1,51 +1,15 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSOLE_H
#define QWINDOWSOLE_H
-#include "qwindowscombase.h"
#include <QtCore/qt_windows.h>
+#include <QtCore/qlist.h>
#include <QtCore/qmap.h>
#include <QtCore/qpointer.h>
-#include <QtCore/qvector.h>
+#include <QtCore/private/qcomobject_p.h>
#include <objidl.h>
@@ -54,7 +18,7 @@ QT_BEGIN_NAMESPACE
class QMimeData;
class QWindow;
-class QWindowsOleDataObject : public QWindowsComBase<IDataObject>
+class QWindowsOleDataObject : public QComObject<IDataObject>
{
public:
explicit QWindowsOleDataObject(QMimeData *mimeData);
@@ -65,17 +29,17 @@ public:
DWORD reportedPerformedEffect() const;
// IDataObject methods
- STDMETHOD(GetData)(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium);
- STDMETHOD(GetDataHere)(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium);
- STDMETHOD(QueryGetData)(LPFORMATETC pformatetc);
- STDMETHOD(GetCanonicalFormatEtc)(LPFORMATETC pformatetc, LPFORMATETC pformatetcOut);
- STDMETHOD(SetData)(LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium,
- BOOL fRelease);
- STDMETHOD(EnumFormatEtc)(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc);
- STDMETHOD(DAdvise)(FORMATETC FAR* pFormatetc, DWORD advf,
- LPADVISESINK pAdvSink, DWORD FAR* pdwConnection);
- STDMETHOD(DUnadvise)(DWORD dwConnection);
- STDMETHOD(EnumDAdvise)(LPENUMSTATDATA FAR* ppenumAdvise);
+ STDMETHOD(GetData)(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium) override;
+ STDMETHOD(GetDataHere)(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) override;
+ STDMETHOD(QueryGetData)(LPFORMATETC pformatetc) override;
+ STDMETHOD(GetCanonicalFormatEtc)(LPFORMATETC pformatetc, LPFORMATETC pformatetcOut) override;
+ STDMETHOD(SetData)(LPFORMATETC pformatetc, STGMEDIUM FAR *pmedium, BOOL fRelease) override;
+ STDMETHOD(EnumFormatEtc)(DWORD dwDirection, LPENUMFORMATETC FAR *ppenumFormatEtc) override;
+ STDMETHOD(DAdvise)
+ (FORMATETC FAR *pFormatetc, DWORD advf, LPADVISESINK pAdvSink,
+ DWORD FAR *pdwConnection) override;
+ STDMETHOD(DUnadvise)(DWORD dwConnection) override;
+ STDMETHOD(EnumDAdvise)(LPENUMSTATDATA FAR *ppenumAdvise) override;
private:
QPointer<QMimeData> data;
@@ -83,26 +47,26 @@ private:
DWORD performedEffect = DROPEFFECT_NONE;
};
-class QWindowsOleEnumFmtEtc : public QWindowsComBase<IEnumFORMATETC>
+class QWindowsOleEnumFmtEtc : public QComObject<IEnumFORMATETC>
{
public:
- explicit QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs);
- explicit QWindowsOleEnumFmtEtc(const QVector<LPFORMATETC> &lpfmtetcs);
+ explicit QWindowsOleEnumFmtEtc(const QList<FORMATETC> &fmtetcs);
+ explicit QWindowsOleEnumFmtEtc(const QList<LPFORMATETC> &lpfmtetcs);
~QWindowsOleEnumFmtEtc() override;
bool isNull() const;
// IEnumFORMATETC methods
- STDMETHOD(Next)(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched);
- STDMETHOD(Skip)(ULONG celt);
- STDMETHOD(Reset)(void);
- STDMETHOD(Clone)(LPENUMFORMATETC FAR* newEnum);
+ STDMETHOD(Next)(ULONG celt, LPFORMATETC rgelt, ULONG FAR *pceltFetched) override;
+ STDMETHOD(Skip)(ULONG celt) override;
+ STDMETHOD(Reset)(void) override;
+ STDMETHOD(Clone)(LPENUMFORMATETC FAR *newEnum) override;
private:
bool copyFormatEtc(LPFORMATETC dest, const FORMATETC *src) const;
ULONG m_nIndex = 0;
- QVector<LPFORMATETC> m_lpfmtetcs;
+ QList<LPFORMATETC> m_lpfmtetcs;
bool m_isNull = false;
};
diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h
index 1416a7e575..3fefe0ad91 100644
--- a/src/plugins/platforms/windows/qwindowsopenglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsopenglcontext.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSOPENGLCONTEXT_H
#define QWINDOWSOPENGLCONTEXT_H
@@ -57,6 +21,7 @@ public:
virtual ~QWindowsStaticOpenGLContext() = default;
virtual QWindowsOpenGLContext *createContext(QOpenGLContext *context) = 0;
+ virtual QWindowsOpenGLContext *createContext(HGLRC context, HWND window) = 0;
virtual void *moduleHandle() const = 0;
virtual QOpenGLContext::OpenGLModuleType moduleType() const = 0;
virtual bool supportsThreadedOpenGL() const { return false; }
@@ -77,9 +42,6 @@ class QWindowsOpenGLContext : public QPlatformOpenGLContext
{
Q_DISABLE_COPY_MOVE(QWindowsOpenGLContext)
public:
- // Returns the native context handle (e.g. HGLRC for WGL, EGLContext for EGL).
- virtual void *nativeContext() const = 0;
-
// These should be implemented only for some winsys interfaces, for example EGL.
// For others, like WGL, they are not relevant.
virtual void *nativeDisplay() const { return nullptr; }
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index afc1991e2c..6a790bcc1b 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsopengltester.h"
#include "qwindowscontext.h"
#include <QtCore/qvariant.h>
+#include <QtCore/qmap.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtextstream.h>
#include <QtCore/qcoreapplication.h>
@@ -49,13 +14,14 @@
#include <QtCore/qstandardpaths.h>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qhash.h>
+#include <private/qsystemlibrary_p.h>
+#include <QtGui/qtgui-config.h>
#ifndef QT_NO_OPENGL
#include <private/qopengl_p.h>
#endif
#include <QtCore/qt_windows.h>
-#include <private/qsystemlibrary_p.h>
#include <d3d9.h>
QT_BEGIN_NAMESPACE
@@ -69,7 +35,7 @@ static GpuDescription adapterIdentifierToGpuDescription(const D3DADAPTER_IDENTIF
result.deviceId = adapterIdentifier.DeviceId;
result.revision = adapterIdentifier.Revision;
result.subSysId = adapterIdentifier.SubSysId;
- QVector<int> version(4, 0);
+ QList<int> version(4, 0);
version[0] = HIWORD(adapterIdentifier.DriverVersion.HighPart); // Product
version[1] = LOWORD(adapterIdentifier.DriverVersion.HighPart); // Version
version[2] = HIWORD(adapterIdentifier.DriverVersion.LowPart); // Sub version
@@ -94,19 +60,12 @@ public:
bool retrieveAdapterIdentifier(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const;
private:
- QSystemLibrary m_d3d9lib;
IDirect3D9 *m_direct3D9 = nullptr;
};
-QDirect3D9Handle::QDirect3D9Handle() :
- m_d3d9lib(QStringLiteral("d3d9"))
+QDirect3D9Handle::QDirect3D9Handle()
{
- using PtrDirect3DCreate9 = IDirect3D9 *(WINAPI *)(UINT);
-
- if (m_d3d9lib.load()) {
- if (auto direct3DCreate9 = (PtrDirect3DCreate9)m_d3d9lib.resolve("Direct3DCreate9"))
- m_direct3D9 = direct3DCreate9(D3D_SDK_VERSION);
- }
+ m_direct3D9 = Direct3DCreate9(D3D_SDK_VERSION);
}
QDirect3D9Handle::~QDirect3D9Handle()
@@ -169,9 +128,9 @@ GpuDescription GpuDescription::detect()
return result;
}
-QVector<GpuDescription> GpuDescription::detectAll()
+QList<GpuDescription> GpuDescription::detectAll()
{
- QVector<GpuDescription> result;
+ QList<GpuDescription> result;
QDirect3D9Handle direct3D9;
if (const UINT adapterCount = direct3D9.adapterCount()) {
for (UINT adp = 0; adp < adapterCount; ++adp) {
@@ -206,7 +165,7 @@ QString GpuDescription::toString() const
str << " Card name : " << description
<< "\n Driver Name : " << driverName
<< "\n Driver Version : " << driverVersion.toString()
- << "\n Vendor ID : 0x" << qSetPadChar(QLatin1Char('0'))
+ << "\n Vendor ID : 0x" << qSetPadChar(u'0')
<< Qt::uppercasedigits << Qt::hex << qSetFieldWidth(4) << vendorId
<< "\n Device ID : 0x" << qSetFieldWidth(4) << deviceId
<< "\n SubSys ID : 0x" << qSetFieldWidth(8) << subSysId
@@ -224,50 +183,30 @@ QVariant GpuDescription::toVariant() const
result.insert(QStringLiteral("deviceId"), QVariant(deviceId));
result.insert(QStringLiteral("subSysId"),QVariant(subSysId));
result.insert(QStringLiteral("revision"), QVariant(revision));
- result.insert(QStringLiteral("driver"), QVariant(QLatin1String(driverName)));
+ result.insert(QStringLiteral("driver"), QVariant(QLatin1StringView(driverName)));
result.insert(QStringLiteral("driverProduct"), QVariant(driverVersion.segmentAt(0)));
result.insert(QStringLiteral("driverVersion"), QVariant(driverVersion.segmentAt(1)));
result.insert(QStringLiteral("driverSubVersion"), QVariant(driverVersion.segmentAt(2)));
result.insert(QStringLiteral("driverBuild"), QVariant(driverVersion.segmentAt(3)));
result.insert(QStringLiteral("driverVersionString"), driverVersion.toString());
- result.insert(QStringLiteral("description"), QVariant(QLatin1String(description)));
+ result.insert(QStringLiteral("description"), QVariant(QLatin1StringView(description)));
result.insert(QStringLiteral("printable"), QVariant(toString()));
return result;
}
-QWindowsOpenGLTester::Renderer QWindowsOpenGLTester::requestedGlesRenderer()
-{
- const char platformVar[] = "QT_ANGLE_PLATFORM";
- if (qEnvironmentVariableIsSet(platformVar)) {
- const QByteArray anglePlatform = qgetenv(platformVar);
- if (anglePlatform == "d3d11")
- return QWindowsOpenGLTester::AngleRendererD3d11;
- if (anglePlatform == "d3d9")
- return QWindowsOpenGLTester::AngleRendererD3d9;
- if (anglePlatform == "warp")
- return QWindowsOpenGLTester::AngleRendererD3d11Warp;
- qCWarning(lcQpaGl) << "Invalid value set for " << platformVar << ": " << anglePlatform;
- }
- return QWindowsOpenGLTester::InvalidRenderer;
-}
-
QWindowsOpenGLTester::Renderer QWindowsOpenGLTester::requestedRenderer()
{
const char openGlVar[] = "QT_OPENGL";
- if (QCoreApplication::testAttribute(Qt::AA_UseOpenGLES)) {
- const Renderer glesRenderer = QWindowsOpenGLTester::requestedGlesRenderer();
- return glesRenderer != InvalidRenderer ? glesRenderer : Gles;
- }
+ if (QCoreApplication::testAttribute(Qt::AA_UseOpenGLES))
+ qWarning("Qt::AA_UseOpenGLES is no longer supported in Qt 6");
if (QCoreApplication::testAttribute(Qt::AA_UseDesktopOpenGL))
return QWindowsOpenGLTester::DesktopGl;
if (QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL))
return QWindowsOpenGLTester::SoftwareRasterizer;
if (qEnvironmentVariableIsSet(openGlVar)) {
const QByteArray requested = qgetenv(openGlVar);
- if (requested == "angle") {
- const Renderer glesRenderer = QWindowsOpenGLTester::requestedGlesRenderer();
- return glesRenderer != InvalidRenderer ? glesRenderer : Gles;
- }
+ if (requested == "angle")
+ qWarning("QT_OPENGL=angle is no longer supported in Qt 6");
if (requested == "desktop")
return QWindowsOpenGLTester::DesktopGl;
if (requested == "software")
@@ -283,9 +222,9 @@ static inline QString resolveBugListFile(const QString &fileName)
return fileName;
// Try QLibraryInfo::SettingsPath which is typically empty unless specified in qt.conf,
// then resolve via QStandardPaths::ConfigLocation.
- const QString settingsPath = QLibraryInfo::location(QLibraryInfo::SettingsPath);
+ const QString settingsPath = QLibraryInfo::path(QLibraryInfo::SettingsPath);
if (!settingsPath.isEmpty()) { // SettingsPath is empty unless specified in qt.conf.
- const QFileInfo fi(settingsPath + QLatin1Char('/') + fileName);
+ const QFileInfo fi(settingsPath + u'/' + fileName);
if (fi.isFile())
return fi.absoluteFilePath();
}
@@ -301,9 +240,9 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c
Renderer requested)
{
#if defined(QT_NO_OPENGL)
- Q_UNUSED(gpu)
- Q_UNUSED(requested)
- return 0;
+ Q_UNUSED(gpu);
+ Q_UNUSED(requested);
+ return {};
#else
QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.vendorId, gpu.deviceId, gpu.driverVersion, gpu.description);
SupportedRenderersCache *srCache = supportedRenderersCache();
@@ -311,46 +250,29 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c
if (it != srCache->cend())
return *it;
- QWindowsOpenGLTester::Renderers result(QWindowsOpenGLTester::AngleRendererD3d11
- | QWindowsOpenGLTester::AngleRendererD3d9
- | QWindowsOpenGLTester::AngleRendererD3d11Warp
- | QWindowsOpenGLTester::SoftwareRasterizer);
+ QWindowsOpenGLTester::Renderers result(QWindowsOpenGLTester::SoftwareRasterizer);
// Don't test for GL if explicitly requested or GLES only is requested
- if (requested == DesktopGl
- || ((requested & GlesMask) == 0 && testDesktopGL())) {
- result |= QWindowsOpenGLTester::DesktopGl;
- }
-
- const char bugListFileVar[] = "QT_OPENGL_BUGLIST";
- QString buglistFileName = QStringLiteral(":/qt-project.org/windows/openglblacklists/default.json");
-
- if (qEnvironmentVariableIsSet(bugListFileVar)) {
- const QString fileName = resolveBugListFile(QFile::decodeName(qgetenv(bugListFileVar)));
- if (!fileName.isEmpty())
- buglistFileName = fileName;
+ if (requested == DesktopGl || testDesktopGL())
+ result |= QWindowsOpenGLTester::DesktopGl;
+
+ QSet<QString> features; // empty by default -> nothing gets disabled
+ if (!qEnvironmentVariableIsSet("QT_NO_OPENGL_BUGLIST")) {
+ const char bugListFileVar[] = "QT_OPENGL_BUGLIST";
+ QString buglistFileName = QStringLiteral(":/qt-project.org/windows/openglblacklists/default.json");
+ if (qEnvironmentVariableIsSet(bugListFileVar)) {
+ const QString fileName = resolveBugListFile(QFile::decodeName(qgetenv(bugListFileVar)));
+ if (!fileName.isEmpty())
+ buglistFileName = fileName;
+ }
+ features = QOpenGLConfig::gpuFeatures(qgpu, buglistFileName);
}
-
- QSet<QString> features = QOpenGLConfig::gpuFeatures(qgpu, buglistFileName);
qCDebug(lcQpaGl) << "GPU features:" << features;
if (features.contains(QStringLiteral("disable_desktopgl"))) { // Qt-specific
qCDebug(lcQpaGl) << "Disabling Desktop GL: " << gpu;
result &= ~QWindowsOpenGLTester::DesktopGl;
}
- if (features.contains(QStringLiteral("disable_angle"))) { // Qt-specific keyword
- qCDebug(lcQpaGl) << "Disabling ANGLE: " << gpu;
- result &= ~QWindowsOpenGLTester::GlesMask;
- } else {
- if (features.contains(QStringLiteral("disable_d3d11"))) { // standard keyword
- qCDebug(lcQpaGl) << "Disabling D3D11: " << gpu;
- result &= ~QWindowsOpenGLTester::AngleRendererD3d11;
- }
- if (features.contains(QStringLiteral("disable_d3d9"))) { // Qt-specific
- qCDebug(lcQpaGl) << "Disabling D3D9: " << gpu;
- result &= ~QWindowsOpenGLTester::AngleRendererD3d9;
- }
- }
if (features.contains(QStringLiteral("disable_rotation"))) {
qCDebug(lcQpaGl) << "Disabling rotation: " << gpu;
result |= DisableRotationFlag;
@@ -395,7 +317,7 @@ bool QWindowsOpenGLTester::testDesktopGL()
// Test #1: Load opengl32.dll and try to resolve an OpenGL 2 function.
// This will typically fail on systems that do not have a real OpenGL driver.
- lib = LoadLibraryA("opengl32.dll");
+ lib = QSystemLibrary::load(L"opengl32");
if (lib) {
CreateContext = reinterpret_cast<CreateContextType>(
reinterpret_cast<QFunctionPointer>(::GetProcAddress(lib, "wglCreateContext")));
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h
index 9576dfbae0..abda0c2dc1 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.h
+++ b/src/plugins/platforms/windows/qwindowsopengltester.h
@@ -1,48 +1,12 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSOPENGLTESTER_H
#define QWINDOWSOPENGLTESTER_H
#include <QtCore/qbytearray.h>
#include <QtCore/qflags.h>
-#include <QtCore/qvector.h>
+#include <QtCore/qlist.h>
#include <QtCore/qversionnumber.h>
QT_BEGIN_NAMESPACE
@@ -53,7 +17,7 @@ class QVariant;
struct GpuDescription
{
static GpuDescription detect();
- static QVector<GpuDescription> detectAll();
+ static QList<GpuDescription> detectAll();
QString toString() const;
QVariant toVariant() const;
@@ -77,12 +41,6 @@ public:
enum Renderer {
InvalidRenderer = 0x0000,
DesktopGl = 0x0001,
- AngleRendererD3d11 = 0x0002,
- AngleRendererD3d9 = 0x0004,
- AngleRendererD3d11Warp = 0x0008, // "Windows Advanced Rasterization Platform"
- AngleBackendMask = AngleRendererD3d11 | AngleRendererD3d9 | AngleRendererD3d11Warp,
- Gles = 0x0010, // ANGLE/unspecified or Generic GLES for Windows CE.
- GlesMask = Gles | AngleBackendMask,
SoftwareRasterizer = 0x0020,
RendererMask = 0x00FF,
DisableRotationFlag = 0x0100,
@@ -90,7 +48,6 @@ public:
};
Q_DECLARE_FLAGS(Renderers, Renderer)
- static Renderer requestedGlesRenderer();
static Renderer requestedRenderer();
static QWindowsOpenGLTester::Renderers supportedRenderers(Renderer requested);
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index fba24d8696..71c7217671 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -1,50 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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$
-**
-****************************************************************************/
-
-#if defined(WINVER) && WINVER < 0x0603
-# undef WINVER
-#endif
-#if !defined(WINVER)
-# define WINVER 0x0603 // Enable pointer functions for MinGW
-#endif
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qt_windows.h>
#include "qwindowspointerhandler.h"
+#include "qwindowsmousehandler.h"
+#if QT_CONFIG(tabletevent)
+# include "qwindowstabletsupport.h"
+#endif
#include "qwindowskeymapper.h"
#include "qwindowscontext.h"
#include "qwindowswindow.h"
@@ -53,12 +16,11 @@
#include <QtGui/qguiapplication.h>
#include <QtGui/qscreen.h>
-#include <QtGui/qtouchdevice.h>
+#include <QtGui/qpointingdevice.h>
#include <QtGui/qwindow.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qloggingcategory.h>
-#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/qqueue.h>
#include <algorithm>
@@ -75,12 +37,18 @@ enum {
QT_PT_TOUCHPAD = 5, // MinGW is missing PT_TOUCHPAD
};
+qint64 QWindowsPointerHandler::m_nextInputDeviceId = 1;
+
+QWindowsPointerHandler::~QWindowsPointerHandler()
+{
+}
+
bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
{
*result = 0;
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
- if (!QWindowsContext::user32dll.getPointerType(pointerId, &m_pointerType)) {
+ if (!GetPointerType(pointerId, &m_pointerType)) {
qWarning() << "GetPointerType() failed:" << qt_error_string();
return false;
}
@@ -94,12 +62,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
}
case QT_PT_TOUCH: {
quint32 pointerCount = 0;
- if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
+ if (!GetPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
return false;
}
QVarLengthArray<POINTER_TOUCH_INFO, 10> touchInfo(pointerCount);
- if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data())) {
+ if (!GetPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data())) {
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
return false;
}
@@ -112,10 +80,10 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
// dispatch any skipped frames if event compression is disabled by the app
if (historyCount > 1 && !QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents)) {
touchInfo.resize(pointerCount * historyCount);
- if (!QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId,
- &historyCount,
- &pointerCount,
- touchInfo.data())) {
+ if (!GetPointerFrameTouchInfoHistory(pointerId,
+ &historyCount,
+ &pointerCount,
+ touchInfo.data())) {
qWarning() << "GetPointerFrameTouchInfoHistory() failed:" << qt_error_string();
return false;
}
@@ -133,7 +101,7 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
}
case QT_PT_PEN: {
POINTER_PEN_INFO penInfo;
- if (!QWindowsContext::user32dll.getPointerPenInfo(pointerId, &penInfo)) {
+ if (!GetPointerPenInfo(pointerId, &penInfo)) {
qWarning() << "GetPointerPenInfo() failed:" << qt_error_string();
return false;
}
@@ -145,9 +113,7 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|| !QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents))) {
QVarLengthArray<POINTER_PEN_INFO, 10> penInfoHistory(historyCount);
- if (!QWindowsContext::user32dll.getPointerPenInfoHistory(pointerId,
- &historyCount,
- penInfoHistory.data())) {
+ if (!GetPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data())) {
qWarning() << "GetPointerPenInfoHistory() failed:" << qt_error_string();
return false;
}
@@ -190,11 +156,11 @@ static inline MouseEvent eventFromMsg(const MSG &msg)
case WM_LBUTTONDBLCLK: // Qt QPA does not handle double clicks, send as press
return {QEvent::MouseButtonPress, Qt::LeftButton};
case WM_MBUTTONDOWN:
- return {QEvent::MouseButtonPress, Qt::MidButton};
+ return {QEvent::MouseButtonPress, Qt::MiddleButton};
case WM_MBUTTONUP:
- return {QEvent::MouseButtonRelease, Qt::MidButton};
+ return {QEvent::MouseButtonRelease, Qt::MiddleButton};
case WM_MBUTTONDBLCLK:
- return {QEvent::MouseButtonPress, Qt::MidButton};
+ return {QEvent::MouseButtonPress, Qt::MiddleButton};
case WM_RBUTTONDOWN:
return {QEvent::MouseButtonPress, Qt::RightButton};
case WM_RBUTTONUP:
@@ -216,11 +182,11 @@ static inline MouseEvent eventFromMsg(const MSG &msg)
case WM_NCLBUTTONDBLCLK:
return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton};
case WM_NCMBUTTONDOWN:
- return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton};
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::MiddleButton};
case WM_NCMBUTTONUP:
- return {QEvent::NonClientAreaMouseButtonRelease, Qt::MidButton};
+ return {QEvent::NonClientAreaMouseButtonRelease, Qt::MiddleButton};
case WM_NCMBUTTONDBLCLK:
- return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton};
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::MiddleButton};
case WM_NCRBUTTONDOWN:
return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton};
case WM_NCRBUTTONUP:
@@ -258,7 +224,7 @@ static Qt::MouseButtons queryMouseButtons()
if (GetAsyncKeyState(VK_RBUTTON) < 0)
result |= mouseSwapped ? Qt::LeftButton : Qt::RightButton;
if (GetAsyncKeyState(VK_MBUTTON) < 0)
- result |= Qt::MidButton;
+ result |= Qt::MiddleButton;
if (GetAsyncKeyState(VK_XBUTTON1) < 0)
result |= Qt::XButton1;
if (GetAsyncKeyState(VK_XBUTTON2) < 0)
@@ -310,32 +276,38 @@ static bool isValidWheelReceiver(QWindow *candidate)
return false;
}
-static QTouchDevice *createTouchDevice()
-{
- const int digitizers = GetSystemMetrics(SM_DIGITIZER);
- if (!(digitizers & (NID_INTEGRATED_TOUCH | NID_EXTERNAL_TOUCH)))
- return nullptr;
- const int tabletPc = GetSystemMetrics(SM_TABLETPC);
- const int maxTouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES);
- qCDebug(lcQpaEvents) << "Digitizers:" << Qt::hex << Qt::showbase << (digitizers & ~NID_READY)
- << "Ready:" << (digitizers & NID_READY) << Qt::dec << Qt::noshowbase
- << "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints;
- auto *result = new QTouchDevice;
- result->setType(digitizers & NID_INTEGRATED_TOUCH
- ? QTouchDevice::TouchScreen : QTouchDevice::TouchPad);
- QTouchDevice::Capabilities capabilities = QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition;
- if (result->type() == QTouchDevice::TouchPad)
- capabilities |= QTouchDevice::MouseEmulation;
- result->setCapabilities(capabilities);
- result->setMaximumTouchPoints(maxTouchPoints);
- return result;
-}
-
-QTouchDevice *QWindowsPointerHandler::ensureTouchDevice()
+QWindowsPointerHandler::QPointingDevicePtr QWindowsPointerHandler::createTouchDevice(bool mouseEmulation)
{
- if (!m_touchDevice)
- m_touchDevice = createTouchDevice();
- return m_touchDevice;
+ const int digitizers = GetSystemMetrics(SM_DIGITIZER);
+ if (!(digitizers & (NID_INTEGRATED_TOUCH | NID_EXTERNAL_TOUCH)))
+ return nullptr;
+ const int tabletPc = GetSystemMetrics(SM_TABLETPC);
+ const int maxTouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES);
+ const QPointingDevice::DeviceType type = (digitizers & NID_INTEGRATED_TOUCH)
+ ? QInputDevice::DeviceType::TouchScreen : QInputDevice::DeviceType::TouchPad;
+ QInputDevice::Capabilities capabilities = QInputDevice::Capability::Position
+ | QInputDevice::Capability::Area
+ | QInputDevice::Capability::NormalizedPosition;
+ if (type != QInputDevice::DeviceType::TouchScreen) {
+ capabilities.setFlag(QInputDevice::Capability::MouseEmulation);
+ capabilities.setFlag(QInputDevice::Capability::Scroll);
+ } else if (mouseEmulation) {
+ capabilities.setFlag(QInputDevice::Capability::MouseEmulation);
+ }
+
+ const int flags = digitizers & ~NID_READY;
+ qCDebug(lcQpaEvents) << "Digitizers:" << Qt::hex << Qt::showbase << flags
+ << "Ready:" << (digitizers & NID_READY) << Qt::dec << Qt::noshowbase
+ << "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints << "Capabilities:" << capabilities;
+
+ const int buttonCount = type == QInputDevice::DeviceType::TouchScreen ? 1 : 3;
+ // TODO: use system-provided name and device ID rather than empty-string and m_nextInputDeviceId
+ const qint64 systemId = m_nextInputDeviceId++ | (qint64(flags << 2));
+ auto d = new QPointingDevice(QString(), systemId, type,
+ QPointingDevice::PointerType::Finger,
+ capabilities, maxTouchPoints, buttonCount,
+ QString(), QPointingDeviceUniqueId::fromNumericId(systemId));
+ return QPointingDevicePtr(d);
}
void QWindowsPointerHandler::clearEvents()
@@ -447,6 +419,8 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
{
Q_UNUSED(hwnd);
+ auto *touchInfo = static_cast<POINTER_TOUCH_INFO *>(vTouchInfo);
+
if (et & QtWindows::NonClientEventFlag)
return false; // Let DefWindowProc() handle Non Client messages.
@@ -454,12 +428,24 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
return false;
if (msg.message == WM_POINTERCAPTURECHANGED) {
- QWindowSystemInterface::handleTouchCancelEvent(window, m_touchDevice,
- QWindowsKeyMapper::queryKeyboardModifiers());
- m_lastTouchPositions.clear();
+ const auto *keyMapper = QWindowsContext::instance()->keyMapper();
+ QWindowSystemInterface::handleTouchCancelEvent(window, msg.time, m_touchDevice.data(),
+ keyMapper->queryKeyboardModifiers());
+ m_lastTouchPoints.clear();
return true;
}
+ if (msg.message == WM_POINTERLEAVE) {
+ for (quint32 i = 0; i < count; ++i) {
+ const quint32 pointerId = touchInfo[i].pointerInfo.pointerId;
+ int id = m_touchInputIDToTouchPointID.value(pointerId, -1);
+ if (id != -1)
+ m_lastTouchPoints.remove(id);
+ }
+ // Send LeaveEvent to reset hover when the last finger leaves the touch screen (QTBUG-62912)
+ QWindowSystemInterface::handleEnterLeaveEvent(nullptr, window);
+ }
+
// Only handle down/up/update, ignore others like WM_POINTERENTER, WM_POINTERLEAVE, etc.
if (msg.message > WM_POINTERUP)
return false;
@@ -470,8 +456,6 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
if (!screen)
return false;
- auto *touchInfo = static_cast<POINTER_TOUCH_INFO *>(vTouchInfo);
-
const QRect screenGeometry = screen->geometry();
QList<QWindowSystemInterface::TouchPoint> touchPoints;
@@ -482,7 +466,8 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
<< " message=" << Qt::hex << msg.message
<< " count=" << Qt::dec << count;
- Qt::TouchPointStates allStates;
+ QEventPoint::States allStates;
+ QSet<int> inputIds;
for (quint32 i = 0; i < count; ++i) {
if (QWindowsContext::verbose > 1)
@@ -495,14 +480,17 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
const quint32 pointerId = touchInfo[i].pointerInfo.pointerId;
int id = m_touchInputIDToTouchPointID.value(pointerId, -1);
if (id == -1) {
+ // Start tracking after fingers touch the screen. Ignore bogus updates after touch is released.
+ if ((touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_DOWN) == 0)
+ continue;
id = m_touchInputIDToTouchPointID.size();
m_touchInputIDToTouchPointID.insert(pointerId, id);
}
touchPoint.id = id;
touchPoint.pressure = (touchInfo[i].touchMask & TOUCH_MASK_PRESSURE) ?
touchInfo[i].pressure / 1024.0 : 1.0;
- if (m_lastTouchPositions.contains(touchPoint.id))
- touchPoint.normalPosition = m_lastTouchPositions.value(touchPoint.id);
+ if (m_lastTouchPoints.contains(touchPoint.id))
+ touchPoint.normalPosition = m_lastTouchPoints.value(touchPoint.id).normalPosition;
const QPointF screenPos = QPointF(touchInfo[i].pointerInfo.ptPixelLocation.x,
touchInfo[i].pointerInfo.ptPixelLocation.y);
@@ -517,32 +505,58 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
touchPoint.normalPosition = normalPosition;
if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_DOWN) {
- touchPoint.state = Qt::TouchPointPressed;
- m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition);
+ touchPoint.state = QEventPoint::State::Pressed;
+ m_lastTouchPoints.insert(touchPoint.id, touchPoint);
} else if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_UP) {
- touchPoint.state = Qt::TouchPointReleased;
- m_lastTouchPositions.remove(touchPoint.id);
+ touchPoint.state = QEventPoint::State::Released;
+ m_lastTouchPoints.remove(touchPoint.id);
} else {
- touchPoint.state = stationaryTouchPoint ? Qt::TouchPointStationary : Qt::TouchPointMoved;
- m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition);
+ touchPoint.state = stationaryTouchPoint ? QEventPoint::State::Stationary : QEventPoint::State::Updated;
+ m_lastTouchPoints.insert(touchPoint.id, touchPoint);
}
allStates |= touchPoint.state;
touchPoints.append(touchPoint);
+ inputIds.insert(touchPoint.id);
// Avoid getting repeated messages for this frame if there are multiple pointerIds
- QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
+ SkipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
+ }
+
+ // Some devices send touches for each finger in a different message/frame, instead of consolidating
+ // them in the same frame as we were expecting. We account for missing unreleased touches here.
+ for (auto tp : std::as_const(m_lastTouchPoints)) {
+ if (!inputIds.contains(tp.id)) {
+ tp.state = QEventPoint::State::Stationary;
+ allStates |= tp.state;
+ touchPoints.append(tp);
+ }
}
+ if (touchPoints.count() == 0)
+ return false;
+
// all touch points released, forget the ids we've seen.
- if (allStates == Qt::TouchPointReleased)
+ if (allStates == QEventPoint::State::Released)
m_touchInputIDToTouchPointID.clear();
- QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints,
- QWindowsKeyMapper::queryKeyboardModifiers());
+ const auto *keyMapper = QWindowsContext::instance()->keyMapper();
+ QWindowSystemInterface::handleTouchEvent(window, msg.time, m_touchDevice.data(), touchPoints,
+ keyMapper->queryKeyboardModifiers());
return false; // Allow mouse messages to be generated.
}
+#if QT_CONFIG(tabletevent)
+QWindowsPointerHandler::QPointingDevicePtr QWindowsPointerHandler::findTabletDevice(QPointingDevice::PointerType pointerType) const
+{
+ for (const auto &d : m_tabletDevices) {
+ if (d->pointerType() == pointerType)
+ return d;
+ }
+ return {};
+}
+#endif
+
bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et,
MSG msg, PVOID vPenInfo)
{
@@ -553,32 +567,35 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
auto *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
RECT pRect, dRect;
- if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
+ if (!GetPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
return false;
- const auto sourceDevice = (qint64)penInfo->pointerInfo.sourceDevice;
+ const auto systemId = (qint64)penInfo->pointerInfo.sourceDevice;
const QPoint globalPos = QPoint(penInfo->pointerInfo.ptPixelLocation.x, penInfo->pointerInfo.ptPixelLocation.y);
const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
const QPointF hiResGlobalPos = QPointF(dRect.left + qreal(penInfo->pointerInfo.ptHimetricLocation.x - pRect.left)
/ (pRect.right - pRect.left) * (dRect.right - dRect.left),
dRect.top + qreal(penInfo->pointerInfo.ptHimetricLocation.y - pRect.top)
/ (pRect.bottom - pRect.top) * (dRect.bottom - dRect.top));
- const qreal pressure = (penInfo->penMask & PEN_MASK_PRESSURE) ? qreal(penInfo->pressure) / 1024.0 : 0.5;
- const qreal rotation = (penInfo->penMask & PEN_MASK_ROTATION) ? qreal(penInfo->rotation) : 0.0;
+ const bool hasPressure = (penInfo->penMask & PEN_MASK_PRESSURE) != 0;
+ const bool hasRotation = (penInfo->penMask & PEN_MASK_ROTATION) != 0;
+ const qreal pressure = hasPressure ? qreal(penInfo->pressure) / 1024.0 : 0.5;
+ const qreal rotation = hasRotation ? qreal(penInfo->rotation) : 0.0;
const qreal tangentialPressure = 0.0;
- const int xTilt = (penInfo->penMask & PEN_MASK_TILT_X) ? penInfo->tiltX : 0;
- const int yTilt = (penInfo->penMask & PEN_MASK_TILT_Y) ? penInfo->tiltY : 0;
+ const bool hasTiltX = (penInfo->penMask & PEN_MASK_TILT_X) != 0;
+ const bool hasTiltY = (penInfo->penMask & PEN_MASK_TILT_Y) != 0;
+ const int xTilt = hasTiltX ? penInfo->tiltX : 0;
+ const int yTilt = hasTiltY ? penInfo->tiltY : 0;
const int z = 0;
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaEvents).noquote().nospace() << Qt::showbase
- << __FUNCTION__ << " sourceDevice=" << sourceDevice
+ << __FUNCTION__ << " systemId=" << systemId
<< " globalPos=" << globalPos << " localPos=" << localPos << " hiResGlobalPos=" << hiResGlobalPos
<< " message=" << Qt::hex << msg.message
<< " flags=" << Qt::hex << penInfo->pointerInfo.pointerFlags;
- const QTabletEvent::TabletDevice device = QTabletEvent::Stylus;
- QTabletEvent::PointerType type;
+ QPointingDevice::PointerType type;
// Since it may be the middle button, so if the checks fail then it should
// be set to Middle if it was used.
Qt::MouseButtons mouseButtons = queryMouseButtons();
@@ -588,16 +605,41 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
mouseButtons = Qt::LeftButton;
if (penInfo->penFlags & (PEN_FLAG_ERASER | PEN_FLAG_INVERTED)) {
- type = QTabletEvent::Eraser;
+ type = QPointingDevice::PointerType::Eraser;
} else {
- type = QTabletEvent::Pen;
+ type = QPointingDevice::PointerType::Pen;
if (pointerInContact && penInfo->penFlags & PEN_FLAG_BARREL)
mouseButtons = Qt::RightButton; // Either left or right, not both
}
+ auto device = findTabletDevice(type);
+ if (device.isNull()) {
+ QInputDevice::Capabilities caps(QInputDevice::Capability::Position
+ | QInputDevice::Capability::MouseEmulation
+ | QInputDevice::Capability::Hover);
+ if (hasPressure)
+ caps |= QInputDevice::Capability::Pressure;
+ if (hasRotation)
+ caps |= QInputDevice::Capability::Rotation;
+ if (hasTiltX)
+ caps |= QInputDevice::Capability::XTilt;
+ if (hasTiltY)
+ caps |= QInputDevice::Capability::YTilt;
+ const qint64 uniqueId = systemId | (qint64(type) << 32L);
+ device.reset(new QPointingDevice(QStringLiteral("wmpointer"),
+ systemId, QInputDevice::DeviceType::Stylus,
+ type, caps, 1, 3, QString(),
+ QPointingDeviceUniqueId::fromNumericId(uniqueId)));
+ QWindowSystemInterface::registerInputDevice(device.data());
+ m_tabletDevices.append(device);
+ }
+
+ const auto uniqueId = device->uniqueId().numericId();
+ m_activeTabletDevice = device;
+
switch (msg.message) {
case WM_POINTERENTER: {
- QWindowSystemInterface::handleTabletEnterProximityEvent(device, type, sourceDevice);
+ QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(window, msg.time, device.data(), true);
m_windowUnderPointer = window;
// The local coordinates may fall outside the window.
// Wait until the next update to send the enter event.
@@ -610,12 +652,12 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
m_windowUnderPointer = nullptr;
m_currentWindow = nullptr;
}
- QWindowSystemInterface::handleTabletLeaveProximityEvent(device, type, sourceDevice);
+ QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(window, msg.time, device.data(), false);
break;
case WM_POINTERDOWN:
case WM_POINTERUP:
case WM_POINTERUPDATE: {
- QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(sourceDevice).target; // Pass to window that grabbed it.
+ QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(uniqueId).target; // Pass to window that grabbed it.
if (!target && m_windowUnderPointer)
target = m_windowUnderPointer;
if (!target)
@@ -633,11 +675,13 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
wumPlatformWindow->applyCursor();
}
}
- const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
+ const auto *keyMapper = QWindowsContext::instance()->keyMapper();
+ const Qt::KeyboardModifiers keyModifiers = keyMapper->queryKeyboardModifiers();
- QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons,
- pressure, xTilt, yTilt, tangentialPressure, rotation, z,
- sourceDevice, keyModifiers);
+ QWindowSystemInterface::handleTabletEvent(target, msg.time, device.data(),
+ localPos, hiResGlobalPos, mouseButtons,
+ pressure, xTilt, yTilt, tangentialPressure,
+ rotation, z, keyModifiers);
return false; // Allow mouse messages to be generated.
}
}
@@ -685,7 +729,7 @@ bool QWindowsPointerHandler::translateMouseWheelEvent(QWindow *window,
QPoint localPos = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos);
- QWindowSystemInterface::handleWheelEvent(receiver, localPos, globalPos, QPoint(), angleDelta, keyModifiers);
+ QWindowSystemInterface::handleWheelEvent(receiver, msg.time, localPos, globalPos, QPoint(), angleDelta, keyModifiers);
return true;
}
@@ -698,25 +742,31 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
{
*result = 0;
- QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
- if ((et & QtWindows::NonClientEventFlag) == 0 && QWindowsBaseWindow::isRtlLayout(hwnd)) {
- RECT clientArea;
- GetClientRect(hwnd, &clientArea);
- eventPos.setX(clientArea.right - eventPos.x());
- }
-
QPoint localPos;
QPoint globalPos;
+ QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
if ((et == QtWindows::MouseWheelEvent) || (et & QtWindows::NonClientEventFlag)) {
globalPos = eventPos;
localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, eventPos);
} else {
- localPos = eventPos;
+ if (QWindowsBaseWindow::isRtlLayout(hwnd)) {
+ RECT clientArea;
+ GetClientRect(hwnd, &clientArea);
+ eventPos.setX(clientArea.right - eventPos.x());
+ }
+
globalPos = QWindowsGeometryHint::mapToGlobal(hwnd, eventPos);
+ auto targetHwnd = hwnd;
+ if (auto *pw = window->handle())
+ targetHwnd = HWND(pw->winId());
+ localPos = targetHwnd == hwnd
+ ? eventPos
+ : QWindowsGeometryHint::mapFromGlobal(targetHwnd, globalPos);
}
- const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
+ const auto *keyMapper = QWindowsContext::instance()->keyMapper();
+ const Qt::KeyboardModifiers keyModifiers = keyMapper->queryKeyboardModifiers();
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
if (et == QtWindows::MouseWheelEvent)
@@ -728,21 +778,35 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
// X11 and macOS.
bool discardEvent = false;
if (msg.message == WM_MOUSEMOVE) {
- static QPoint lastMouseMovePos;
+ Q_CONSTINIT static QPoint lastMouseMovePos;
if (msg.wParam == 0 && (m_windowUnderPointer.isNull() || globalPos == lastMouseMovePos))
discardEvent = true;
lastMouseMovePos = globalPos;
}
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
+ const QPointingDevice *device = QWindowsMouseHandler::primaryMouse();
+
// Following the logic of the old mouse handler, only events synthesized
// for touch screen are marked as such. On some systems, using the bit 7 of
// the extra msg info for checking if synthesized for touch does not work,
// so we use the pointer type of the last pointer message.
- if (isMouseEventSynthesizedFromPenOrTouch() && m_pointerType == QT_PT_TOUCH) {
- if (QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)
+ if (isMouseEventSynthesizedFromPenOrTouch()) {
+ switch (m_pointerType) {
+ case QT_PT_TOUCH:
+ if (QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)
+ return false;
+ source = Qt::MouseEventSynthesizedBySystem;
+ if (!m_touchDevice.isNull())
+ device = m_touchDevice.data();
+ break;
+ case QT_PT_PEN:
+#if QT_CONFIG(tabletevent)
+ qCDebug(lcQpaTablet) << "ignoring synth-mouse event for tablet event from" << device;
return false;
- source = Qt::MouseEventSynthesizedBySystem;
+#endif
+ break;
+ }
}
const MouseEvent mouseEvent = eventFromMsg(msg);
@@ -762,19 +826,16 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
if (m_lastEventType == QEvent::NonClientAreaMouseButtonPress
&& (mouseEvent.type == QEvent::NonClientAreaMouseMove || mouseEvent.type == QEvent::MouseMove)
&& (m_lastEventButton & mouseButtons) == 0) {
- if (mouseEvent.type == QEvent::NonClientAreaMouseMove) {
- QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons, m_lastEventButton,
- QEvent::NonClientAreaMouseButtonRelease, keyModifiers, source);
- } else {
- QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, m_lastEventButton,
- QEvent::MouseButtonRelease, keyModifiers, source);
- }
+ auto releaseType = mouseEvent.type == QEvent::NonClientAreaMouseMove ?
+ QEvent::NonClientAreaMouseButtonRelease : QEvent::MouseButtonRelease;
+ QWindowSystemInterface::handleMouseEvent(window, msg.time, device, localPos, globalPos, mouseButtons, m_lastEventButton,
+ releaseType, keyModifiers, source);
}
m_lastEventType = mouseEvent.type;
m_lastEventButton = mouseEvent.button;
if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) {
- QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons,
+ QWindowSystemInterface::handleMouseEvent(window, msg.time, device, localPos, globalPos, mouseButtons,
mouseEvent.button, mouseEvent.type, keyModifiers, source);
return false; // Allow further event processing
}
@@ -794,7 +855,7 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
handleEnterLeave(window, currentWindowUnderPointer, globalPos);
if (!discardEvent && mouseEvent.type != QEvent::None) {
- QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons,
+ QWindowSystemInterface::handleMouseEvent(window, msg.time, device, localPos, globalPos, mouseButtons,
mouseEvent.button, mouseEvent.type, keyModifiers, source);
}
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h
index 8874db27e3..b64a8c146a 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.h
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSPOINTERHANDLER_H
#define QWINDOWSPOINTERHANDLER_H
@@ -45,23 +9,31 @@
#include <QtCore/qpointer.h>
#include <QtCore/qscopedpointer.h>
+#include <QtCore/qsharedpointer.h>
#include <QtCore/qhash.h>
#include <QtGui/qevent.h>
+#include <qpa/qwindowsysteminterface.h>
QT_BEGIN_NAMESPACE
class QWindow;
-class QTouchDevice;
+class QPointingDevice;
class QWindowsPointerHandler
{
Q_DISABLE_COPY_MOVE(QWindowsPointerHandler)
public:
+ using QPointingDevicePtr = QSharedPointer<QPointingDevice>;
+
QWindowsPointerHandler() = default;
+ ~QWindowsPointerHandler();
bool translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result);
bool translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result);
- QTouchDevice *touchDevice() const { return m_touchDevice; }
- QTouchDevice *ensureTouchDevice();
+
+ const QPointingDevicePtr &touchDevice() const { return m_touchDevice; }
+ void setTouchDevice(const QPointingDevicePtr &d) { m_touchDevice = d; }
+ static QPointingDevicePtr createTouchDevice(bool mouseEmulation);
+
QWindow *windowUnderMouse() const { return m_windowUnderPointer.data(); }
void clearWindowUnderMouse() { m_windowUnderPointer = nullptr; }
void clearEvents();
@@ -72,9 +44,16 @@ private:
bool translateMouseWheelEvent(QWindow *window, QWindow *currentWindowUnderPointer, MSG msg, QPoint globalPos, Qt::KeyboardModifiers keyModifiers);
void handleCaptureRelease(QWindow *window, QWindow *currentWindowUnderPointer, HWND hwnd, QEvent::Type eventType, Qt::MouseButtons mouseButtons);
void handleEnterLeave(QWindow *window, QWindow *currentWindowUnderPointer, QPoint globalPos);
+#if QT_CONFIG(tabletevent)
+ QPointingDevicePtr findTabletDevice(QPointingDevice::PointerType pointerType) const;
+#endif
- QTouchDevice *m_touchDevice = nullptr;
- QHash<int, QPointF> m_lastTouchPositions;
+ QPointingDevicePtr m_touchDevice;
+#if QT_CONFIG(tabletevent)
+ QList<QPointingDevicePtr> m_tabletDevices;
+ QPointingDevicePtr m_activeTabletDevice;
+#endif
+ QHash<int, QWindowSystemInterface::TouchPoint> m_lastTouchPoints;
QHash<DWORD, int> m_touchInputIDToTouchPointID;
QPointer<QWindow> m_windowUnderPointer;
QPointer<QWindow> m_currentWindow;
@@ -83,6 +62,7 @@ private:
QEvent::Type m_lastEventType = QEvent::None;
Qt::MouseButton m_lastEventButton = Qt::NoButton;
DWORD m_pointerType = 0;
+ static qint64 m_nextInputDeviceId; // workaround until we know how to get system device IDs
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 4f76a82544..a50f9fd4b0 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsscreen.h"
#include "qwindowscontext.h"
@@ -50,13 +14,28 @@
#include <QtGui/qpixmap.h>
#include <QtGui/qguiapplication.h>
#include <qpa/qwindowsysteminterface.h>
+#include <QtCore/private/qsystemerror_p.h>
+#include <QtGui/private/qedidparser_p.h>
#include <private/qhighdpiscaling_p.h>
+#include <private/qwindowsfontdatabasebase_p.h>
+#include <private/qpixmap_win_p.h>
+#include <private/quniquehandle_p.h>
+
#include <QtGui/qscreen.h>
#include <QtCore/qdebug.h>
+#include <memory>
+#include <type_traits>
+
+#include <cfgmgr32.h>
+#include <setupapi.h>
+#include <shellscalingapi.h>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static inline QDpi deviceDPI(HDC hdc)
{
return QDpi(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
@@ -64,16 +43,222 @@ static inline QDpi deviceDPI(HDC hdc)
static inline QDpi monitorDPI(HMONITOR hMonitor)
{
- if (QWindowsContext::shcoredll.isValid()) {
- UINT dpiX;
- UINT dpiY;
- if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, 0, &dpiX, &dpiY)))
- return QDpi(dpiX, dpiY);
- }
+ UINT dpiX;
+ UINT dpiY;
+ if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
+ return QDpi(dpiX, dpiY);
return {0, 0};
}
-using WindowsScreenDataList = QVector<QWindowsScreenData>;
+static std::vector<DISPLAYCONFIG_PATH_INFO> getPathInfo(const MONITORINFOEX &viewInfo)
+{
+ // We might want to consider storing adapterId/id from DISPLAYCONFIG_PATH_TARGET_INFO.
+ std::vector<DISPLAYCONFIG_PATH_INFO> pathInfos;
+ std::vector<DISPLAYCONFIG_MODE_INFO> modeInfos;
+
+ // Fetch paths
+ LONG result;
+ UINT32 numPathArrayElements;
+ UINT32 numModeInfoArrayElements;
+ do {
+ // QueryDisplayConfig documentation doesn't say the number of needed elements is updated
+ // when the call fails with ERROR_INSUFFICIENT_BUFFER, so we need a separate call to
+ // look up the needed buffer sizes.
+ if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &numPathArrayElements,
+ &numModeInfoArrayElements) != ERROR_SUCCESS) {
+ return {};
+ }
+ pathInfos.resize(numPathArrayElements);
+ modeInfos.resize(numModeInfoArrayElements);
+ result = QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &numPathArrayElements, pathInfos.data(),
+ &numModeInfoArrayElements, modeInfos.data(), nullptr);
+ } while (result == ERROR_INSUFFICIENT_BUFFER);
+
+ if (result != ERROR_SUCCESS)
+ return {};
+
+ // Find paths matching monitor name
+ auto discardThese =
+ std::remove_if(pathInfos.begin(), pathInfos.end(), [&](const auto &path) -> bool {
+ DISPLAYCONFIG_SOURCE_DEVICE_NAME deviceName;
+ deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
+ deviceName.header.size = sizeof(DISPLAYCONFIG_SOURCE_DEVICE_NAME);
+ deviceName.header.adapterId = path.sourceInfo.adapterId;
+ deviceName.header.id = path.sourceInfo.id;
+ if (DisplayConfigGetDeviceInfo(&deviceName.header) == ERROR_SUCCESS) {
+ return wcscmp(viewInfo.szDevice, deviceName.viewGdiDeviceName) != 0;
+ }
+ return true;
+ });
+
+ pathInfos.erase(discardThese, pathInfos.end());
+
+ return pathInfos;
+}
+
+#if 0
+// Needed later for HDR support
+static float getMonitorSDRWhiteLevel(DISPLAYCONFIG_PATH_TARGET_INFO *targetInfo)
+{
+ const float defaultSdrWhiteLevel = 200.0;
+ if (!targetInfo)
+ return defaultSdrWhiteLevel;
+
+ DISPLAYCONFIG_SDR_WHITE_LEVEL whiteLevel = {};
+ whiteLevel.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL;
+ whiteLevel.header.size = sizeof(DISPLAYCONFIG_SDR_WHITE_LEVEL);
+ whiteLevel.header.adapterId = targetInfo->adapterId;
+ whiteLevel.header.id = targetInfo->id;
+ if (DisplayConfigGetDeviceInfo(&whiteLevel.header) != ERROR_SUCCESS)
+ return defaultSdrWhiteLevel;
+ return whiteLevel.SDRWhiteLevel * 80.0 / 1000.0;
+}
+#endif
+
+using WindowsScreenDataList = QList<QWindowsScreenData>;
+
+namespace {
+
+struct DiRegKeyHandleTraits
+{
+ using Type = HKEY;
+ static Type invalidValue()
+ {
+ // The setupapi.h functions return INVALID_HANDLE_VALUE when failing to open a registry key
+ return reinterpret_cast<HKEY>(INVALID_HANDLE_VALUE);
+ }
+ static bool close(Type handle) { return RegCloseKey(handle) == ERROR_SUCCESS; }
+};
+
+using DiRegKeyHandle = QUniqueHandle<DiRegKeyHandleTraits>;
+
+}
+
+static void setMonitorDataFromSetupApi(QWindowsScreenData &data,
+ const std::vector<DISPLAYCONFIG_PATH_INFO> &pathGroup)
+{
+ if (pathGroup.empty()) {
+ return;
+ }
+
+ // The only property shared among monitors in a clone group is deviceName
+ {
+ DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName = {};
+ deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
+ deviceName.header.size = sizeof(DISPLAYCONFIG_TARGET_DEVICE_NAME);
+ // The first element in the clone group is the main monitor.
+ deviceName.header.adapterId = pathGroup[0].targetInfo.adapterId;
+ deviceName.header.id = pathGroup[0].targetInfo.id;
+ if (DisplayConfigGetDeviceInfo(&deviceName.header) == ERROR_SUCCESS) {
+ data.devicePath = QString::fromWCharArray(deviceName.monitorDevicePath);
+ } else {
+ qCWarning(lcQpaScreen)
+ << u"Unable to get device information for %1:"_s.arg(pathGroup[0].targetInfo.id)
+ << QSystemError::windowsString();
+ }
+ }
+
+ // The rest must be concatenated into the resulting property
+ QStringList names;
+ QStringList manufacturers;
+ QStringList models;
+ QStringList serialNumbers;
+
+ for (const auto &path : pathGroup) {
+ DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName = {};
+ deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
+ deviceName.header.size = sizeof(DISPLAYCONFIG_TARGET_DEVICE_NAME);
+ deviceName.header.adapterId = path.targetInfo.adapterId;
+ deviceName.header.id = path.targetInfo.id;
+ if (DisplayConfigGetDeviceInfo(&deviceName.header) != ERROR_SUCCESS) {
+ qCWarning(lcQpaScreen)
+ << u"Unable to get device information for %1:"_s.arg(path.targetInfo.id)
+ << QSystemError::windowsString();
+ continue;
+ }
+
+ // https://learn.microsoft.com/en-us/windows-hardware/drivers/install/guid-devinterface-monitor
+ constexpr GUID GUID_DEVINTERFACE_MONITOR = {
+ 0xe6f07b5f, 0xee97, 0x4a90, { 0xb0, 0x76, 0x33, 0xf5, 0x7b, 0xf4, 0xea, 0xa7 }
+ };
+ const HDEVINFO devInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_MONITOR, nullptr, nullptr,
+ DIGCF_DEVICEINTERFACE);
+
+ SP_DEVICE_INTERFACE_DATA deviceInterfaceData{};
+ deviceInterfaceData.cbSize = sizeof(deviceInterfaceData);
+
+ if (!SetupDiOpenDeviceInterfaceW(devInfo, deviceName.monitorDevicePath, DIODI_NO_ADD,
+ &deviceInterfaceData)) {
+ qCWarning(lcQpaScreen)
+ << u"Unable to open monitor interface to %1:"_s.arg(data.deviceName)
+ << QSystemError::windowsString();
+ continue;
+ }
+
+ DWORD requiredSize{ 0 };
+ if (SetupDiGetDeviceInterfaceDetailW(devInfo, &deviceInterfaceData, nullptr, 0,
+ &requiredSize, nullptr)
+ || GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ continue;
+ }
+
+ const std::unique_ptr<std::byte[]> storage(new std::byte[requiredSize]);
+ auto *devicePath = reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA_W *>(storage.get());
+ devicePath->cbSize = sizeof(std::remove_pointer_t<decltype(devicePath)>);
+ SP_DEVINFO_DATA deviceInfoData{};
+ deviceInfoData.cbSize = sizeof(deviceInfoData);
+ if (!SetupDiGetDeviceInterfaceDetailW(devInfo, &deviceInterfaceData, devicePath,
+ requiredSize, nullptr, &deviceInfoData)) {
+ qCDebug(lcQpaScreen) << u"Unable to get monitor metadata for %1:"_s.arg(data.deviceName)
+ << QSystemError::windowsString();
+ continue;
+ }
+
+ const DiRegKeyHandle edidRegistryKey{ SetupDiOpenDevRegKey(
+ devInfo, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ) };
+
+ if (!edidRegistryKey.isValid())
+ continue;
+
+ DWORD edidDataSize{ 0 };
+ if (RegQueryValueExW(edidRegistryKey.get(), L"EDID", nullptr, nullptr, nullptr,
+ &edidDataSize)
+ != ERROR_SUCCESS) {
+ continue;
+ }
+
+ QByteArray edidData;
+ edidData.resize(edidDataSize);
+
+ if (RegQueryValueExW(edidRegistryKey.get(), L"EDID", nullptr, nullptr,
+ reinterpret_cast<unsigned char *>(edidData.data()), &edidDataSize)
+ != ERROR_SUCCESS) {
+ qCDebug(lcQpaScreen) << u"Unable to get EDID from the Registry for %1:"_s.arg(
+ data.deviceName)
+ << QSystemError::windowsString();
+ continue;
+ }
+
+ QEdidParser edid;
+
+ if (!edid.parse(edidData)) {
+ qCDebug(lcQpaScreen) << "Invalid EDID blob for" << data.deviceName;
+ continue;
+ }
+
+ // We skip edid.identifier because it is unreliable, and a better option
+ // is already available through DisplayConfigGetDeviceInfo (see below).
+ names << QString::fromWCharArray(deviceName.monitorFriendlyDeviceName);
+ manufacturers << edid.manufacturer;
+ models << edid.model;
+ serialNumbers << edid.serialNumber;
+ }
+
+ data.name = names.join(u"|"_s);
+ data.manufacturer = manufacturers.join(u"|"_s);
+ data.model = models.join(u"|"_s);
+ data.serialNumber = serialNumbers.join(u"|"_s);
+}
static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data)
{
@@ -86,8 +271,14 @@ static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data)
data->hMonitor = hMonitor;
data->geometry = QRect(QPoint(info.rcMonitor.left, info.rcMonitor.top), QPoint(info.rcMonitor.right - 1, info.rcMonitor.bottom - 1));
data->availableGeometry = QRect(QPoint(info.rcWork.left, info.rcWork.top), QPoint(info.rcWork.right - 1, info.rcWork.bottom - 1));
- data->name = QString::fromWCharArray(info.szDevice);
- if (data->name == QLatin1String("WinDisc")) {
+ data->deviceName = QString::fromWCharArray(info.szDevice);
+ const auto pathGroup = getPathInfo(info);
+ if (!pathGroup.empty()) {
+ setMonitorDataFromSetupApi(*data, pathGroup);
+ }
+ if (data->name.isEmpty())
+ data->name = data->deviceName;
+ if (data->deviceName == u"WinDisc") {
data->flags |= QWindowsScreenData::LockScreen;
} else {
if (const HDC hdc = CreateDC(info.szDevice, nullptr, nullptr, nullptr)) {
@@ -102,12 +293,41 @@ static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data)
DeleteDC(hdc);
} else {
qWarning("%s: Unable to obtain handle for monitor '%s', defaulting to %g DPI.",
- __FUNCTION__, qPrintable(QString::fromWCharArray(info.szDevice)),
+ __FUNCTION__, qPrintable(data->deviceName),
data->dpi.first);
} // CreateDC() failed
} // not lock screen
- data->orientation = data->geometry.height() > data->geometry.width() ?
- Qt::PortraitOrientation : Qt::LandscapeOrientation;
+
+ // ### We might want to consider storing adapterId/id from DISPLAYCONFIG_PATH_TARGET_INFO,
+ // if we are going to use DISPLAYCONFIG lookups more.
+ if (!pathGroup.empty()) {
+ // The first element in the clone group is the main monitor.
+ const auto &pathInfo = pathGroup[0];
+ switch (pathInfo.targetInfo.rotation) {
+ case DISPLAYCONFIG_ROTATION_IDENTITY:
+ data->orientation = Qt::LandscapeOrientation;
+ break;
+ case DISPLAYCONFIG_ROTATION_ROTATE90:
+ data->orientation = Qt::PortraitOrientation;
+ break;
+ case DISPLAYCONFIG_ROTATION_ROTATE180:
+ data->orientation = Qt::InvertedLandscapeOrientation;
+ break;
+ case DISPLAYCONFIG_ROTATION_ROTATE270:
+ data->orientation = Qt::InvertedPortraitOrientation;
+ break;
+ case DISPLAYCONFIG_ROTATION_FORCE_UINT32:
+ Q_UNREACHABLE();
+ break;
+ }
+ if (pathInfo.targetInfo.refreshRate.Numerator && pathInfo.targetInfo.refreshRate.Denominator)
+ data->refreshRateHz = static_cast<qreal>(pathInfo.targetInfo.refreshRate.Numerator)
+ / pathInfo.targetInfo.refreshRate.Denominator;
+ } else {
+ data->orientation = data->geometry.height() > data->geometry.width()
+ ? Qt::PortraitOrientation
+ : Qt::LandscapeOrientation;
+ }
// EnumDisplayMonitors (as opposed to EnumDisplayDevices) enumerates only
// virtual desktop screens.
data->flags |= QWindowsScreenData::VirtualDesktop;
@@ -116,12 +336,22 @@ static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data)
return true;
}
-// from QDesktopWidget, taking WindowsScreenDataList as LPARAM
+// from monitorData, taking WindowsScreenDataList as LPARAM
BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM p)
{
QWindowsScreenData data;
if (monitorData(hMonitor, &data)) {
auto *result = reinterpret_cast<WindowsScreenDataList *>(p);
+ auto it = std::find_if(result->rbegin(), result->rend(),
+ [&data](QWindowsScreenData i){ return i.name == data.name; });
+ if (it != result->rend()) {
+ int previousIndex = 1;
+ if (it->deviceIndex.has_value())
+ previousIndex = it->deviceIndex.value();
+ else
+ (*it).deviceIndex = 1;
+ data.deviceIndex = previousIndex + 1;
+ }
// QWindowSystemInterface::handleScreenAdded() documentation specifies that first
// added screen will be the primary screen, so order accordingly.
// Note that the side effect of this policy is that there is no way to change primary
@@ -148,14 +378,14 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d)
QDebugStateSaver saver(dbg);
dbg.nospace();
dbg.noquote();
- dbg << "Screen \"" << d.name << "\" "
- << d.geometry.width() << 'x' << d.geometry.height() << '+' << d.geometry.x() << '+' << d.geometry.y()
- << " avail: "
- << d.availableGeometry.width() << 'x' << d.availableGeometry.height() << '+' << d.availableGeometry.x() << '+' << d.availableGeometry.y()
- << " physical: " << d.physicalSizeMM.width() << 'x' << d.physicalSizeMM.height()
- << " DPI: " << d.dpi.first << 'x' << d.dpi.second << " Depth: " << d.depth
- << " Format: " << d.format
- << " hMonitor: " << d.hMonitor;
+ dbg << "Screen \"" << d.name << "\" " << d.geometry.width() << 'x' << d.geometry.height() << '+'
+ << d.geometry.x() << '+' << d.geometry.y() << " avail: " << d.availableGeometry.width()
+ << 'x' << d.availableGeometry.height() << '+' << d.availableGeometry.x() << '+'
+ << d.availableGeometry.y() << " physical: " << d.physicalSizeMM.width() << 'x'
+ << d.physicalSizeMM.height() << " DPI: " << d.dpi.first << 'x' << d.dpi.second
+ << " Depth: " << d.depth << " Format: " << d.format << " hMonitor: " << d.hMonitor
+ << " device name: " << d.deviceName << " manufacturer: " << d.manufacturer
+ << " model: " << d.model << " serial number: " << d.serialNumber;
if (d.flags & QWindowsScreenData::PrimaryScreen)
dbg << " primary";
if (d.flags & QWindowsScreenData::VirtualDesktop)
@@ -171,7 +401,6 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d)
\brief Windows screen.
\sa QWindowsScreenManager
\internal
- \ingroup qt-lighthouse-win
*/
QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) :
@@ -182,7 +411,12 @@ QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) :
{
}
-Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0);
+QString QWindowsScreen::name() const
+{
+ return m_data.deviceIndex.has_value()
+ ? (u"%1 (%2)"_s).arg(m_data.name, QString::number(m_data.deviceIndex.value()))
+ : m_data.name;
+}
QPixmap QWindowsScreen::grabWindow(WId window, int xIn, int yIn, int width, int height) const
{
@@ -242,7 +476,7 @@ QWindow *QWindowsScreen::topLevelAt(const QPoint &point) const
if (QWindow *child = QWindowsScreen::windowAt(point, CWP_SKIPINVISIBLE))
result = QWindowsWindow::topLevelOf(child);
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaWindows) <<__FUNCTION__ << point << result;
+ qCDebug(lcQpaScreen) <<__FUNCTION__ << point << result;
return result;
}
@@ -253,7 +487,7 @@ QWindow *QWindowsScreen::windowAt(const QPoint &screenPoint, unsigned flags)
findPlatformWindowAt(GetDesktopWindow(), screenPoint, flags))
result = bw->window();
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaWindows) <<__FUNCTION__ << screenPoint << " returns " << result;
+ qCDebug(lcQpaScreen) <<__FUNCTION__ << screenPoint << " returns " << result;
return result;
}
@@ -289,7 +523,7 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData)
m_data.physicalSizeMM = newData.physicalSizeMM;
if (m_data.hMonitor != newData.hMonitor) {
- qCDebug(lcQpaWindows) << "Monitor" << m_data.name
+ qCDebug(lcQpaScreen) << "Monitor" << m_data.name
<< "has had its hMonitor handle changed from"
<< m_data.hMonitor << "to" << newData.hMonitor;
m_data.hMonitor = newData.hMonitor;
@@ -302,10 +536,14 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData)
const bool dpiChanged = !qFuzzyCompare(m_data.dpi.first, newData.dpi.first)
|| !qFuzzyCompare(m_data.dpi.second, newData.dpi.second);
const bool orientationChanged = m_data.orientation != newData.orientation;
+ const bool primaryChanged = (newData.flags & QWindowsScreenData::PrimaryScreen)
+ && !(m_data.flags & QWindowsScreenData::PrimaryScreen);
m_data.dpi = newData.dpi;
m_data.orientation = newData.orientation;
m_data.geometry = newData.geometry;
m_data.availableGeometry = newData.availableGeometry;
+ m_data.flags = (m_data.flags & ~QWindowsScreenData::PrimaryScreen)
+ | (newData.flags & QWindowsScreenData::PrimaryScreen);
if (dpiChanged) {
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(),
@@ -318,6 +556,8 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData)
QWindowSystemInterface::handleScreenGeometryChange(screen(),
newData.geometry, newData.availableGeometry);
}
+ if (primaryChanged)
+ QWindowSystemInterface::handlePrimaryScreenChanged(this);
}
HMONITOR QWindowsScreen::handle() const
@@ -334,62 +574,50 @@ QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScre
return result;
}
-enum OrientationPreference : DWORD // matching Win32 API ORIENTATION_PREFERENCE
-{
- orientationPreferenceNone = 0,
- orientationPreferenceLandscape = 0x1,
- orientationPreferencePortrait = 0x2,
- orientationPreferenceLandscapeFlipped = 0x4,
- orientationPreferencePortraitFlipped = 0x8
-};
-
bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
{
bool result = false;
- if (QWindowsContext::user32dll.setDisplayAutoRotationPreferences) {
- DWORD orientationPreference = 0;
- switch (o) {
- case Qt::PrimaryOrientation:
- orientationPreference = orientationPreferenceNone;
- break;
- case Qt::PortraitOrientation:
- orientationPreference = orientationPreferencePortrait;
- break;
- case Qt::LandscapeOrientation:
- orientationPreference = orientationPreferenceLandscape;
- break;
- case Qt::InvertedPortraitOrientation:
- orientationPreference = orientationPreferencePortraitFlipped;
- break;
- case Qt::InvertedLandscapeOrientation:
- orientationPreference = orientationPreferenceLandscapeFlipped;
- break;
- }
- result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences(orientationPreference);
+ ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
+ switch (o) {
+ case Qt::PrimaryOrientation:
+ break;
+ case Qt::PortraitOrientation:
+ orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT;
+ break;
+ case Qt::LandscapeOrientation:
+ orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE;
+ break;
+ case Qt::InvertedPortraitOrientation:
+ orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED;
+ break;
+ case Qt::InvertedLandscapeOrientation:
+ orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
+ break;
}
+ result = SetDisplayAutoRotationPreferences(orientationPreference);
return result;
}
Qt::ScreenOrientation QWindowsScreen::orientationPreference()
{
Qt::ScreenOrientation result = Qt::PrimaryOrientation;
- if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences) {
- DWORD orientationPreference = 0;
- if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences(&orientationPreference)) {
- switch (orientationPreference) {
- case orientationPreferenceLandscape:
- result = Qt::LandscapeOrientation;
- break;
- case orientationPreferencePortrait:
- result = Qt::PortraitOrientation;
- break;
- case orientationPreferenceLandscapeFlipped:
- result = Qt::InvertedLandscapeOrientation;
- break;
- case orientationPreferencePortraitFlipped:
- result = Qt::InvertedPortraitOrientation;
- break;
- }
+ ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
+ if (GetDisplayAutoRotationPreferences(&orientationPreference)) {
+ switch (orientationPreference) {
+ case ORIENTATION_PREFERENCE_NONE:
+ break;
+ case ORIENTATION_PREFERENCE_LANDSCAPE:
+ result = Qt::LandscapeOrientation;
+ break;
+ case ORIENTATION_PREFERENCE_PORTRAIT:
+ result = Qt::PortraitOrientation;
+ break;
+ case ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED:
+ result = Qt::InvertedLandscapeOrientation;
+ break;
+ case ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED:
+ result = Qt::InvertedPortraitOrientation;
+ break;
}
}
return result;
@@ -402,9 +630,9 @@ QPlatformScreen::SubpixelAntialiasingType QWindowsScreen::subpixelAntialiasingTy
{
QPlatformScreen::SubpixelAntialiasingType type = QPlatformScreen::subpixelAntialiasingTypeHint();
if (type == QPlatformScreen::Subpixel_None) {
- QSettings settings(QLatin1String(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Avalon.Graphics\DISPLAY1)"),
+ QSettings settings(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Avalon.Graphics\DISPLAY1)"_L1,
QSettings::NativeFormat);
- int registryValue = settings.value(QLatin1String("PixelStructure"), -1).toInt();
+ int registryValue = settings.value("PixelStructure"_L1, -1).toInt();
switch (registryValue) {
case 0:
type = QPlatformScreen::Subpixel_None;
@@ -432,55 +660,68 @@ QPlatformScreen::SubpixelAntialiasingType QWindowsScreen::subpixelAntialiasingTy
\sa QWindowsScreen
\internal
- \ingroup qt-lighthouse-win
*/
-QWindowsScreenManager::QWindowsScreenManager() = default;
+extern "C" LRESULT QT_WIN_CALLBACK qDisplayChangeObserverWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (message == WM_DISPLAYCHANGE) {
+ qCDebug(lcQpaScreen) << "Handling WM_DISPLAYCHANGE";
+ if (QWindowsTheme *t = QWindowsTheme::instance())
+ t->displayChanged();
+ QWindowsWindow::displayChanged();
+ if (auto *context = QWindowsContext::instance())
+ context->screenManager().handleScreenChanges();
+ }
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
-bool QWindowsScreenManager::isSingleScreen()
+QWindowsScreenManager::QWindowsScreenManager() = default;
+
+void QWindowsScreenManager::initialize()
{
- return QWindowsContext::instance()->screenManager().screens().size() < 2;
-}
+ qCDebug(lcQpaScreen) << "Initializing screen manager";
-/*!
- \brief Triggers synchronization of screens (WM_DISPLAYCHANGE).
+ auto className = QWindowsContext::instance()->registerWindowClass(
+ QWindowsContext::classNamePrefix() + QLatin1String("ScreenChangeObserverWindow"),
+ qDisplayChangeObserverWndProc);
- Subsequent events are compressed since WM_DISPLAYCHANGE is sent to
- each top level window.
-*/
+ // HWND_MESSAGE windows do not get WM_DISPLAYCHANGE, so we need to create
+ // a real top level window that we never show.
+ m_displayChangeObserver = CreateWindowEx(0, reinterpret_cast<LPCWSTR>(className.utf16()),
+ nullptr, WS_TILED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
+ Q_ASSERT(m_displayChangeObserver);
-bool QWindowsScreenManager::handleDisplayChange(WPARAM wParam, LPARAM lParam)
-{
- const int newDepth = int(wParam);
- const WORD newHorizontalResolution = LOWORD(lParam);
- const WORD newVerticalResolution = HIWORD(lParam);
- if (newDepth != m_lastDepth || newHorizontalResolution != m_lastHorizontalResolution
- || newVerticalResolution != m_lastVerticalResolution) {
- m_lastDepth = newDepth;
- m_lastHorizontalResolution = newHorizontalResolution;
- m_lastVerticalResolution = newVerticalResolution;
- qCDebug(lcQpaWindows) << __FUNCTION__ << "Depth=" << newDepth
- << ", resolution " << newHorizontalResolution << 'x' << newVerticalResolution;
- handleScreenChanges();
- }
- return false;
+ qCDebug(lcQpaScreen) << "Created display change observer" << m_displayChangeObserver;
+
+ handleScreenChanges();
+}
+
+QWindowsScreenManager::~QWindowsScreenManager()
+{
+ DestroyWindow(m_displayChangeObserver);
+}
+
+bool QWindowsScreenManager::isSingleScreen()
+{
+ return QWindowsContext::instance()->screenManager().screens().size() < 2;
}
static inline int indexOfMonitor(const QWindowsScreenManager::WindowsScreenList &screens,
- const QString &monitorName)
+ const QString &deviceName)
{
for (int i= 0; i < screens.size(); ++i)
- if (screens.at(i)->data().name == monitorName)
+ if (screens.at(i)->data().deviceName == deviceName)
return i;
return -1;
}
static inline int indexOfMonitor(const WindowsScreenDataList &screenData,
- const QString &monitorName)
+ const QString &deviceName)
{
for (int i = 0; i < screenData.size(); ++i)
- if (screenData.at(i).name == monitorName)
+ if (screenData.at(i).deviceName == deviceName)
return i;
return -1;
}
@@ -504,7 +745,7 @@ static void moveToVirtualScreen(QWindow *w, const QScreen *newScreen)
void QWindowsScreenManager::removeScreen(int index)
{
- qCDebug(lcQpaWindows) << "Removing Monitor:" << m_screens.at(index)->data();
+ qCDebug(lcQpaScreen) << "Removing Monitor:" << m_screens.at(index)->data();
QScreen *screen = m_screens.at(index)->screen();
QScreen *primaryScreen = QGuiApplication::primaryScreen();
// QTBUG-38650: When a screen is disconnected, Windows will automatically
@@ -546,7 +787,7 @@ bool QWindowsScreenManager::handleScreenChanges()
const bool lockScreen = newDataList.size() == 1 && (newDataList.front().flags & QWindowsScreenData::LockScreen);
bool primaryScreenChanged = false;
for (const QWindowsScreenData &newData : newDataList) {
- const int existingIndex = indexOfMonitor(m_screens, newData.name);
+ const int existingIndex = indexOfMonitor(m_screens, newData.deviceName);
if (existingIndex != -1) {
m_screens.at(existingIndex)->handleChanges(newData);
if (existingIndex == 0)
@@ -556,19 +797,21 @@ bool QWindowsScreenManager::handleScreenChanges()
m_screens.push_back(newScreen);
QWindowSystemInterface::handleScreenAdded(newScreen,
newData.flags & QWindowsScreenData::PrimaryScreen);
- qCDebug(lcQpaWindows) << "New Monitor: " << newData;
+ qCDebug(lcQpaScreen) << "New Monitor: " << newData;
} // exists
} // for new screens.
// Remove deleted ones but keep main monitors if we get only the
// temporary lock screen to avoid window recreation (QTBUG-33062).
if (!lockScreen) {
for (int i = m_screens.size() - 1; i >= 0; --i) {
- if (indexOfMonitor(newDataList, m_screens.at(i)->data().name) == -1)
+ if (indexOfMonitor(newDataList, m_screens.at(i)->data().deviceName) == -1)
removeScreen(i);
} // for existing screens
} // not lock screen
- if (primaryScreenChanged)
- QWindowsTheme::instance()->refreshFonts();
+ if (primaryScreenChanged) {
+ if (auto theme = QWindowsTheme::instance()) // QTBUG-85734/Wine
+ theme->refreshFonts();
+ }
return true;
}
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 5c095808f2..0467ab2a0c 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSSCREEN_H
#define QWINDOWSSCREEN_H
@@ -43,10 +7,9 @@
#include "qtwindowsglobal.h"
#include <QtCore/qlist.h>
-#include <QtCore/qvector.h>
-#include <QtCore/qpair.h>
#include <QtCore/qscopedpointer.h>
#include <qpa/qplatformscreen.h>
+#include <QtGui/qscreen_platform.h>
QT_BEGIN_NAMESPACE
@@ -67,12 +30,18 @@ struct QWindowsScreenData
QImage::Format format = QImage::Format_ARGB32_Premultiplied;
unsigned flags = VirtualDesktop;
QString name;
+ QString manufacturer;
+ QString model;
+ QString serialNumber;
Qt::ScreenOrientation orientation = Qt::LandscapeOrientation;
qreal refreshRateHz = 60;
HMONITOR hMonitor = nullptr;
+ QString deviceName;
+ QString devicePath;
+ std::optional<int> deviceIndex = std::nullopt;
};
-class QWindowsScreen : public QPlatformScreen
+class QWindowsScreen : public QPlatformScreen, public QNativeInterface::QWindowsScreen
{
public:
#ifndef QT_NO_CURSOR
@@ -87,10 +56,13 @@ public:
QImage::Format format() const override { return m_data.format; }
QSizeF physicalSize() const override { return m_data.physicalSizeMM; }
QDpi logicalDpi() const override { return m_data.dpi; }
- QDpi logicalBaseDpi() const override { return QDpi(96, 96); };
+ QDpi logicalBaseDpi() const override { return QDpi(baseDpi, baseDpi); }
qreal devicePixelRatio() const override { return 1.0; }
qreal refreshRate() const override { return m_data.refreshRateHz; }
- QString name() const override { return m_data.name; }
+ QString name() const override;
+ QString manufacturer() const override { return m_data.manufacturer; }
+ QString model() const override { return m_data.model; }
+ QString serialNumber() const override { return m_data.serialNumber; }
Qt::ScreenOrientation orientation() const override { return m_data.orientation; }
QList<QPlatformScreen *> virtualSiblings() const override;
QWindow *topLevelAt(const QPoint &point) const override;
@@ -104,7 +76,7 @@ public:
inline void handleChanges(const QWindowsScreenData &newData);
- HMONITOR handle() const;
+ HMONITOR handle() const override;
#ifndef QT_NO_CURSOR
QPlatformCursor *cursor() const override { return m_cursor.data(); }
@@ -116,6 +88,7 @@ public:
const QWindowsScreenData &data() const { return m_data; }
static QRect virtualGeometry(const QPlatformScreen *screen);
+ static inline int baseDpi = 96;
private:
QWindowsScreenData m_data;
@@ -126,15 +99,17 @@ private:
class QWindowsScreenManager
{
+ Q_DISABLE_COPY_MOVE(QWindowsScreenManager)
public:
- using WindowsScreenList = QVector<QWindowsScreen *>;
+ using WindowsScreenList = QList<QWindowsScreen *>;
QWindowsScreenManager();
+ void initialize();
+ ~QWindowsScreenManager();
void clearScreens();
bool handleScreenChanges();
- bool handleDisplayChange(WPARAM wParam, LPARAM lParam);
const WindowsScreenList &screens() const { return m_screens; }
const QWindowsScreen *screenAtDp(const QPoint &p) const;
@@ -145,10 +120,8 @@ public:
private:
void removeScreen(int index);
+ HWND m_displayChangeObserver = nullptr;
WindowsScreenList m_screens;
- int m_lastDepth = -1;
- WORD m_lastHorizontalResolution = 0;
- WORD m_lastVerticalResolution = 0;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp
index 83b052bb49..89f93fd161 100644
--- a/src/plugins/platforms/windows/qwindowsservices.cpp
+++ b/src/plugins/platforms/windows/qwindowsservices.cpp
@@ -1,71 +1,118 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
-
-#define QT_NO_URL_CAST_FROM_STRING
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
#include "qwindowsservices.h"
#include <QtCore/qt_windows.h>
#include <QtCore/qurl.h>
#include <QtCore/qdebug.h>
#include <QtCore/qdir.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qthread.h>
#include <QtCore/private/qwinregistry_p.h>
+#include <QtCore/private/qfunctions_win_p.h>
#include <shlobj.h>
+#include <shlwapi.h>
#include <intshcut.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
enum { debug = 0 };
+class QWindowsShellExecuteThread : public QThread
+{
+public:
+ explicit QWindowsShellExecuteThread(const wchar_t *operation, const wchar_t *file,
+ const wchar_t *parameters)
+ : m_operation(operation)
+ , m_file(file)
+ , m_parameters(parameters) { }
+
+ void run() override
+ {
+ QComHelper comHelper;
+ if (comHelper.isValid())
+ m_result = ShellExecute(nullptr, m_operation, m_file, m_parameters, nullptr,
+ SW_SHOWNORMAL);
+ }
+
+ HINSTANCE result() const { return m_result; }
+
+private:
+ HINSTANCE m_result = nullptr;
+ const wchar_t *m_operation;
+ const wchar_t *m_file;
+ const wchar_t *m_parameters;
+};
+
+static QString msgShellExecuteFailed(const QUrl &url, quintptr code)
+{
+ QString result;
+ QTextStream(&result) <<"ShellExecute '" << url.toString() << "' failed (error " << code << ").";
+ return result;
+}
+
+// Retrieve the web browser and open the URL. This should be used for URLs with
+// fragments which don't work when using ShellExecute() directly (QTBUG-14460,
+// QTBUG-55300).
+static bool openWebBrowser(const QUrl &url)
+{
+ WCHAR browserExecutable[MAX_PATH] = {};
+ const wchar_t operation[] = L"open";
+ DWORD browserExecutableSize = MAX_PATH;
+ if (FAILED(AssocQueryString(0, ASSOCSTR_EXECUTABLE, L"http", operation,
+ browserExecutable, &browserExecutableSize))) {
+ return false;
+ }
+ QString browser = QString::fromWCharArray(browserExecutable, browserExecutableSize - 1);
+ // Workaround for "old" MS Edge entries. Instead of LaunchWinApp.exe we can just use msedge.exe
+ if (browser.contains("LaunchWinApp.exe"_L1, Qt::CaseInsensitive))
+ browser = "msedge.exe"_L1;
+ const QString urlS = url.toString(QUrl::FullyEncoded);
+
+ // Run ShellExecute() in a thread since it may spin the event loop.
+ // Prevent it from interfering with processing of posted events (QTBUG-85676).
+ QWindowsShellExecuteThread thread(operation,
+ reinterpret_cast<const wchar_t *>(browser.utf16()),
+ reinterpret_cast<const wchar_t *>(urlS.utf16()));
+ thread.start();
+ thread.wait();
+
+ const auto result = reinterpret_cast<quintptr>(thread.result());
+ if (debug)
+ qDebug() << __FUNCTION__ << urlS << QString::fromWCharArray(browserExecutable) << result;
+ // ShellExecute returns a value greater than 32 if successful
+ if (result <= 32) {
+ qWarning("%s", qPrintable(msgShellExecuteFailed(url, result)));
+ return false;
+ }
+ return true;
+}
+
static inline bool shellExecute(const QUrl &url)
{
const QString nativeFilePath = url.isLocalFile() && !url.hasFragment() && !url.hasQuery()
? QDir::toNativeSeparators(url.toLocalFile())
: url.toString(QUrl::FullyEncoded);
- const auto result =
- reinterpret_cast<quintptr>(ShellExecute(nullptr, nullptr,
- reinterpret_cast<const wchar_t *>(nativeFilePath.utf16()),
- nullptr, nullptr, SW_SHOWNORMAL));
+
+
+ // Run ShellExecute() in a thread since it may spin the event loop.
+ // Prevent it from interfering with processing of posted events (QTBUG-85676).
+ QWindowsShellExecuteThread thread(nullptr,
+ reinterpret_cast<const wchar_t *>(nativeFilePath.utf16()),
+ nullptr);
+ thread.start();
+ thread.wait();
+
+ const auto result = reinterpret_cast<quintptr>(thread.result());
+
// ShellExecute returns a value greater than 32 if successful
if (result <= 32) {
- qWarning("ShellExecute '%s' failed (error %s).", qPrintable(url.toString()), qPrintable(QString::number(result)));
+ qWarning("%s", qPrintable(msgShellExecuteFailed(url, result)));
return false;
}
return true;
@@ -83,16 +130,16 @@ static inline QString mailCommand()
// Check if user has set preference, otherwise use default.
QString keyName = QWinRegistryKey(HKEY_CURRENT_USER, mailUserKey)
.stringValue( L"Progid");
- const QLatin1String mailto = keyName.isEmpty() ? QLatin1String("mailto") : QLatin1String();
- keyName += mailto + QLatin1String("\\Shell\\Open\\Command");
+ const auto mailto = keyName.isEmpty() ? "mailto"_L1 : QLatin1StringView();
+ keyName += mailto + "\\Shell\\Open\\Command"_L1;
if (debug)
qDebug() << __FUNCTION__ << "keyName=" << keyName;
const QString command = QWinRegistryKey(HKEY_CLASSES_ROOT, keyName).stringValue(L"");
// QTBUG-57816: As of Windows 10, if there is no mail client installed, an entry like
// "rundll32.exe .. url.dll,MailToProtocolHandler %l" is returned. Launching it
// silently fails or brings up a broken dialog after a long time, so exclude it and
- // fall back to ShellExecute() which brings up the URL assocation dialog.
- if (command.isEmpty() || command.contains(QLatin1String(",MailToProtocolHandler")))
+ // fall back to ShellExecute() which brings up the URL association dialog.
+ if (command.isEmpty() || command.contains(u",MailToProtocolHandler"))
return QString();
wchar_t expandedCommand[MAX_PATH] = {0};
return ExpandEnvironmentStrings(reinterpret_cast<const wchar_t *>(command.utf16()),
@@ -104,13 +151,18 @@ static inline bool launchMail(const QUrl &url)
{
QString command = mailCommand();
if (command.isEmpty()) {
- qWarning("Cannot launch '%s': There is no mail program installed.", qPrintable(url.toString()));
+ qWarning("Cannot launch '%ls': There is no mail program installed.", qUtf16Printable(url.toString()));
+ return false;
+ }
+ // Fix mail launch if no param is expected in this command.
+ if (command.indexOf("%1"_L1) < 0) {
+ qWarning() << "The mail command lacks the '%1' parameter.";
return false;
}
//Make sure the path for the process is in quotes
- const QChar doubleQuote = QLatin1Char('"');
+ const QChar doubleQuote = u'"';
if (!command.startsWith(doubleQuote)) {
- const int exeIndex = command.indexOf(QStringLiteral(".exe "), 0, Qt::CaseInsensitive);
+ const int exeIndex = command.indexOf(".exe "_L1, 0, Qt::CaseInsensitive);
if (exeIndex != -1) {
command.insert(exeIndex + 4, doubleQuote);
command.prepend(doubleQuote);
@@ -118,7 +170,7 @@ static inline bool launchMail(const QUrl &url)
}
// Pass the url as the parameter. Should use QProcess::startDetached(),
// but that cannot handle a Windows command line [yet].
- command.replace(QLatin1String("%1"), url.toString(QUrl::FullyEncoded));
+ command.replace("%1"_L1, url.toString(QUrl::FullyEncoded));
if (debug)
qDebug() << __FUNCTION__ << "Launching" << command;
//start the process
@@ -129,7 +181,7 @@ static inline bool launchMail(const QUrl &url)
si.cb = sizeof(si);
if (!CreateProcess(nullptr, reinterpret_cast<wchar_t *>(const_cast<ushort *>(command.utf16())),
nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi)) {
- qErrnoWarning("Unable to launch '%s'", qPrintable(command));
+ qErrnoWarning("Unable to launch '%ls'", qUtf16Printable(command));
return false;
}
CloseHandle(pi.hProcess);
@@ -140,9 +192,10 @@ static inline bool launchMail(const QUrl &url)
bool QWindowsServices::openUrl(const QUrl &url)
{
const QString scheme = url.scheme();
- if (scheme == QLatin1String("mailto") && launchMail(url))
+ if (scheme == u"mailto" && launchMail(url))
return true;
- return shellExecute(url);
+ return url.isLocalFile() && url.hasFragment()
+ ? openWebBrowser(url) : shellExecute(url);
}
bool QWindowsServices::openDocument(const QUrl &url)
diff --git a/src/plugins/platforms/windows/qwindowsservices.h b/src/plugins/platforms/windows/qwindowsservices.h
index 5feb7c8490..56279f57fc 100644
--- a/src/plugins/platforms/windows/qwindowsservices.h
+++ b/src/plugins/platforms/windows/qwindowsservices.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSDESKTOPSERVICES_H
#define QWINDOWSDESKTOPSERVICES_H
diff --git a/src/plugins/platforms/windows/qwindowssessionmanager.cpp b/src/plugins/platforms/windows/qwindowssessionmanager.cpp
index 500fdc750c..487ebeba65 100644
--- a/src/plugins/platforms/windows/qwindowssessionmanager.cpp
+++ b/src/plugins/platforms/windows/qwindowssessionmanager.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowssessionmanager.h"
diff --git a/src/plugins/platforms/windows/qwindowssessionmanager.h b/src/plugins/platforms/windows/qwindowssessionmanager.h
index 0769ed1fce..320c1aedee 100644
--- a/src/plugins/platforms/windows/qwindowssessionmanager.h
+++ b/src/plugins/platforms/windows/qwindowssessionmanager.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSSESSIONMANAGER_H
#define QWINDOWSSESSIONMANAGER_H
diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
index f2dba4d06b..6f0680ac23 100644
--- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
+++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
@@ -1,55 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
-
-#if defined(WINVER) && WINVER < 0x0601
-# undef WINVER
-#endif
-#if !defined(WINVER)
-# define WINVER 0x0601 // required for NOTIFYICONDATA_V2_SIZE, ChangeWindowMessageFilterEx() (MinGW 5.3)
-#endif
-
-#if defined(NTDDI_VERSION) && NTDDI_VERSION < 0x06010000
-# undef NTDDI_VERSION
-#endif
-#if !defined(NTDDI_VERSION)
-# define NTDDI_VERSION 0x06010000 // required for Shell_NotifyIconGetRect (MinGW 5.3)
-#endif
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qt_windows.h>
#include "qwindowssystemtrayicon.h"
#include "qwindowscontext.h"
@@ -57,13 +9,14 @@
#include "qwindowsmenu.h"
#include "qwindowsscreen.h"
+#include <QtGui/qguiapplication.h>
#include <QtGui/qpixmap.h>
#include <QtCore/qdebug.h>
+#include <QtCore/qlist.h>
#include <QtCore/qrect.h>
-#include <QtCore/qvector.h>
#include <QtCore/qsettings.h>
+#include <qpa/qwindowsysteminterface.h>
-#include <qt_windows.h>
#include <commctrl.h>
#include <shellapi.h>
#include <shlobj.h>
@@ -71,6 +24,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::Literals::StringLiterals;
+
static const UINT q_uNOTIFYICONID = 0;
static uint MYWM_TASKBARCREATED = 0;
@@ -117,7 +72,7 @@ struct QWindowsHwndSystemTrayIconEntry
QWindowsSystemTrayIcon *trayIcon;
};
-using HwndTrayIconEntries = QVector<QWindowsHwndSystemTrayIconEntry>;
+using HwndTrayIconEntries = QList<QWindowsHwndSystemTrayIconEntry>;
Q_GLOBAL_STATIC(HwndTrayIconEntries, hwndTrayIconEntries)
@@ -136,7 +91,7 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsTrayIconWndProc(HWND hwnd, UINT messa
{
if (message == MYWM_TASKBARCREATED || message == MYWM_NOTIFYICON
|| message == WM_INITMENU || message == WM_INITMENUPOPUP
- || message == WM_COMMAND) {
+ || message == WM_CLOSE || message == WM_COMMAND) {
const int index = indexOfHwnd(hwnd);
if (index >= 0) {
MSG msg;
@@ -163,7 +118,7 @@ static inline HWND createTrayIconMessageWindow()
return nullptr;
// Register window class in the platform plugin.
const QString className =
- ctx->registerWindowClass(QStringLiteral("QTrayIconMessageWindowClass"),
+ ctx->registerWindowClass(QWindowsContext::classNamePrefix() + "TrayIconMessageWindowClass"_L1,
qWindowsTrayIconWndProc);
const wchar_t windowName[] = L"QTrayIconMessageWindow";
return CreateWindowEx(0, reinterpret_cast<const wchar_t *>(className.utf16()),
@@ -179,7 +134,6 @@ static inline HWND createTrayIconMessageWindow()
\brief Windows native system tray icon
\internal
- \ingroup qt-lighthouse-win
*/
QWindowsSystemTrayIcon::QWindowsSystemTrayIcon()
@@ -210,8 +164,7 @@ void QWindowsSystemTrayIcon::cleanup()
void QWindowsSystemTrayIcon::updateIcon(const QIcon &icon)
{
qCDebug(lcQpaTrayIcon) << __FUNCTION__ << '(' << icon << ')' << this;
- if (icon.cacheKey() == m_icon.cacheKey())
- return;
+ m_icon = icon;
const HICON hIconToDestroy = createIcon(icon);
if (ensureInstalled())
sendTrayMessage(NIM_MODIFY);
@@ -231,6 +184,9 @@ void QWindowsSystemTrayIcon::updateToolTip(const QString &tooltip)
QRect QWindowsSystemTrayIcon::geometry() const
{
+ if (!isIconVisible())
+ return QRect();
+
NOTIFYICONIDENTIFIER nid;
memset(&nid, 0, sizeof(nid));
nid.cbSize = sizeof(nid);
@@ -256,7 +212,7 @@ void QWindowsSystemTrayIcon::showMessage(const QString &title, const QString &me
// For empty messages, ensures that they show when only title is set
QString message = messageIn;
if (message.isEmpty() && !title.isEmpty())
- message.append(QLatin1Char(' '));
+ message.append(u' ');
NOTIFYICONDATA tnd;
initNotifyIconData(tnd);
@@ -264,25 +220,19 @@ void QWindowsSystemTrayIcon::showMessage(const QString &title, const QString &me
qStringToLimitedWCharArray(title, tnd.szInfoTitle, 64);
tnd.uID = q_uNOTIFYICONID;
- tnd.dwInfoFlags = NIIF_USER;
-
- QSize size(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
- const QSize largeIcon(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
- const QSize more = icon.actualSize(largeIcon);
- if (more.height() > (largeIcon.height() * 3/4) || more.width() > (largeIcon.width() * 3/4)) {
- tnd.dwInfoFlags |= NIIF_LARGE_ICON;
- size = largeIcon;
- }
+
+ const auto size = icon.actualSize(QSize(256, 256));
QPixmap pm = icon.pixmap(size);
+ if (m_hMessageIcon) {
+ DestroyIcon(m_hMessageIcon);
+ m_hMessageIcon = nullptr;
+ }
if (pm.isNull()) {
tnd.dwInfoFlags = NIIF_INFO;
} else {
- if (pm.size() != size) {
- qWarning("QSystemTrayIcon::showMessage: Wrong icon size (%dx%d), please add standard one: %dx%d",
- pm.size().width(), pm.size().height(), size.width(), size.height());
- pm = pm.scaled(size, Qt::IgnoreAspectRatio);
- }
- tnd.hBalloonIcon = qt_pixmapToWinHICON(pm);
+ tnd.dwInfoFlags = NIIF_USER | NIIF_LARGE_ICON;
+ m_hMessageIcon = qt_pixmapToWinHICON(pm);
+ tnd.hBalloonIcon = m_hMessageIcon;
}
tnd.hWnd = m_hwnd;
tnd.uTimeout = msecsIn <= 0 ? UINT(10000) : UINT(msecsIn); // 10s default
@@ -340,7 +290,10 @@ void QWindowsSystemTrayIcon::ensureCleanup()
}
if (m_hIcon != nullptr)
DestroyIcon(m_hIcon);
+ if (m_hMessageIcon != nullptr)
+ DestroyIcon(m_hMessageIcon);
m_hIcon = nullptr;
+ m_hMessageIcon = nullptr;
m_menu = nullptr; // externally owned
m_toolTip.clear();
}
@@ -357,6 +310,29 @@ bool QWindowsSystemTrayIcon::setIconVisible(bool visible)
return Shell_NotifyIcon(NIM_MODIFY, &tnd) == TRUE;
}
+bool QWindowsSystemTrayIcon::isIconVisible() const
+{
+ NOTIFYICONIDENTIFIER nid;
+ memset(&nid, 0, sizeof(nid));
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = m_hwnd;
+ nid.uID = q_uNOTIFYICONID;
+ RECT rect;
+ const HRESULT hr = Shell_NotifyIconGetRect(&nid, &rect);
+ // Windows 10 returns S_FALSE if the icon is hidden
+ if (FAILED(hr) || hr == S_FALSE)
+ return false;
+
+ HMONITOR monitor = MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST);
+ MONITORINFO info;
+ info.cbSize = sizeof(MONITORINFO);
+ GetMonitorInfo(monitor, &info);
+ // Windows 11 seems to return a geometry outside of the current monitor's geometry in case of
+ // the icon being hidden. As it's impossible to change the alignment of the task bar on Windows
+ // 11 this check should be fine.
+ return rect.bottom <= info.rcMonitor.bottom;
+}
+
bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg)
{
NOTIFYICONDATA tnd;
@@ -419,8 +395,12 @@ bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result)
if (screen) {
emit contextMenuRequested(globalPos, screen);
emit activated(Context);
- if (m_menu)
+ if (m_menu) {
+ // Set the foreground window to the controlling window so that clicking outside
+ // of the menu or window will cause the menu to close
+ SetForegroundWindow(m_hwnd);
m_menu->trackPopupMenu(message.hwnd, globalPos.x(), globalPos.y());
+ }
}
}
break;
@@ -439,12 +419,22 @@ bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result)
case WM_INITMENUPOPUP:
QWindowsPopupMenu::notifyAboutToShow(reinterpret_cast<HMENU>(message.wParam));
break;
+ case WM_CLOSE:
+ QWindowSystemInterface::handleApplicationTermination<QWindowSystemInterface::SynchronousDelivery>();
+ break;
case WM_COMMAND:
QWindowsPopupMenu::notifyTriggered(LOWORD(message.wParam));
break;
default:
- if (message.message == MYWM_TASKBARCREATED) // self-registered message id (tray crashed)
+ if (message.message == MYWM_TASKBARCREATED) {
+ // self-registered message id to handle that
+ // - screen resolution/DPR changed
+ const QIcon oldIcon = m_icon;
+ m_icon = QIcon(); // updateIcon is a no-op if the icon doesn't change
+ updateIcon(oldIcon);
+ // - or tray crashed
sendTrayMessage(NIM_ADD);
+ }
break;
}
return false;
diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.h b/src/plugins/platforms/windows/qwindowssystemtrayicon.h
index 44e1bcc761..3ad5feb125 100644
--- a/src/plugins/platforms/windows/qwindowssystemtrayicon.h
+++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSSYSTEMTRAYICON_H
#define QWINDOWSSYSTEMTRAYICON_H
@@ -85,12 +49,14 @@ private:
void ensureCleanup();
bool sendTrayMessage(DWORD msg);
bool setIconVisible(bool visible);
+ bool isIconVisible() const;
HICON createIcon(const QIcon &icon);
QIcon m_icon;
QString m_toolTip;
HWND m_hwnd = nullptr;
HICON m_hIcon = nullptr;
+ HICON m_hMessageIcon = nullptr;
mutable QPointer<QWindowsPopupMenu> m_menu;
bool m_ignoreNextMouseRelease = false;
bool m_visible = false;
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
index cd5a78abb6..ceebb483d2 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowstabletsupport.h"
@@ -133,11 +97,10 @@ QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t)
{
QDebugStateSaver saver(d);
d.nospace();
- d << "TabletDevice id:" << t.uniqueId << " pressure: " << t.minPressure
+ d << "TabletDevice id:" << t.systemId << " pressure: " << t.minPressure
<< ".." << t.maxPressure << " tan pressure: " << t.minTanPressure << ".."
<< t.maxTanPressure << " area: (" << t.minX << ',' << t.minY << ',' << t.minZ
- << ")..(" << t.maxX << ',' << t.maxY << ',' << t.maxZ << ") device "
- << t.currentDevice << " pointer " << t.currentPointerType;
+ << ")..(" << t.maxX << ',' << t.maxY << ',' << t.maxZ << ')';
return d;
}
@@ -166,6 +129,48 @@ QDebug operator<<(QDebug d, const LOGCONTEXT &lc)
}
#endif // !QT_NO_DEBUG_STREAM
+QWinTabPointingDevice *createInputDevice(const QSharedPointer<QWindowsTabletDeviceData> &d,
+ QInputDevice::DeviceType devType,
+ QPointingDevice::PointerType pointerType)
+{
+ const qint64 uniqueId = d->systemId | (qint64(devType) << 32)
+ | (qint64(pointerType) << 48L);
+ QInputDevice::Capabilities caps(QInputDevice::Capability::Position
+ | QInputDevice::Capability::Pressure
+ | QInputDevice::Capability::MouseEmulation
+ | QInputDevice::Capability::Hover);
+ if (d->zCapability)
+ caps |= QInputDevice::Capability::ZPosition;
+ if (d->tiltCapability) {
+ caps |= QInputDevice::Capability::XTilt
+ | QInputDevice::Capability::YTilt
+ | QInputDevice::Capability::Rotation
+ | QInputDevice::Capability::TangentialPressure;
+ }
+
+ auto result = new QWinTabPointingDevice(d, QStringLiteral("wintab"), d->systemId,
+ devType, pointerType, caps, 1,
+ d->buttonsMap.size(), QString(),
+ QPointingDeviceUniqueId::fromNumericId(uniqueId));
+ QWindowSystemInterface::registerInputDevice(result);
+ return result;
+}
+
+QWinTabPointingDevice::QWinTabPointingDevice(const QWinTabPointingDevice::DeviceDataPtr &data,
+ const QString &name, qint64 systemId,
+ QInputDevice::DeviceType devType,
+ QPointingDevice::PointerType pType,
+ QInputDevice::Capabilities caps,
+ int maxPoints, int buttonCount,
+ const QString &seatName,
+ QPointingDeviceUniqueId uniqueId,
+ QObject *parent)
+ : QPointingDevice(name, systemId, devType, pType, caps, maxPoints, buttonCount,
+ seatName, uniqueId, parent),
+ m_deviceData(data)
+{
+}
+
QWindowsWinTab32DLL QWindowsTabletSupport::m_winTab32DLL;
/*!
@@ -173,7 +178,6 @@ QWindowsWinTab32DLL QWindowsTabletSupport::m_winTab32DLL;
\brief Functions from wintabl32.dll shipped with WACOM tablets used by QWindowsTabletSupport.
\internal
- \ingroup qt-lighthouse-win
*/
bool QWindowsWinTab32DLL::init()
@@ -205,9 +209,10 @@ bool QWindowsWinTab32DLL::init()
\internal
\since 5.2
- \ingroup qt-lighthouse-win
*/
+int QWindowsTabletSupport::m_absoluteRange = 20;
+
QWindowsTabletSupport::QWindowsTabletSupport(HWND window, HCTX context)
: m_window(window)
, m_context(context)
@@ -320,56 +325,103 @@ void QWindowsTabletSupport::notifyActivate()
qCDebug(lcQpaTablet) << __FUNCTION__ << result;
}
-static inline int indexOfDevice(const QVector<QWindowsTabletDeviceData> &devices, qint64 uniqueId)
-{
- for (int i = 0; i < devices.size(); ++i)
- if (devices.at(i).uniqueId == uniqueId)
- return i;
- return -1;
-}
-
-static inline QTabletEvent::TabletDevice deviceType(const UINT cursorType)
+static inline QInputDevice::DeviceType deviceType(const UINT cursorType)
{
if (((cursorType & 0x0006) == 0x0002) && ((cursorType & CursorTypeBitMask) != 0x0902))
- return QTabletEvent::Stylus;
+ return QInputDevice::DeviceType::Stylus;
if (cursorType == 0x4020) // Surface Pro 2 tablet device
- return QTabletEvent::Stylus;
+ return QInputDevice::DeviceType::Stylus;
switch (cursorType & CursorTypeBitMask) {
case 0x0802:
- return QTabletEvent::Stylus;
+ return QInputDevice::DeviceType::Stylus;
case 0x0902:
- return QTabletEvent::Airbrush;
+ return QInputDevice::DeviceType::Airbrush;
case 0x0004:
- return QTabletEvent::FourDMouse;
+ return QInputDevice::DeviceType::Mouse;
case 0x0006:
- return QTabletEvent::Puck;
+ return QInputDevice::DeviceType::Puck;
case 0x0804:
- return QTabletEvent::RotationStylus;
+ return QInputDevice::DeviceType::Stylus;
default:
break;
}
- return QTabletEvent::NoDevice;
+ return QInputDevice::DeviceType::Unknown;
}
-static inline QTabletEvent::PointerType pointerType(unsigned currentCursor)
+static inline QPointingDevice::PointerType pointerType(unsigned currentCursor)
{
switch (currentCursor % 3) { // %3 for dual track
case 0:
- return QTabletEvent::Cursor;
+ return QPointingDevice::PointerType::Cursor;
case 1:
- return QTabletEvent::Pen;
+ return QPointingDevice::PointerType::Pen;
case 2:
- return QTabletEvent::Eraser;
+ return QPointingDevice::PointerType::Eraser;
default:
break;
}
- return QTabletEvent::UnknownPointer;
+ return QPointingDevice::PointerType::Unknown;
}
-QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(qint64 uniqueId, UINT cursorType) const
+inline void QWindowsTabletSupport::enterProximity(ulong time, QWindow *window)
+{
+ enterLeaveProximity(true, time, window);
+}
+
+inline void QWindowsTabletSupport::leaveProximity(ulong time, QWindow *window)
+{
+ enterLeaveProximity(false, time, window);
+}
+
+void QWindowsTabletSupport::enterLeaveProximity(bool enter, ulong time, QWindow *window)
+{
+ Q_ASSERT(!m_currentDevice.isNull());
+ if (time == 0) // Some leave events do not have a time associated
+ ++m_eventTime;
+ else
+ m_eventTime = time;
+ QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(window, m_eventTime,
+ m_currentDevice.data(),
+ enter);
+}
+
+QWindowsTabletSupport::DevicePtr QWindowsTabletSupport::findDevice(qint64 systemId) const
+{
+ for (const auto &d : m_devices) {
+ if (d->deviceData()->systemId == systemId)
+ return d;
+ }
+ return {};
+}
+
+QWindowsTabletSupport::DevicePtr QWindowsTabletSupport::findDevice(qint64 systemId,
+ QInputDevice::DeviceType deviceType,
+ QPointingDevice::PointerType pointerType) const
+{
+ for (const auto &d : m_devices) {
+ if (d->deviceData()->systemId == systemId && d->type() == deviceType
+ && d->pointerType() == pointerType) {
+ return d;
+ }
+ }
+ return {};
+}
+
+// Clone a device for a new pointer type.
+QWindowsTabletSupport::DevicePtr QWindowsTabletSupport::clonePhysicalDevice(qint64 systemId,
+ QInputDevice::DeviceType deviceType,
+ QPointingDevice::PointerType pointerType)
+{
+ auto similar = findDevice(systemId);
+ if (similar.isNull())
+ return {};
+ DevicePtr result(createInputDevice(similar->deviceData(), deviceType, pointerType));
+ m_devices.append(result);
+ return result;
+}
+
+void QWindowsTabletSupport::updateData(QWindowsTabletDeviceData *data) const
{
- QWindowsTabletDeviceData result;
- result.uniqueId = uniqueId;
/* browse WinTab's many info items to discover pressure handling. */
AXIS axis;
LOGCONTEXT lc;
@@ -377,21 +429,40 @@ QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(qint64 uniqueId, UINT
QWindowsTabletSupport::m_winTab32DLL.wTGet(m_context, &lc);
/* get the size of the pressure axis. */
QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_DEVICES + lc.lcDevice, DVC_NPRESSURE, &axis);
- result.minPressure = int(axis.axMin);
- result.maxPressure = int(axis.axMax);
+ data->minPressure = int(axis.axMin);
+ data->maxPressure = int(axis.axMax);
QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_DEVICES + lc.lcDevice, DVC_TPRESSURE, &axis);
- result.minTanPressure = int(axis.axMin);
- result.maxTanPressure = int(axis.axMax);
+ data->minTanPressure = int(axis.axMin);
+ data->maxTanPressure = int(axis.axMax);
LOGCONTEXT defaultLc;
/* get default region */
QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_DEFCONTEXT, 0, &defaultLc);
- result.maxX = int(defaultLc.lcInExtX) - int(defaultLc.lcInOrgX);
- result.maxY = int(defaultLc.lcInExtY) - int(defaultLc.lcInOrgY);
- result.maxZ = int(defaultLc.lcInExtZ) - int(defaultLc.lcInOrgZ);
- result.currentDevice = deviceType(cursorType);
- return result;
+ data->maxX = int(defaultLc.lcInExtX) - int(defaultLc.lcInOrgX);
+ data->maxY = int(defaultLc.lcInExtY) - int(defaultLc.lcInOrgY);
+ data->maxZ = int(defaultLc.lcInExtZ) - int(defaultLc.lcInOrgZ);
+}
+
+void QWindowsTabletSupport::updateButtons(unsigned currentCursor, QWindowsTabletDeviceData *data) const
+{
+ // We should check button map for changes on every proximity event, not
+ // only during initialization phase.
+ // WARNING: in 2016 there were some Wacom tablet drivers, which could mess up
+ // button mapping if the remapped button was pressed, while the
+ // application **didn't have input focus**. This bug is somehow
+ // related to the fact that Wacom drivers allow user to configure
+ // per-application button-mappings. If the bug shows up again,
+ // just move this button-map fetching into initialization block.
+ //
+ // See https://bugs.kde.org/show_bug.cgi?id=359561
+ BYTE logicalButtons[32];
+ memset(logicalButtons, 0, 32);
+ m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_SYSBTNMAP, &logicalButtons);
+ data->buttonsMap.clear();
+ data->buttonsMap[0x1] = logicalButtons[0];
+ data->buttonsMap[0x2] = logicalButtons[1];
+ data->buttonsMap[0x4] = logicalButtons[2];
}
bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, LPARAM lParam)
@@ -400,21 +471,11 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L
const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer);
if (!LOWORD(lParam)) {
- qCDebug(lcQpaTablet) << "leave proximity for device #" << m_currentDevice;
- if (m_currentDevice < 0 || m_currentDevice >= m_devices.size()) // QTBUG-65120, spurious leave observed
+ if (m_currentDevice.isNull()) // QTBUG-65120, spurious leave observed
return false;
+ qCDebug(lcQpaTablet) << "leave proximity for device #" << m_currentDevice.data();
m_state = PenUp;
- if (totalPacks > 0) {
- QWindowSystemInterface::handleTabletLeaveProximityEvent(proximityBuffer[0].pkTime,
- m_devices.at(m_currentDevice).currentDevice,
- m_devices.at(m_currentDevice).currentPointerType,
- m_devices.at(m_currentDevice).uniqueId);
- } else {
- QWindowSystemInterface::handleTabletLeaveProximityEvent(m_devices.at(m_currentDevice).currentDevice,
- m_devices.at(m_currentDevice).currentPointerType,
- m_devices.at(m_currentDevice).uniqueId);
-
- }
+ leaveProximity(totalPacks > 0 ? proximityBuffer[0].pkTime : 0u);
return true;
}
@@ -424,46 +485,37 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L
const UINT currentCursor = proximityBuffer[0].pkCursor;
UINT physicalCursorId;
QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &physicalCursorId);
+ const qint64 systemId = physicalCursorId;
UINT cursorType;
QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_TYPE, &cursorType);
- const qint64 uniqueId = (qint64(cursorType & DeviceIdMask) << 32L) | qint64(physicalCursorId);
+
+ const QInputDevice::DeviceType currentType = deviceType(cursorType);
+ const QPointingDevice::PointerType currentPointerType = pointerType(currentCursor);
// initializing and updating the cursor should be done in response to
// WT_CSRCHANGE. We do it in WT_PROXIMITY because some wintab never send
// the event WT_CSRCHANGE even if asked with CXO_CSRMESSAGES
- m_currentDevice = indexOfDevice(m_devices, uniqueId);
- if (m_currentDevice < 0) {
- m_currentDevice = m_devices.size();
- m_devices.push_back(tabletInit(uniqueId, cursorType));
+ m_currentDevice = findDevice(systemId, currentType, currentPointerType);
+ if (m_currentDevice.isNull())
+ m_currentDevice = clonePhysicalDevice(systemId, currentType, currentPointerType);
+ if (m_currentDevice.isNull()) {
+ QWinTabPointingDevice::DeviceDataPtr data(new QWindowsTabletDeviceData);
+ data->systemId = systemId;
+ data->tiltCapability = m_tiltSupport;
+ data->zCapability = (cursorType == 0x0004);
+ updateButtons(currentCursor, data.data());
+ m_currentDevice.reset(createInputDevice(data, currentType, currentPointerType));
+ m_devices.append(m_currentDevice);
}
- /**
- * We should check button map for changes on every proximity event, not
- * only during initialization phase.
- *
- * WARNING: in 2016 there were some Wacom table drivers, which could mess up
- * button mapping if the remapped button was pressed, while the
- * application **didn't have input focus**. This bug is somehow
- * related to the fact that Wacom drivers allow user to configure
- * per-application button-mappings. If the bug shows up again,
- * just move this button-map fetching into initialization block.
- *
- * See https://bugs.kde.org/show_bug.cgi?id=359561
- */
- BYTE logicalButtons[32];
- memset(logicalButtons, 0, 32);
- m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_SYSBTNMAP, &logicalButtons);
- m_devices[m_currentDevice].buttonsMap[0x1] = logicalButtons[0];
- m_devices[m_currentDevice].buttonsMap[0x2] = logicalButtons[1];
- m_devices[m_currentDevice].buttonsMap[0x4] = logicalButtons[2];
+ // The user can switch pressure sensitivity level in the driver,which
+ // will make our saved values invalid (this option is provided by Wacom
+ // drivers for compatibility reasons, and it can be adjusted on the fly)
+ updateData(m_currentDevice->deviceData().data());
- m_devices[m_currentDevice].currentPointerType = pointerType(currentCursor);
m_state = PenProximity;
qCDebug(lcQpaTablet) << "enter proximity for device #"
- << m_currentDevice << m_devices.at(m_currentDevice);
- QWindowSystemInterface::handleTabletEnterProximityEvent(proximityBuffer[0].pkTime,
- m_devices.at(m_currentDevice).currentDevice,
- m_devices.at(m_currentDevice).currentPointerType,
- m_devices.at(m_currentDevice).uniqueId);
+ << m_currentDevice.data();
+ enterProximity(proximityBuffer[0].pkTime);
return true;
}
@@ -517,12 +569,10 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
{
static PACKET localPacketBuf[TabletPacketQSize]; // our own tablet packet queue.
const int packetCount = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, TabletPacketQSize, &localPacketBuf);
- if (!packetCount || m_currentDevice < 0)
+ if (!packetCount || m_currentDevice.isNull())
return false;
- const int currentDevice = m_devices.at(m_currentDevice).currentDevice;
- const int currentPointer = m_devices.at(m_currentDevice).currentPointerType;
- const qint64 uniqueId = m_devices.at(m_currentDevice).uniqueId;
+ const QWindowsTabletDeviceData &current = *m_currentDevice->deviceData();
// The tablet can be used in 2 different modes (reflected in enum Mode),
// depending on its settings:
@@ -542,21 +592,40 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
if (QWindowsContext::verbose > 1) {
qCDebug(lcQpaTablet) << __FUNCTION__ << "processing" << packetCount
- << "mode=" << m_mode << "target:"
- << QGuiApplicationPrivate::tabletDevicePoint(uniqueId).target;
+ << "mode=" << m_mode;
}
- const Qt::KeyboardModifiers keyboardModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
+ const auto *keyMapper = QWindowsContext::instance()->keyMapper();
+ const Qt::KeyboardModifiers keyboardModifiers = keyMapper->queryKeyboardModifiers();
for (int i = 0; i < packetCount ; ++i) {
const PACKET &packet = localPacketBuf[i];
- const int z = currentDevice == QTabletEvent::FourDMouse ? int(packet.pkZ) : 0;
+ const int z = current.zCapability ? int(packet.pkZ) : 0;
+
+ const auto packetPointerType = pointerType(packet.pkCursor);
+
+ const Qt::MouseButtons buttons =
+ convertTabletButtons(packet.pkButtons, current);
+
+ if (buttons == Qt::NoButton && packetPointerType != m_currentDevice->pointerType()) {
+ leaveProximity(packet.pkTime);
+ Q_ASSERT(!m_currentDevice.isNull());
+ // Pointer type changed, find or clone a new device for this physical cursor.
+ const qint64 systemId = m_currentDevice->systemId();
+ const QInputDevice::DeviceType type = m_currentDevice->type();
+ m_currentDevice = findDevice(systemId, type, packetPointerType);
+ if (m_currentDevice.isNull())
+ m_currentDevice = clonePhysicalDevice(systemId, type, packetPointerType);
+ Q_ASSERT(!m_currentDevice.isNull());
+ enterProximity(packet.pkTime);
+ }
QPointF globalPosF =
- m_devices.at(m_currentDevice).scaleCoordinates(packet.pkX, packet.pkY, virtualDesktopArea);
+ current.scaleCoordinates(packet.pkX, packet.pkY, virtualDesktopArea);
- QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(uniqueId).target; // Pass to window that grabbed it.
+ // Pass to window that grabbed it.
+ QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(m_currentDevice->uniqueId().numericId()).target;
// Get Mouse Position and compare to tablet info
const QPoint mouseLocation = QWindowsCursor::mousePosition();
@@ -580,12 +649,12 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
Q_ASSERT(platformWindow);
const QPoint localPos = platformWindow->mapFromGlobal(globalPos);
- const qreal pressureNew = packet.pkButtons && (currentPointer == QTabletEvent::Pen || currentPointer == QTabletEvent::Eraser) ?
- m_devices.at(m_currentDevice).scalePressure(packet.pkNormalPressure) :
- qreal(0);
- const qreal tangentialPressure = currentDevice == QTabletEvent::Airbrush ?
- m_devices.at(m_currentDevice).scaleTangentialPressure(packet.pkTangentPressure) :
- qreal(0);
+ const qreal pressureNew = packet.pkButtons
+ && (m_currentDevice->pointerType() == QPointingDevice::PointerType::Pen
+ || m_currentDevice->pointerType() == QPointingDevice::PointerType::Eraser)
+ ? current.scalePressure(packet.pkNormalPressure) : qreal(0);
+ const qreal tangentialPressure = m_currentDevice->type() == QInputDevice::DeviceType::Airbrush
+ ? current.scaleTangentialPressure(packet.pkTangentPressure) : qreal(0);
int tiltX = 0;
int tiltY = 0;
@@ -614,20 +683,18 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
qCDebug(lcQpaTablet)
<< "Packet #" << i << '/' << packetCount << "button:" << packet.pkButtons
<< globalPosF << z << "to:" << target << localPos << "(packet" << packet.pkX
- << packet.pkY << ") dev:" << currentDevice << "pointer:"
- << currentPointer << "P:" << pressureNew << "tilt:" << tiltX << ','
- << tiltY << "tanP:" << tangentialPressure << "rotation:" << rotation;
+ << packet.pkY << ") dev:" << m_currentDevice->type() << "pointer:"
+ << m_currentDevice->pointerType() << "P:" << pressureNew << "tilt:" << tiltX << ','
+ << tiltY << "tanP:" << tangentialPressure << "rotation:" << rotation
+ << " target=" << target;
}
- Qt::MouseButtons buttons =
- convertTabletButtons(packet.pkButtons, m_devices.at(m_currentDevice));
-
- QWindowSystemInterface::handleTabletEvent(target, packet.pkTime, QPointF(localPos), globalPosF,
- currentDevice, currentPointer,
- buttons,
- pressureNew, tiltX, tiltY,
+ m_eventTime = packet.pkTime;
+ QWindowSystemInterface::handleTabletEvent(target, packet.pkTime,
+ m_currentDevice.data(),
+ QPointF(localPos), globalPosF,
+ buttons, pressureNew, tiltX, tiltY,
tangentialPressure, rotation, z,
- uniqueId,
keyboardModifiers);
}
return true;
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.h b/src/plugins/platforms/windows/qwindowstabletsupport.h
index 6bcf3357a5..fb639294d3 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.h
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.h
@@ -1,51 +1,17 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSTABLETSUPPORT_H
#define QWINDOWSTABLETSUPPORT_H
#include "qtwindowsglobal.h"
#include <QtGui/qtguiglobal.h>
+#include <QtGui/qpointingdevice.h>
-#include <QtCore/qvector.h>
-#include <QtCore/qpoint.h>
#include <QtCore/qhash.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qsharedpointer.h>
#include <wintab.h>
@@ -82,6 +48,8 @@ struct QWindowsWinTab32DLL
PtrWTQueueSizeSet wTQueueSizeSet = nullptr;
};
+// Data associated with a physical cursor (system ID) which is shared between
+// devices of varying device type/pointer type.
struct QWindowsTabletDeviceData
{
QPointF scaleCoordinates(int coordX, int coordY,const QRect &targetArea) const;
@@ -98,12 +66,31 @@ struct QWindowsTabletDeviceData
int maxY = 0;
int minZ = 0;
int maxZ = 0;
- qint64 uniqueId = 0;
- int currentDevice = 0;
- int currentPointerType = 0;
+ qint64 systemId = 0;
+ bool zCapability = false;
+ bool tiltCapability = false;
QHash<quint8, quint8> buttonsMap;
};
+class QWinTabPointingDevice : public QPointingDevice
+{
+public:
+ using DeviceDataPtr = QSharedPointer<QWindowsTabletDeviceData>;
+
+ explicit QWinTabPointingDevice(const DeviceDataPtr &data,
+ const QString &name, qint64 systemId,
+ QInputDevice::DeviceType devType,
+ PointerType pType, Capabilities caps, int maxPoints,
+ int buttonCount, const QString &seatName = QString(),
+ QPointingDeviceUniqueId uniqueId = QPointingDeviceUniqueId(),
+ QObject *parent = nullptr);
+
+ const DeviceDataPtr &deviceData() const { return m_deviceData; }
+
+private:
+ DeviceDataPtr m_deviceData;
+};
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t);
#endif
@@ -115,6 +102,9 @@ class QWindowsTabletSupport
explicit QWindowsTabletSupport(HWND window, HCTX context);
public:
+ using DevicePtr = QSharedPointer<QWinTabPointingDevice>;
+ using Devices = QList<DevicePtr>;
+
enum Mode
{
PenMode,
@@ -138,22 +128,35 @@ public:
bool translateTabletProximityEvent(WPARAM wParam, LPARAM lParam);
bool translateTabletPacketEvent();
- int absoluteRange() const { return m_absoluteRange; }
- void setAbsoluteRange(int a) { m_absoluteRange = a; }
+ static int absoluteRange() { return m_absoluteRange; }
+ static void setAbsoluteRange(int a) { m_absoluteRange = a; }
private:
unsigned options() const;
QWindowsTabletDeviceData tabletInit(qint64 uniqueId, UINT cursorType) const;
+ void updateData(QWindowsTabletDeviceData *data) const;
+ void updateButtons(unsigned currentCursor, QWindowsTabletDeviceData *data) const;
+ void enterProximity(ulong time = 0, QWindow *window = nullptr);
+ void leaveProximity(ulong time = 0, QWindow *window = nullptr);
+ void enterLeaveProximity(bool enter, ulong time, QWindow *window = nullptr);
+ DevicePtr findDevice(qint64 systemId) const;
+ DevicePtr findDevice(qint64 systemId,
+ QInputDevice::DeviceType deviceType,
+ QPointingDevice::PointerType pointerType) const;
+ DevicePtr clonePhysicalDevice(qint64 systemId,
+ QInputDevice::DeviceType deviceType,
+ QPointingDevice::PointerType pointerType);
static QWindowsWinTab32DLL m_winTab32DLL;
const HWND m_window;
const HCTX m_context;
- int m_absoluteRange = 20;
+ static int m_absoluteRange;
bool m_tiltSupport = false;
- QVector<QWindowsTabletDeviceData> m_devices;
- int m_currentDevice = -1;
+ Devices m_devices;
+ DevicePtr m_currentDevice;
Mode m_mode = PenMode;
State m_state = PenUp;
+ ulong m_eventTime = 0;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 32a65109af..e8a324aedb 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -1,107 +1,59 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
-
-// SHSTOCKICONINFO is only available since Vista
-#if _WIN32_WINNT < 0x0601
-# undef _WIN32_WINNT
-# define _WIN32_WINNT 0x0601
-#endif
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qt_windows.h>
#include "qwindowstheme.h"
#include "qwindowsmenu.h"
#include "qwindowsdialoghelpers.h"
#include "qwindowscontext.h"
+#include "qwindowsiconengine.h"
#include "qwindowsintegration.h"
#if QT_CONFIG(systemtrayicon)
# include "qwindowssystemtrayicon.h"
#endif
-#include "qt_windows.h"
+#include "qwindowsscreen.h"
+#include "qwindowswindow.h"
#include <commctrl.h>
#include <objbase.h>
-#ifndef Q_CC_MINGW
-# include <commoncontrols.h>
-#endif
+#include <commoncontrols.h>
#include <shellapi.h>
+#include <QtCore/qapplicationstatic.h>
#include <QtCore/qvariant.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdebug.h>
-#include <QtCore/qtextstream.h>
#include <QtCore/qsysinfo.h>
#include <QtCore/qcache.h>
#include <QtCore/qthread.h>
+#include <QtCore/qqueue.h>
#include <QtCore/qmutex.h>
#include <QtCore/qwaitcondition.h>
+#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/qcolor.h>
#include <QtGui/qpalette.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qpainter.h>
#include <QtGui/qpixmapcache.h>
#include <qpa/qwindowsysteminterface.h>
-#include <QtThemeSupport/private/qabstractfileiconengine_p.h>
-#include <QtFontDatabaseSupport/private/qwindowsfontdatabase_p.h>
+#include <QtGui/private/qabstractfileiconengine_p.h>
+#include <QtGui/private/qwindowsfontdatabase_p.h>
#include <private/qhighdpiscaling_p.h>
#include <private/qsystemlibrary_p.h>
+#include <private/qwinregistry_p.h>
+#include <QtCore/private/qfunctions_win_p.h>
#include <algorithm>
-#if defined(__IImageList_INTERFACE_DEFINED__) && defined(__IID_DEFINED__)
-# define USE_IIMAGELIST
-#endif
+#if QT_CONFIG(cpp_winrt)
+# include <QtCore/private/qt_winrtbase_p.h>
+
+# include <winrt/Windows.UI.ViewManagement.h>
+#endif // QT_CONFIG(cpp_winrt)
QT_BEGIN_NAMESPACE
-static inline QColor COLORREFToQColor(COLORREF cr)
-{
- return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr));
-}
-
-static inline QTextStream& operator<<(QTextStream &str, const QColor &c)
-{
- str.setIntegerBase(16);
- str.setFieldWidth(2);
- str.setPadChar(QLatin1Char('0'));
- str << " rgb: #" << c.red() << c.green() << c.blue();
- str.setIntegerBase(10);
- str.setFieldWidth(0);
- return str;
-}
+using namespace Qt::StringLiterals;
static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue)
{
@@ -126,120 +78,159 @@ static inline QColor mixColors(const QColor &c1, const QColor &c2)
(c1.blue() + c2.blue()) / 2};
}
+enum AccentColorLevel {
+ AccentColorDarkest,
+ AccentColorNormal,
+ AccentColorLightest
+};
+
+#if QT_CONFIG(cpp_winrt)
+static constexpr QColor getSysColor(winrt::Windows::UI::Color &&color)
+{
+ return QColor(color.R, color.G, color.B, color.A);
+}
+#endif
+
+[[maybe_unused]] [[nodiscard]] static inline QColor qt_accentColor(AccentColorLevel level)
+{
+#if QT_CONFIG(cpp_winrt)
+ using namespace winrt::Windows::UI::ViewManagement;
+ const auto settings = UISettings();
+ const QColor accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
+ const QColor accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
+ const QColor accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
+#else
+ const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
+ if (!registry.isValid())
+ return {};
+ const QVariant value = registry.value(L"AccentColor");
+ if (!value.isValid())
+ return {};
+ // The retrieved value is in the #AABBGGRR format, we need to
+ // convert it to the #AARRGGBB format which Qt expects.
+ const QColor abgr = QColor::fromRgba(qvariant_cast<DWORD>(value));
+ if (!abgr.isValid())
+ return {};
+ const QColor accent = QColor::fromRgb(abgr.blue(), abgr.green(), abgr.red(), abgr.alpha());
+ const QColor accentLight = accent.lighter(120);
+ const QColor accentDarkest = accent.darker(120 * 120 * 120);
+#endif
+ if (level == AccentColorDarkest)
+ return accentDarkest;
+ else if (level == AccentColorLightest)
+ return accentLight;
+ return accent;
+}
+
static inline QColor getSysColor(int index)
{
- return COLORREFToQColor(GetSysColor(index));
+ COLORREF cr = GetSysColor(index);
+ return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr));
}
// QTBUG-48823/Windows 10: SHGetFileInfo() (as called by item views on file system
// models has been observed to trigger a WM_PAINT on the mainwindow. Suppress the
// behavior by running it in a thread.
-
-struct QShGetFileInfoParams
-{
- QShGetFileInfoParams(const QString &fn, DWORD a, SHFILEINFO *i, UINT f, bool *r)
- : fileName(fn), attributes(a), flags(f), info(i), result(r)
- { }
-
- const QString &fileName;
- const DWORD attributes;
- const UINT flags;
- SHFILEINFO *const info;
- bool *const result;
-};
-
class QShGetFileInfoThread : public QThread
{
public:
- explicit QShGetFileInfoThread()
- : QThread(), m_params(nullptr)
+ struct Task
{
- connect(this, &QThread::finished, this, &QObject::deleteLater);
+ Task(const QString &fn, DWORD a, UINT f)
+ : fileName(fn), attributes(a), flags(f)
+ {}
+ Q_DISABLE_COPY(Task)
+ ~Task()
+ {
+ DestroyIcon(hIcon);
+ hIcon = 0;
+ }
+ // Request
+ const QString fileName;
+ const DWORD attributes;
+ const UINT flags;
+ // Result
+ HICON hIcon = 0;
+ int iIcon = -1;
+ bool finished = false;
+ bool resultValid() const { return hIcon != 0 && iIcon >= 0 && finished; }
+ };
+
+ QShGetFileInfoThread()
+ : QThread()
+ {
+ start();
}
- void run() override
+ ~QShGetFileInfoThread()
{
- m_init = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+ cancel();
+ wait();
+ }
- QMutexLocker readyLocker(&m_readyMutex);
- while (!m_cancelled.loadRelaxed()) {
- if (!m_params && !m_cancelled.loadRelaxed()
- && !m_readyCondition.wait(&m_readyMutex, QDeadlineTimer(1000ll)))
- continue;
+ QSharedPointer<Task> getNextTask()
+ {
+ QMutexLocker l(&m_waitForTaskMutex);
+ while (!isInterruptionRequested()) {
+ if (!m_taskQueue.isEmpty())
+ return m_taskQueue.dequeue();
+ m_waitForTaskCondition.wait(&m_waitForTaskMutex);
+ }
+ return nullptr;
+ }
- if (m_params) {
- const QString fileName = m_params->fileName;
+ void run() override
+ {
+ QComHelper comHelper(COINIT_MULTITHREADED);
+
+ while (!isInterruptionRequested()) {
+ auto task = getNextTask();
+ if (task) {
SHFILEINFO info;
- const bool result = SHGetFileInfo(reinterpret_cast<const wchar_t *>(fileName.utf16()),
- m_params->attributes, &info, sizeof(SHFILEINFO),
- m_params->flags);
- m_doneMutex.lock();
- if (!m_cancelled.loadRelaxed()) {
- *m_params->result = result;
- memcpy(m_params->info, &info, sizeof(SHFILEINFO));
+ const bool result = SHGetFileInfo(reinterpret_cast<const wchar_t *>(task->fileName.utf16()),
+ task->attributes, &info, sizeof(SHFILEINFO),
+ task->flags);
+ if (result) {
+ task->hIcon = info.hIcon;
+ task->iIcon = info.iIcon;
}
- m_params = nullptr;
-
+ task->finished = true;
m_doneCondition.wakeAll();
- m_doneMutex.unlock();
}
}
-
- if (m_init != S_FALSE)
- CoUninitialize();
}
- bool runWithParams(QShGetFileInfoParams *params, qint64 timeOutMSecs)
+ void runWithParams(const QSharedPointer<Task> &task,
+ std::chrono::milliseconds timeout = std::chrono::milliseconds(5000))
{
- QMutexLocker doneLocker(&m_doneMutex);
-
- m_readyMutex.lock();
- m_params = params;
- m_readyCondition.wakeAll();
- m_readyMutex.unlock();
+ {
+ QMutexLocker l(&m_waitForTaskMutex);
+ m_taskQueue.enqueue(task);
+ m_waitForTaskCondition.wakeAll();
+ }
- return m_doneCondition.wait(&m_doneMutex, QDeadlineTimer(timeOutMSecs));
+ QMutexLocker doneLocker(&m_doneMutex);
+ while (!task->finished && !isInterruptionRequested()) {
+ if (!m_doneCondition.wait(&m_doneMutex, QDeadlineTimer(timeout)))
+ return;
+ }
}
void cancel()
{
- QMutexLocker doneLocker(&m_doneMutex);
- m_cancelled.storeRelaxed(1);
- m_readyCondition.wakeAll();
+ requestInterruption();
+ m_doneCondition.wakeAll();
+ m_waitForTaskCondition.wakeAll();
}
private:
- HRESULT m_init;
- QShGetFileInfoParams *m_params;
- QAtomicInt m_cancelled;
- QWaitCondition m_readyCondition;
+ QQueue<QSharedPointer<Task>> m_taskQueue;
QWaitCondition m_doneCondition;
- QMutex m_readyMutex;
+ QWaitCondition m_waitForTaskCondition;
QMutex m_doneMutex;
+ QMutex m_waitForTaskMutex;
};
-
-static bool shGetFileInfoBackground(const QString &fileName, DWORD attributes,
- SHFILEINFO *info, UINT flags,
- qint64 timeOutMSecs = 5000)
-{
- static QShGetFileInfoThread *getFileInfoThread = nullptr;
- if (!getFileInfoThread) {
- getFileInfoThread = new QShGetFileInfoThread;
- getFileInfoThread->start();
- }
-
- bool result = false;
- QShGetFileInfoParams params(fileName, attributes, info, flags, &result);
- if (!getFileInfoThread->runWithParams(&params, timeOutMSecs)) {
- // Cancel and reset getFileInfoThread. It'll
- // be reinitialized the next time we get called.
- getFileInfoThread->cancel();
- getFileInfoThread = nullptr;
- qWarning().noquote() << "SHGetFileInfo() timed out for " << fileName;
- return false;
- }
- return result;
-}
+Q_APPLICATION_STATIC(QShGetFileInfoThread, s_shGetFileInfoThread)
// from QStyle::standardPalette
static inline QPalette standardPalette()
@@ -258,25 +249,47 @@ static inline QPalette standardPalette()
return palette;
}
-static inline QPalette systemPalette()
+static QColor placeHolderColor(QColor textColor)
{
- QPalette result = standardPalette();
+ textColor.setAlpha(128);
+ return textColor;
+}
+
+/*
+ This is used when the theme is light mode, and when the theme is dark but the
+ application doesn't support dark mode. In the latter case, we need to check.
+*/
+void QWindowsTheme::populateLightSystemBasePalette(QPalette &result)
+{
+ const QColor background = getSysColor(COLOR_BTNFACE);
+ const QColor textColor = getSysColor(COLOR_WINDOWTEXT);
+
+ const QColor accent = qt_accentColor(AccentColorNormal);
+ const QColor accentDarkest = qt_accentColor(AccentColorDarkest);
+
+ const QColor linkColor = accent;
+ const QColor btnFace = background;
+ const QColor btnHighlight = getSysColor(COLOR_BTNHIGHLIGHT);
+
+ result.setColor(QPalette::Highlight, getSysColor(COLOR_HIGHLIGHT));
result.setColor(QPalette::WindowText, getSysColor(COLOR_WINDOWTEXT));
- result.setColor(QPalette::Button, getSysColor(COLOR_BTNFACE));
- result.setColor(QPalette::Light, getSysColor(COLOR_BTNHIGHLIGHT));
+ result.setColor(QPalette::Button, btnFace);
+ result.setColor(QPalette::Light, btnHighlight);
result.setColor(QPalette::Dark, getSysColor(COLOR_BTNSHADOW));
result.setColor(QPalette::Mid, result.button().color().darker(150));
- result.setColor(QPalette::Text, getSysColor(COLOR_WINDOWTEXT));
- result.setColor(QPalette::BrightText, getSysColor(COLOR_BTNHIGHLIGHT));
+ result.setColor(QPalette::Text, textColor);
+ result.setColor(QPalette::PlaceholderText, placeHolderColor(textColor));
+ result.setColor(QPalette::BrightText, btnHighlight);
result.setColor(QPalette::Base, getSysColor(COLOR_WINDOW));
- result.setColor(QPalette::Window, getSysColor(COLOR_BTNFACE));
+ result.setColor(QPalette::Window, btnFace);
result.setColor(QPalette::ButtonText, getSysColor(COLOR_BTNTEXT));
result.setColor(QPalette::Midlight, getSysColor(COLOR_3DLIGHT));
result.setColor(QPalette::Shadow, getSysColor(COLOR_3DDKSHADOW));
- result.setColor(QPalette::Highlight, getSysColor(COLOR_HIGHLIGHT));
result.setColor(QPalette::HighlightedText, getSysColor(COLOR_HIGHLIGHTTEXT));
- result.setColor(QPalette::Link, Qt::blue);
- result.setColor(QPalette::LinkVisited, Qt::magenta);
+ result.setColor(QPalette::Accent, accent);
+
+ result.setColor(QPalette::Link, linkColor);
+ result.setColor(QPalette::LinkVisited, accentDarkest);
result.setColor(QPalette::Inactive, QPalette::Button, result.button().color());
result.setColor(QPalette::Inactive, QPalette::Window, result.window().color());
result.setColor(QPalette::Inactive, QPalette::Light, result.light().color());
@@ -284,35 +297,79 @@ static inline QPalette systemPalette()
if (result.midlight() == result.button())
result.setColor(QPalette::Midlight, result.button().color().lighter(110));
- if (result.window() != result.base()) {
- result.setColor(QPalette::Inactive, QPalette::Highlight, result.color(QPalette::Inactive, QPalette::Window));
- result.setColor(QPalette::Inactive, QPalette::HighlightedText, result.color(QPalette::Inactive, QPalette::Text));
- }
-
- const QColor disabled =
- mixColors(result.windowText().color(), result.button().color());
+}
- result.setColorGroup(QPalette::Disabled, result.windowText(), result.button(),
- result.light(), result.dark(), result.mid(),
- result.text(), result.brightText(), result.base(),
- result.window());
- result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
- result.setColor(QPalette::Disabled, QPalette::Text, disabled);
- result.setColor(QPalette::Disabled, QPalette::ButtonText, disabled);
- result.setColor(QPalette::Disabled, QPalette::Highlight,
- getSysColor(COLOR_HIGHLIGHT));
- result.setColor(QPalette::Disabled, QPalette::HighlightedText,
- getSysColor(COLOR_HIGHLIGHTTEXT));
- result.setColor(QPalette::Disabled, QPalette::Base,
- result.window().color());
- return result;
+void QWindowsTheme::populateDarkSystemBasePalette(QPalette &result)
+{
+#if QT_CONFIG(cpp_winrt)
+ using namespace winrt::Windows::UI::ViewManagement;
+ const auto settings = UISettings();
+
+ // We have to craft a palette from these colors. The settings.UIElementColor(UIElementType) API
+ // returns the old system colors, not the dark mode colors. If the background is black (which it
+ // usually), then override it with a dark gray instead so that we can go up and down the lightness.
+ const QColor foreground = getSysColor(settings.GetColorValue(UIColorType::Foreground));
+ const QColor background = [&settings]() -> QColor {
+ auto systemBackground = getSysColor(settings.GetColorValue(UIColorType::Background));
+ if (systemBackground == Qt::black)
+ systemBackground = QColor(0x1E, 0x1E, 0x1E);
+ return systemBackground;
+ }();
+
+ const QColor accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
+ const QColor accentDark = getSysColor(settings.GetColorValue(UIColorType::AccentDark1));
+ const QColor accentDarker = getSysColor(settings.GetColorValue(UIColorType::AccentDark2));
+ const QColor accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
+ const QColor accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
+ const QColor accentLighter = getSysColor(settings.GetColorValue(UIColorType::AccentLight2));
+ const QColor accentLightest = getSysColor(settings.GetColorValue(UIColorType::AccentLight3));
+#else
+ const QColor foreground = Qt::white;
+ const QColor background = QColor(0x1E, 0x1E, 0x1E);
+ const QColor accent = qt_accentColor(AccentColorNormal);
+ const QColor accentDark = accent.darker(120);
+ const QColor accentDarker = accentDark.darker(120);
+ const QColor accentDarkest = accentDarker.darker(120);
+ const QColor accentLight = accent.lighter(120);
+ const QColor accentLighter = accentLight.lighter(120);
+ const QColor accentLightest = accentLighter.lighter(120);
+#endif
+ const QColor linkColor = accent;
+ const QColor buttonColor = background.lighter(200);
+
+ result.setColor(QPalette::All, QPalette::WindowText, foreground);
+ result.setColor(QPalette::All, QPalette::Text, foreground);
+ result.setColor(QPalette::All, QPalette::BrightText, accentLightest);
+
+ result.setColor(QPalette::All, QPalette::Button, buttonColor);
+ result.setColor(QPalette::All, QPalette::ButtonText, foreground);
+ result.setColor(QPalette::All, QPalette::Light, buttonColor.lighter(200));
+ result.setColor(QPalette::All, QPalette::Midlight, buttonColor.lighter(150));
+ result.setColor(QPalette::All, QPalette::Dark, buttonColor.darker(200));
+ result.setColor(QPalette::All, QPalette::Mid, buttonColor.darker(150));
+ result.setColor(QPalette::All, QPalette::Shadow, Qt::black);
+
+ result.setColor(QPalette::All, QPalette::Base, background.lighter(150));
+ result.setColor(QPalette::All, QPalette::Window, background);
+
+ result.setColor(QPalette::All, QPalette::Highlight, accent);
+ result.setColor(QPalette::All, QPalette::HighlightedText, accent.lightness() > 128 ? Qt::black : Qt::white);
+ result.setColor(QPalette::All, QPalette::Link, linkColor);
+ result.setColor(QPalette::All, QPalette::LinkVisited, accentDarkest);
+ result.setColor(QPalette::All, QPalette::AlternateBase, accentDarkest);
+ result.setColor(QPalette::All, QPalette::ToolTipBase, buttonColor);
+ result.setColor(QPalette::All, QPalette::ToolTipText, foreground.darker(120));
+ result.setColor(QPalette::All, QPalette::PlaceholderText, placeHolderColor(foreground));
+ result.setColor(QPalette::All, QPalette::Accent, accent);
}
-static inline QPalette toolTipPalette(const QPalette &systemPalette)
+static inline QPalette toolTipPalette(const QPalette &systemPalette, bool light)
{
QPalette result(systemPalette);
- const QColor tipBgColor(getSysColor(COLOR_INFOBK));
- const QColor tipTextColor(getSysColor(COLOR_INFOTEXT));
+ const QColor tipBgColor = light ? getSysColor(COLOR_INFOBK)
+ : systemPalette.button().color();
+ const QColor tipTextColor = light ? getSysColor(COLOR_INFOTEXT)
+ : systemPalette.buttonText().color().darker(120);
result.setColor(QPalette::All, QPalette::Button, tipBgColor);
result.setColor(QPalette::All, QPalette::Window, tipBgColor);
@@ -326,8 +383,7 @@ static inline QPalette toolTipPalette(const QPalette &systemPalette)
result.setColor(QPalette::All, QPalette::ButtonText, tipTextColor);
result.setColor(QPalette::All, QPalette::ToolTipBase, tipBgColor);
result.setColor(QPalette::All, QPalette::ToolTipText, tipTextColor);
- const QColor disabled =
- mixColors(result.windowText().color(), result.button().color());
+ const QColor disabled = mixColors(result.windowText().color(), result.button().color());
result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
result.setColor(QPalette::Disabled, QPalette::Text, disabled);
result.setColor(QPalette::Disabled, QPalette::ToolTipText, disabled);
@@ -337,12 +393,15 @@ static inline QPalette toolTipPalette(const QPalette &systemPalette)
return result;
}
-static inline QPalette menuPalette(const QPalette &systemPalette)
+static inline QPalette menuPalette(const QPalette &systemPalette, bool light)
{
+ if (!light)
+ return systemPalette;
+
QPalette result(systemPalette);
- const QColor menuColor(getSysColor(COLOR_MENU));
- const QColor menuTextColor(getSysColor(COLOR_MENUTEXT));
- const QColor disabled(getSysColor(COLOR_GRAYTEXT));
+ const QColor menuColor = getSysColor(COLOR_MENU);
+ const QColor menuTextColor = getSysColor(COLOR_MENUTEXT);
+ const QColor disabled = getSysColor(COLOR_GRAYTEXT);
// we might need a special color group for the result.
result.setColor(QPalette::Active, QPalette::Button, menuColor);
result.setColor(QPalette::Active, QPalette::Text, menuTextColor);
@@ -351,8 +410,8 @@ static inline QPalette menuPalette(const QPalette &systemPalette)
result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
result.setColor(QPalette::Disabled, QPalette::Text, disabled);
const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false);
- result.setColor(QPalette::Disabled, QPalette::Highlight,
- getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT));
+ const QColor highlightColor = getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT);
+ result.setColor(QPalette::Disabled, QPalette::Highlight, highlightColor);
result.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled);
result.setColor(QPalette::Disabled, QPalette::Button,
result.color(QPalette::Active, QPalette::Button));
@@ -373,16 +432,17 @@ static inline QPalette menuPalette(const QPalette &systemPalette)
return result;
}
-static inline QPalette *menuBarPalette(const QPalette &menuPalette)
+static inline QPalette *menuBarPalette(const QPalette &menuPalette, bool light)
{
QPalette *result = nullptr;
- if (booleanSystemParametersInfo(SPI_GETFLATMENU, false)) {
- result = new QPalette(menuPalette);
- const QColor menubar(getSysColor(COLOR_MENUBAR));
- result->setColor(QPalette::Active, QPalette::Button, menubar);
- result->setColor(QPalette::Disabled, QPalette::Button, menubar);
- result->setColor(QPalette::Inactive, QPalette::Button, menubar);
- }
+ if (!light || !booleanSystemParametersInfo(SPI_GETFLATMENU, false))
+ return result;
+
+ result = new QPalette(menuPalette);
+ const QColor menubar(getSysColor(COLOR_MENUBAR));
+ result->setColor(QPalette::Active, QPalette::Button, menubar);
+ result->setColor(QPalette::Disabled, QPalette::Button, menubar);
+ result->setColor(QPalette::Inactive, QPalette::Button, menubar);
return result;
}
@@ -392,6 +452,7 @@ QWindowsTheme *QWindowsTheme::m_instance = nullptr;
QWindowsTheme::QWindowsTheme()
{
m_instance = this;
+ s_colorScheme = QWindowsTheme::queryColorScheme();
std::fill(m_fonts, m_fonts + NFonts, nullptr);
std::fill(m_palettes, m_palettes + NPalettes, nullptr);
refresh();
@@ -407,13 +468,16 @@ QWindowsTheme::~QWindowsTheme()
static inline QStringList iconThemeSearchPaths()
{
- const QFileInfo appDir(QCoreApplication::applicationDirPath() + QLatin1String("/icons"));
+ const QFileInfo appDir(QCoreApplication::applicationDirPath() + "/icons"_L1);
return appDir.isDir() ? QStringList(appDir.absoluteFilePath()) : QStringList();
}
static inline QStringList styleNames()
{
- return { QStringLiteral("WindowsVista"), QStringLiteral("Windows") };
+ QStringList styles = { QStringLiteral("WindowsVista"), QStringLiteral("Windows") };
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11)
+ styles.prepend(QStringLiteral("Windows11"));
+ return styles;
}
static inline int uiEffects()
@@ -468,12 +532,43 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const
}
case MouseDoubleClickDistance:
return GetSystemMetrics(SM_CXDOUBLECLK);
+ case MenuBarFocusOnAltPressRelease:
+ return true;
default:
break;
}
return QPlatformTheme::themeHint(hint);
}
+Qt::ColorScheme QWindowsTheme::colorScheme() const
+{
+ return QWindowsTheme::effectiveColorScheme();
+}
+
+Qt::ColorScheme QWindowsTheme::effectiveColorScheme()
+{
+ if (queryHighContrast())
+ return Qt::ColorScheme::Unknown;
+ return s_colorScheme;
+}
+
+void QWindowsTheme::handleSettingsChanged()
+{
+ const auto newColorScheme = QWindowsTheme::queryColorScheme();
+ const bool colorSchemeChanged = newColorScheme != QWindowsTheme::s_colorScheme;
+ s_colorScheme = newColorScheme;
+ auto integration = QWindowsIntegration::instance();
+ integration->updateApplicationBadge();
+ if (integration->darkModeHandling().testFlag(QWindowsApplication::DarkModeStyle)) {
+ QWindowsTheme::instance()->refresh();
+ QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>();
+ }
+ if (colorSchemeChanged) {
+ for (QWindowsWindow *w : std::as_const(QWindowsContext::instance()->windows()))
+ w->setDarkBorder(s_colorScheme == Qt::ColorScheme::Dark);
+ }
+}
+
void QWindowsTheme::clearPalettes()
{
qDeleteAll(m_palettes, m_palettes + NPalettes);
@@ -482,13 +577,64 @@ void QWindowsTheme::clearPalettes()
void QWindowsTheme::refreshPalettes()
{
-
if (!QGuiApplication::desktopSettingsAware())
return;
- m_palettes[SystemPalette] = new QPalette(systemPalette());
- m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette]));
- m_palettes[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette]));
- m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette]);
+ const bool light =
+ effectiveColorScheme() != Qt::ColorScheme::Dark
+ || !QWindowsIntegration::instance()->darkModeHandling().testFlag(QWindowsApplication::DarkModeStyle);
+ clearPalettes();
+ m_palettes[SystemPalette] = new QPalette(QWindowsTheme::systemPalette(s_colorScheme));
+ m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette], light));
+ m_palettes[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette], light));
+ m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette], light);
+ if (!light) {
+ m_palettes[CheckBoxPalette] = new QPalette(*m_palettes[SystemPalette]);
+ m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Base, qt_accentColor(AccentColorNormal));
+ m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Button, qt_accentColor(AccentColorLightest));
+ m_palettes[CheckBoxPalette]->setColor(QPalette::Inactive, QPalette::Base, qt_accentColor(AccentColorDarkest));
+ m_palettes[RadioButtonPalette] = new QPalette(*m_palettes[CheckBoxPalette]);
+ }
+}
+
+QPalette QWindowsTheme::systemPalette(Qt::ColorScheme colorScheme)
+{
+ QPalette result = standardPalette();
+
+ switch (colorScheme) {
+ case Qt::ColorScheme::Unknown:
+ // when a high-contrast theme is active or when we fail to read, assume light
+ Q_FALLTHROUGH();
+ case Qt::ColorScheme::Light:
+ populateLightSystemBasePalette(result);
+ break;
+ case Qt::ColorScheme::Dark:
+ populateDarkSystemBasePalette(result);
+ break;
+ }
+
+ if (result.window() != result.base()) {
+ result.setColor(QPalette::Inactive, QPalette::Highlight,
+ result.color(QPalette::Inactive, QPalette::Window));
+ result.setColor(QPalette::Inactive, QPalette::HighlightedText,
+ result.color(QPalette::Inactive, QPalette::Text));
+ result.setColor(QPalette::Inactive, QPalette::Accent,
+ result.color(QPalette::Inactive, QPalette::Window));
+ }
+
+ const QColor disabled = mixColors(result.windowText().color(), result.button().color());
+
+ result.setColorGroup(QPalette::Disabled, result.windowText(), result.button(),
+ result.light(), result.dark(), result.mid(),
+ result.text(), result.brightText(), result.base(),
+ result.window());
+ result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
+ result.setColor(QPalette::Disabled, QPalette::Text, disabled);
+ result.setColor(QPalette::Disabled, QPalette::ButtonText, disabled);
+ result.setColor(QPalette::Disabled, QPalette::Highlight, result.color(QPalette::Highlight));
+ result.setColor(QPalette::Disabled, QPalette::HighlightedText, result.color(QPalette::HighlightedText));
+ result.setColor(QPalette::Disabled, QPalette::Accent, disabled);
+ result.setColor(QPalette::Disabled, QPalette::Base, result.window().color());
+ return result;
}
void QWindowsTheme::clearFonts()
@@ -497,23 +643,55 @@ void QWindowsTheme::clearFonts()
std::fill(m_fonts, m_fonts + NFonts, nullptr);
}
+void QWindowsTheme::refresh()
+{
+ refreshPalettes();
+ refreshFonts();
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const NONCLIENTMETRICS &m)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d.noquote();
+ d << "NONCLIENTMETRICS(iMenu=" << m.iMenuWidth << 'x' << m.iMenuHeight
+ << ", lfCaptionFont=";
+ QWindowsFontDatabase::debugFormat(d, m.lfCaptionFont);
+ d << ", lfSmCaptionFont=";
+ QWindowsFontDatabase::debugFormat(d, m.lfSmCaptionFont);
+ d << ", lfMenuFont=";
+ QWindowsFontDatabase::debugFormat(d, m.lfMenuFont);
+ d << ", lfMessageFont=";
+ QWindowsFontDatabase::debugFormat(d, m.lfMessageFont);
+ d <<", lfStatusFont=";
+ QWindowsFontDatabase::debugFormat(d, m.lfStatusFont);
+ d << ')';
+ return d;
+}
+#endif // QT_NO_DEBUG_STREAM
+
void QWindowsTheme::refreshFonts()
{
clearFonts();
if (!QGuiApplication::desktopSettingsAware())
return;
+
+ const int dpi = 96;
NONCLIENTMETRICS ncm;
- QWindowsContext::nonClientMetrics(&ncm);
- const QFont menuFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMenuFont);
- const QFont messageBoxFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont);
- const QFont statusFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfStatusFont);
- const QFont titleFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfCaptionFont);
+ QWindowsContext::nonClientMetrics(&ncm, dpi);
+ qCDebug(lcQpaWindow) << __FUNCTION__ << ncm;
+
+ const QFont menuFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMenuFont, dpi);
+ const QFont messageBoxFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont, dpi);
+ const QFont statusFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfStatusFont, dpi);
+ const QFont titleFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfCaptionFont, dpi);
QFont fixedFont(QStringLiteral("Courier New"), messageBoxFont.pointSize());
fixedFont.setStyleHint(QFont::TypeWriter);
LOGFONT lfIconTitleFont;
- SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
- const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont);
+ SystemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
+ const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
m_fonts[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont());
m_fonts[MenuFont] = new QFont(menuFont);
@@ -570,13 +748,9 @@ void QWindowsTheme::refreshIconPixmapSizes()
fileIconSizes[LargeFileIcon] + fileIconSizes[LargeFileIcon] / 2;
fileIconSizes[JumboFileIcon] = 8 * fileIconSizes[LargeFileIcon]; // empirical, has not been observed to work
-#ifdef USE_IIMAGELIST
int *availEnd = fileIconSizes + JumboFileIcon + 1;
-#else
- int *availEnd = fileIconSizes + LargeFileIcon + 1;
-#endif // USE_IIMAGELIST
m_fileIconSizes = QAbstractFileIconEngine::toSizeList(fileIconSizes, availEnd);
- qCDebug(lcQpaWindows) << __FUNCTION__ << m_fileIconSizes;
+ qCDebug(lcQpaWindow) << __FUNCTION__ << m_fileIconSizes;
}
// Defined in qpixmap_win.cpp
@@ -687,15 +861,18 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
}
if (stockId != SIID_INVALID) {
- QPixmap pixmap;
SHSTOCKICONINFO iconInfo;
memset(&iconInfo, 0, sizeof(iconInfo));
iconInfo.cbSize = sizeof(iconInfo);
- stockFlags |= (pixmapSize.width() > 16 ? SHGFI_LARGEICON : SHGFI_SMALLICON);
- if (SHGetStockIconInfo(stockId, SHGFI_ICON | stockFlags, &iconInfo) == S_OK) {
- pixmap = qt_pixmapFromWinHICON(iconInfo.hIcon);
- DestroyIcon(iconInfo.hIcon);
- return pixmap;
+ stockFlags |= SHGSI_ICONLOCATION;
+ if (SHGetStockIconInfo(stockId, stockFlags, &iconInfo) == S_OK) {
+ const auto iconSize = pixmapSize.width();
+ HICON icon;
+ if (SHDefExtractIcon(iconInfo.szPath, iconInfo.iIcon, 0, &icon, nullptr, iconSize) == S_OK) {
+ QPixmap pixmap = qt_pixmapFromWinHICON(icon);
+ DestroyIcon(icon);
+ return pixmap;
+ }
}
}
@@ -729,15 +906,15 @@ enum { // Shell image list ids
static QString dirIconPixmapCacheKey(int iIcon, int iconSize, int imageListSize)
{
- QString key = QLatin1String("qt_dir_") + QString::number(iIcon);
+ QString key = "qt_dir_"_L1 + QString::number(iIcon);
if (iconSize == SHGFI_LARGEICON)
- key += QLatin1Char('l');
+ key += u'l';
switch (imageListSize) {
case sHIL_EXTRALARGE:
- key += QLatin1Char('e');
+ key += u'e';
break;
case sHIL_JUMBO:
- key += QLatin1Char('j');
+ key += u'j';
break;
}
return key;
@@ -748,7 +925,7 @@ class FakePointer
{
public:
- Q_STATIC_ASSERT_X(sizeof(T) <= sizeof(void *), "FakePointers can only go that far.");
+ static_assert(sizeof(T) <= sizeof(void *), "FakePointers can only go that far.");
static FakePointer *create(T thing)
{
@@ -765,10 +942,9 @@ public:
// Shell image list helper functions.
-static QPixmap pixmapFromShellImageList(int iImageList, const SHFILEINFO &info)
+static QPixmap pixmapFromShellImageList(int iImageList, int iIcon)
{
QPixmap result;
-#ifdef USE_IIMAGELIST
// For MinGW:
static const IID iID_IImageList = {0x46eb5926, 0x582e, 0x4017, {0x9f, 0xdf, 0xe8, 0x99, 0x8d, 0xaa, 0x9, 0x50}};
@@ -777,16 +953,12 @@ static QPixmap pixmapFromShellImageList(int iImageList, const SHFILEINFO &info)
if (hr != S_OK)
return result;
HICON hIcon;
- hr = imageList->GetIcon(info.iIcon, ILD_TRANSPARENT, &hIcon);
+ hr = imageList->GetIcon(iIcon, ILD_TRANSPARENT, &hIcon);
if (hr == S_OK) {
result = qt_pixmapFromWinHICON(hIcon);
DestroyIcon(hIcon);
}
imageList->Release();
-#else
- Q_UNUSED(iImageList)
- Q_UNUSED(info)
-#endif // USE_IIMAGELIST
return result;
}
@@ -796,7 +968,7 @@ public:
explicit QWindowsFileIconEngine(const QFileInfo &info, QPlatformTheme::IconOptions opts) :
QAbstractFileIconEngine(info, opts) {}
- QList<QSize> availableSizes(QIcon::Mode = QIcon::Normal, QIcon::State = QIcon::Off) const override
+ QList<QSize> availableSizes(QIcon::Mode = QIcon::Normal, QIcon::State = QIcon::Off) override
{ return QWindowsTheme::instance()->availableFileIconSizes(); }
protected:
@@ -815,24 +987,21 @@ QString QWindowsFileIconEngine::cacheKey() const
// It is faster to just look at the file extensions;
// avoiding slow QFileInfo::isExecutable() (QTBUG-13182)
QString suffix = fileInfo().suffix();
- if (!suffix.compare(QLatin1String("exe"), Qt::CaseInsensitive)
- || !suffix.compare(QLatin1String("lnk"), Qt::CaseInsensitive)
- || !suffix.compare(QLatin1String("ico"), Qt::CaseInsensitive)) {
+ if (!suffix.compare(u"exe", Qt::CaseInsensitive)
+ || !suffix.compare(u"lnk", Qt::CaseInsensitive)
+ || !suffix.compare(u"ico", Qt::CaseInsensitive)) {
return QString();
}
- return QLatin1String("qt_.")
+ return "qt_."_L1
+ (suffix.isEmpty() ? fileInfo().fileName() : std::move(suffix).toUpper()); // handle "Makefile" ;)
}
QPixmap QWindowsFileIconEngine::filePixmap(const QSize &size, QIcon::Mode, QIcon::State)
{
- /* We don't use the variable, but by storing it statically, we
- * ensure CoInitialize is only called once. */
- static HRESULT comInit = CoInitialize(nullptr);
- Q_UNUSED(comInit);
+ QComHelper comHelper;
static QCache<QString, FakePointer<int> > dirIconEntryCache(1000);
- static QMutex mx;
+ Q_CONSTINIT static QMutex mx;
static int defaultFolderIIcon = -1;
const bool useDefaultFolderIcon = options() & QPlatformTheme::DontUseCustomDirectoryIcons;
@@ -841,13 +1010,9 @@ QPixmap QWindowsFileIconEngine::filePixmap(const QSize &size, QIcon::Mode, QIcon
const int width = int(size.width());
const int iconSize = width > fileIconSizes[SmallFileIcon] ? SHGFI_LARGEICON : SHGFI_SMALLICON;
const int requestedImageListSize =
-#ifdef USE_IIMAGELIST
width > fileIconSizes[ExtraLargeFileIcon]
? sHIL_JUMBO
: (width > fileIconSizes[LargeFileIcon] ? sHIL_EXTRALARGE : 0);
-#else
- 0;
-#endif // !USE_IIMAGELIST
bool cacheableDirIcon = fileInfo().isDir() && !fileInfo().isRoot();
if (cacheableDirIcon) {
QMutexLocker locker(&mx);
@@ -863,7 +1028,6 @@ QPixmap QWindowsFileIconEngine::filePixmap(const QSize &size, QIcon::Mode, QIcon
}
}
- SHFILEINFO info;
unsigned int flags = SHGFI_ICON | iconSize | SHGFI_SYSICONINDEX | SHGFI_ADDOVERLAYS | SHGFI_OVERLAYINDEX;
DWORD attributes = 0;
QString path = filePath;
@@ -875,43 +1039,43 @@ QPixmap QWindowsFileIconEngine::filePixmap(const QSize &size, QIcon::Mode, QIcon
flags |= SHGFI_USEFILEATTRIBUTES;
attributes |= FILE_ATTRIBUTE_NORMAL;
}
- const bool val = shGetFileInfoBackground(path, attributes, &info, flags);
-
+ auto task = QSharedPointer<QShGetFileInfoThread::Task>(
+ new QShGetFileInfoThread::Task(path, attributes, flags));
+ s_shGetFileInfoThread()->runWithParams(task);
// Even if GetFileInfo returns a valid result, hIcon can be empty in some cases
- if (val && info.hIcon) {
+ if (task->resultValid()) {
QString key;
if (cacheableDirIcon) {
if (useDefaultFolderIcon && defaultFolderIIcon < 0)
- defaultFolderIIcon = info.iIcon;
+ defaultFolderIIcon = task->iIcon;
//using the unique icon index provided by windows save us from duplicate keys
- key = dirIconPixmapCacheKey(info.iIcon, iconSize, requestedImageListSize);
+ key = dirIconPixmapCacheKey(task->iIcon, iconSize, requestedImageListSize);
QPixmapCache::find(key, &pixmap);
if (!pixmap.isNull()) {
QMutexLocker locker(&mx);
- dirIconEntryCache.insert(filePath, FakePointer<int>::create(info.iIcon));
+ dirIconEntryCache.insert(filePath, FakePointer<int>::create(task->iIcon));
}
}
if (pixmap.isNull()) {
if (requestedImageListSize) {
- pixmap = pixmapFromShellImageList(requestedImageListSize, info);
+ pixmap = pixmapFromShellImageList(requestedImageListSize, task->iIcon);
if (pixmap.isNull() && requestedImageListSize == sHIL_JUMBO)
- pixmap = pixmapFromShellImageList(sHIL_EXTRALARGE, info);
+ pixmap = pixmapFromShellImageList(sHIL_EXTRALARGE, task->iIcon);
}
if (pixmap.isNull())
- pixmap = qt_pixmapFromWinHICON(info.hIcon);
+ pixmap = qt_pixmapFromWinHICON(task->hIcon);
if (!pixmap.isNull()) {
if (cacheableDirIcon) {
QMutexLocker locker(&mx);
QPixmapCache::insert(key, pixmap);
- dirIconEntryCache.insert(filePath, FakePointer<int>::create(info.iIcon));
+ dirIconEntryCache.insert(filePath, FakePointer<int>::create(task->iIcon));
}
} else {
qWarning("QWindowsTheme::fileIconPixmap() no icon found");
}
}
- DestroyIcon(info.hIcon);
}
return pixmap;
@@ -922,6 +1086,11 @@ QIcon QWindowsTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOpt
return QIcon(new QWindowsFileIconEngine(fileInfo, iconOptions));
}
+QIconEngine *QWindowsTheme::createIconEngine(const QString &iconName) const
+{
+ return new QWindowsIconEngine(iconName);
+}
+
static inline bool doUseNativeMenus()
{
const unsigned options = QWindowsIntegration::instance()->options();
@@ -946,6 +1115,25 @@ bool QWindowsTheme::useNativeMenus()
return result;
}
+Qt::ColorScheme QWindowsTheme::queryColorScheme()
+{
+ if (queryHighContrast())
+ return Qt::ColorScheme::Unknown;
+
+ const auto setting = QWinRegistryKey(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)")
+ .dwordValue(L"AppsUseLightTheme");
+ return setting.second && setting.first == 0 ? Qt::ColorScheme::Dark : Qt::ColorScheme::Light;
+}
+
+bool QWindowsTheme::queryHighContrast()
+{
+ HIGHCONTRAST hcf = {};
+ hcf.cbSize = static_cast<UINT>(sizeof(HIGHCONTRAST));
+ if (SystemParametersInfo(SPI_GETHIGHCONTRAST, hcf.cbSize, &hcf, FALSE))
+ return hcf.dwFlags & HCF_HIGHCONTRASTON;
+ return false;
+}
+
QPlatformMenuItem *QWindowsTheme::createPlatformMenuItem() const
{
qCDebug(lcQpaMenus) << __FUNCTION__;
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index 7a8c321da4..6109122944 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSTHEME_H
#define QWINDOWSTHEME_H
@@ -44,6 +8,8 @@
#include <QtCore/qsharedpointer.h>
#include <QtCore/qvariant.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qsize.h>
QT_BEGIN_NAMESPACE
@@ -64,6 +30,11 @@ public:
QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
#endif
QVariant themeHint(ThemeHint) const override;
+
+ Qt::ColorScheme colorScheme() const override;
+
+ static void handleSettingsChanged();
+
const QPalette *palette(Palette type = SystemPalette) const override
{ return m_palettes[type]; }
const QFont *font(Font type = SystemFont) const override
@@ -72,6 +43,7 @@ public:
QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override;
QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions = {}) const override;
+ QIconEngine *createIconEngine(const QString &iconName) const override;
void windowsThemeChanged(QWindow *window);
void displayChanged() { refreshIconPixmapSizes(); }
@@ -86,17 +58,27 @@ public:
static bool useNativeMenus();
void refreshFonts();
+ void refresh();
static const char *name;
+ static QPalette systemPalette(Qt::ColorScheme);
+
private:
- void refresh() { refreshPalettes(); refreshFonts(); }
void clearPalettes();
void refreshPalettes();
void clearFonts();
void refreshIconPixmapSizes();
+ static void populateLightSystemBasePalette(QPalette &result);
+ static void populateDarkSystemBasePalette(QPalette &result);
+
+ static Qt::ColorScheme queryColorScheme();
+ static Qt::ColorScheme effectiveColorScheme();
+ static bool queryHighContrast();
+
static QWindowsTheme *m_instance;
+ static inline Qt::ColorScheme s_colorScheme = Qt::ColorScheme::Unknown;
QPalette *m_palettes[NPalettes];
QFont *m_fonts[NFonts];
QList<QSize> m_fileIconSizes;
diff --git a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
index ffe2e62069..cc550d912b 100644
--- a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
+++ b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSTHREADPOOLRUNNER_H
#define QWINDOWSTHREADPOOLRUNNER_H
@@ -55,7 +19,6 @@ QT_BEGIN_NAMESPACE
to be done by using QWaitCondition/QMutex.
\internal
- \ingroup qt-lighthouse-win
*/
class QWindowsThreadPoolRunner
{
diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
index 812ea8193a..0c2ee9edf5 100644
--- a/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
+++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsvulkaninstance.h"
diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.h b/src/plugins/platforms/windows/qwindowsvulkaninstance.h
index cc7ef476d4..5e287d0302 100644
--- a/src/plugins/platforms/windows/qwindowsvulkaninstance.h
+++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSVULKANINSTANCE_H
#define QWINDOWSVULKANINSTANCE_H
@@ -46,7 +10,7 @@
#define VK_USE_PLATFORM_WIN32_KHR
-#include <QtVulkanSupport/private/qbasicvulkanplatforminstance_p.h>
+#include <QtGui/private/qbasicvulkanplatforminstance_p.h>
#include <QtCore/qlibrary.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index c3b7a92df9..5d96d40af5 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1,51 +1,11 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
-
-#if defined(WINVER) && WINVER < 0x0601
-# undef WINVER
-#endif
-#if !defined(WINVER)
-# define WINVER 0x0601 // Enable touch functions for MinGW
-#endif
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qt_windows.h>
#include "qwindowswindow.h"
#include "qwindowscontext.h"
+#include "qwindowstheme.h"
#if QT_CONFIG(draganddrop)
# include "qwindowsdrag.h"
#endif
@@ -68,7 +28,7 @@
#include <QtGui/qwindow.h>
#include <QtGui/qregion.h>
#include <QtGui/qopenglcontext.h>
-#include <private/qsystemlibrary_p.h>
+#include <QtGui/private/qwindowsthemecache_p.h>
#include <private/qwindow_p.h> // QWINDOWSIZE_MAX
#include <private/qguiapplication_p.h>
#include <private/qhighdpiscaling_p.h>
@@ -76,7 +36,6 @@
#include <QtCore/qdebug.h>
#include <QtCore/qlibraryinfo.h>
-#include <QtCore/qoperatingsystemversion.h>
#include <dwmapi.h>
@@ -84,6 +43,8 @@
#include "qwindowsvulkaninstance.h"
#endif
+#include <shellscalingapi.h>
+
QT_BEGIN_NAMESPACE
using QWindowCreationContextPtr = QSharedPointer<QWindowCreationContext>;
@@ -119,6 +80,34 @@ static QByteArray debugWinStyle(DWORD style)
rc += " WS_MINIMIZEBOX";
if (style & WS_MAXIMIZEBOX)
rc += " WS_MAXIMIZEBOX";
+ if (style & WS_BORDER)
+ rc += " WS_BORDER";
+ if (style & WS_CAPTION)
+ rc += " WS_CAPTION";
+ if (style & WS_CHILDWINDOW)
+ rc += " WS_CHILDWINDOW";
+ if (style & WS_DISABLED)
+ rc += " WS_DISABLED";
+ if (style & WS_GROUP)
+ rc += " WS_GROUP";
+ if (style & WS_HSCROLL)
+ rc += " WS_HSCROLL";
+ if (style & WS_ICONIC)
+ rc += " WS_ICONIC";
+ if (style & WS_MAXIMIZE)
+ rc += " WS_MAXIMIZE";
+ if (style & WS_MINIMIZE)
+ rc += " WS_MINIMIZE";
+ if (style & WS_SIZEBOX)
+ rc += " WS_SIZEBOX";
+ if (style & WS_TABSTOP)
+ rc += " WS_TABSTOP";
+ if (style & WS_TILED)
+ rc += " WS_TILED";
+ if (style & WS_VISIBLE)
+ rc += " WS_VISIBLE";
+ if (style & WS_VSCROLL)
+ rc += " WS_VSCROLL";
return rc;
}
@@ -138,6 +127,44 @@ static QByteArray debugWinExStyle(DWORD exStyle)
rc += " WS_EX_LAYOUTRTL";
if (exStyle & WS_EX_NOINHERITLAYOUT)
rc += " WS_EX_NOINHERITLAYOUT";
+ if (exStyle & WS_EX_ACCEPTFILES)
+ rc += " WS_EX_ACCEPTFILES";
+ if (exStyle & WS_EX_APPWINDOW)
+ rc += " WS_EX_APPWINDOW";
+ if (exStyle & WS_EX_CLIENTEDGE)
+ rc += " WS_EX_CLIENTEDGE";
+ if (exStyle & WS_EX_COMPOSITED)
+ rc += " WS_EX_COMPOSITED";
+ if (exStyle & WS_EX_CONTROLPARENT)
+ rc += " WS_EX_CONTROLPARENT";
+ if (exStyle & WS_EX_LEFT)
+ rc += " WS_EX_LEFT";
+ if (exStyle & WS_EX_LEFTSCROLLBAR)
+ rc += " WS_EX_LEFTSCROLLBAR";
+ if (exStyle & WS_EX_LTRREADING)
+ rc += " WS_EX_LTRREADING";
+ if (exStyle & WS_EX_MDICHILD)
+ rc += " WS_EX_MDICHILD";
+ if (exStyle & WS_EX_NOACTIVATE)
+ rc += " WS_EX_NOACTIVATE";
+ if (exStyle & WS_EX_NOPARENTNOTIFY)
+ rc += " WS_EX_NOPARENTNOTIFY";
+ if (exStyle & WS_EX_NOREDIRECTIONBITMAP)
+ rc += " WS_EX_NOREDIRECTIONBITMAP";
+ if (exStyle & WS_EX_RIGHT)
+ rc += " WS_EX_RIGHT";
+ if (exStyle & WS_EX_RIGHTSCROLLBAR)
+ rc += " WS_EX_RIGHTSCROLLBAR";
+ if (exStyle & WS_EX_RTLREADING)
+ rc += " WS_EX_RTLREADING";
+ if (exStyle & WS_EX_STATICEDGE)
+ rc += " WS_EX_STATICEDGE";
+ if (exStyle & WS_EX_TOPMOST)
+ rc += " WS_EX_TOPMOST";
+ if (exStyle & WS_EX_TRANSPARENT)
+ rc += " WS_EX_TRANSPARENT";
+ if (exStyle & WS_EX_WINDOWEDGE)
+ rc += " WS_EX_WINDOWEDGE";
return rc;
}
@@ -167,6 +194,62 @@ static QByteArray debugWinSwpPos(UINT flags)
rc += " SWP_NOZORDER";
if (flags & SWP_SHOWWINDOW)
rc += " SWP_SHOWWINDOW";
+ if (flags & SWP_ASYNCWINDOWPOS)
+ rc += " SWP_ASYNCWINDOWPOS";
+ if (flags & SWP_DEFERERASE)
+ rc += " SWP_DEFERERASE";
+ if (flags & SWP_DRAWFRAME)
+ rc += " SWP_DRAWFRAME";
+ if (flags & SWP_NOREPOSITION)
+ rc += " SWP_NOREPOSITION";
+ return rc;
+}
+
+[[nodiscard]] static inline QByteArray debugWindowPlacementFlags(const UINT flags)
+{
+ QByteArray rc = "0x";
+ rc += QByteArray::number(flags, 16);
+ if (flags & WPF_SETMINPOSITION)
+ rc += " WPF_SETMINPOSITION";
+ if (flags & WPF_RESTORETOMAXIMIZED)
+ rc += " WPF_RESTORETOMAXIMIZED";
+ if (flags & WPF_ASYNCWINDOWPLACEMENT)
+ rc += " WPF_ASYNCWINDOWPLACEMENT";
+ return rc;
+}
+
+[[nodiscard]] static inline QByteArray debugShowWindowCmd(const UINT cmd)
+{
+ QByteArray rc = {};
+ rc += QByteArray::number(cmd);
+ if (cmd == SW_HIDE)
+ rc += " SW_HIDE";
+ if (cmd == SW_SHOWNORMAL)
+ rc += " SW_SHOWNORMAL";
+ if (cmd == SW_NORMAL)
+ rc += " SW_NORMAL";
+ if (cmd == SW_SHOWMINIMIZED)
+ rc += " SW_SHOWMINIMIZED";
+ if (cmd == SW_SHOWMAXIMIZED)
+ rc += " SW_SHOWMAXIMIZED";
+ if (cmd == SW_MAXIMIZE)
+ rc += " SW_MAXIMIZE";
+ if (cmd == SW_SHOWNOACTIVATE)
+ rc += " SW_SHOWNOACTIVATE";
+ if (cmd == SW_SHOW)
+ rc += " SW_SHOW";
+ if (cmd == SW_MINIMIZE)
+ rc += " SW_MINIMIZE";
+ if (cmd == SW_SHOWMINNOACTIVE)
+ rc += " SW_SHOWMINNOACTIVE";
+ if (cmd == SW_SHOWNA)
+ rc += " SW_SHOWNA";
+ if (cmd == SW_RESTORE)
+ rc += " SW_RESTORE";
+ if (cmd == SW_SHOWDEFAULT)
+ rc += " SW_SHOWDEFAULT";
+ if (cmd == SW_FORCEMINIMIZE)
+ rc += " SW_FORCEMINIMIZE";
return rc;
}
@@ -202,7 +285,9 @@ QDebug operator<<(QDebug d, const RECT &r)
QDebug operator<<(QDebug d, const POINT &p)
{
- d << p.x << ',' << p.y;
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "POINT(x=" << p.x << ", y=" << p.y << ')';
return d;
}
@@ -221,7 +306,7 @@ QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p)
{
QDebugStateSaver saver(d);
d.nospace();
- d << "NCCALCSIZE_PARAMS(rgrc=[" << p.rgrc[0] << ' ' << p.rgrc[1] << ' '
+ d << "NCCALCSIZE_PARAMS(rgrc=[" << p.rgrc[0] << ", " << p.rgrc[1] << ", "
<< p.rgrc[2] << "], lppos=" << *p.lppos << ')';
return d;
}
@@ -230,11 +315,10 @@ QDebug operator<<(QDebug d, const MINMAXINFO &i)
{
QDebugStateSaver saver(d);
d.nospace();
- d << "MINMAXINFO maxSize=" << i.ptMaxSize.x << ','
- << i.ptMaxSize.y << " maxpos=" << i.ptMaxPosition.x
- << ',' << i.ptMaxPosition.y << " mintrack="
- << i.ptMinTrackSize.x << ',' << i.ptMinTrackSize.y
- << " maxtrack=" << i.ptMaxTrackSize.x << ',' << i.ptMaxTrackSize.y;
+ d << "MINMAXINFO(maxSize=" << i.ptMaxSize << ", "
+ << "maxpos=" << i.ptMaxPosition << ", "
+ << "maxtrack=" << i.ptMaxTrackSize << ", "
+ << "mintrack=" << i.ptMinTrackSize << ')';
return d;
}
@@ -243,9 +327,10 @@ QDebug operator<<(QDebug d, const WINDOWPLACEMENT &wp)
QDebugStateSaver saver(d);
d.nospace();
d.noquote();
- d << "WINDOWPLACEMENT(flags=0x" << Qt::hex << wp.flags << Qt::dec << ", showCmd="
- << wp.showCmd << ", ptMinPosition=" << wp.ptMinPosition << ", ptMaxPosition=" << wp.ptMaxPosition
- << ", rcNormalPosition=" << wp.rcNormalPosition;
+ d << "WINDOWPLACEMENT(flags=" << debugWindowPlacementFlags(wp.flags) << ", showCmd="
+ << debugShowWindowCmd(wp.showCmd) << ", ptMinPosition=" << wp.ptMinPosition
+ << ", ptMaxPosition=" << wp.ptMaxPosition << ", rcNormalPosition="
+ << wp.rcNormalPosition << ')';
return d;
}
@@ -253,7 +338,7 @@ QDebug operator<<(QDebug d, const GUID &guid)
{
QDebugStateSaver saver(d);
d.nospace();
- d << '{' << Qt::hex << Qt::uppercasedigits << qSetPadChar(QLatin1Char('0'))
+ d << '{' << Qt::hex << Qt::uppercasedigits << qSetPadChar(u'0')
<< qSetFieldWidth(8) << guid.Data1
<< qSetFieldWidth(0) << '-' << qSetFieldWidth(4)
<< guid.Data2 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4)
@@ -346,10 +431,8 @@ static inline bool windowIsAccelerated(const QWindow *w)
{
switch (w->surfaceType()) {
case QSurface::OpenGLSurface:
- return true;
- case QSurface::RasterGLSurface:
- return qt_window_private(const_cast<QWindow *>(w))->compositing;
case QSurface::VulkanSurface:
+ case QSurface::Direct3DSurface:
return true;
default:
return false;
@@ -358,20 +441,11 @@ static inline bool windowIsAccelerated(const QWindow *w)
static bool applyBlurBehindWindow(HWND hwnd)
{
- BOOL compositionEnabled;
- if (DwmIsCompositionEnabled(&compositionEnabled) != S_OK)
- return false;
-
DWM_BLURBEHIND blurBehind = {0, 0, nullptr, 0};
- if (compositionEnabled) {
- blurBehind.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
- blurBehind.fEnable = TRUE;
- blurBehind.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
- } else {
- blurBehind.dwFlags = DWM_BB_ENABLE;
- blurBehind.fEnable = FALSE;
- }
+ blurBehind.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
+ blurBehind.fEnable = TRUE;
+ blurBehind.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
const bool result = DwmEnableBlurBehindWindow(hwnd, &blurBehind) == S_OK;
@@ -392,20 +466,27 @@ static bool shouldShowMaximizeButton(const QWindow *w, Qt::WindowFlags flags)
w->maximumSize() == QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX);
}
+bool QWindowsWindow::hasNoNativeFrame(HWND hwnd, Qt::WindowFlags flags)
+{
+ const LONG_PTR style = GetWindowLongPtr(hwnd, GWL_STYLE);
+ return (style & WS_CHILD) || (flags & Qt::FramelessWindowHint);
+}
+
// Set the WS_EX_LAYERED flag on a HWND if required. This is required for
// translucent backgrounds, not fully opaque windows and for
// Qt::WindowTransparentForInput (in combination with WS_EX_TRANSPARENT).
bool QWindowsWindow::setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity)
{
- const LONG exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+ const LONG_PTR exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
+ // Native children are frameless by nature, so check for that as well.
const bool needsLayered = (flags & Qt::WindowTransparentForInput)
- || (hasAlpha && (flags & Qt::FramelessWindowHint)) || opacity < 1.0;
+ || (hasAlpha && hasNoNativeFrame(hwnd, flags)) || opacity < 1.0;
const bool isLayered = (exStyle & WS_EX_LAYERED);
if (needsLayered != isLayered) {
if (needsLayered) {
- SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
+ SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
} else {
- SetWindowLong(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);
+ SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);
}
}
return needsLayered;
@@ -415,7 +496,7 @@ static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bo
{
if (QWindowsWindow::setWindowLayered(hwnd, flags, hasAlpha, level)) {
const BYTE alpha = BYTE(qRound(255.0 * level));
- if (hasAlpha && !accelerated && (flags & Qt::FramelessWindowHint)) {
+ if (hasAlpha && !accelerated && QWindowsWindow::hasNoNativeFrame(hwnd, flags)) {
// Non-GL windows with alpha: Use blend function to update.
BLENDFUNCTION blend = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA};
UpdateLayeredWindow(hwnd, nullptr, nullptr, nullptr, nullptr, nullptr, 0, &blend, ULW_ALPHA);
@@ -438,31 +519,41 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
setWindowOpacity(hwnd, flags, hasAlpha, isAccelerated, opacity);
}
+[[nodiscard]] static inline int getResizeBorderThickness(const UINT dpi)
+{
+ // The width of the padded border will always be 0 if DWM composition is
+ // disabled, but since it will always be enabled and can't be programtically
+ // disabled from Windows 8, we are safe to go.
+ return GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
+ + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
+}
+
/*!
Calculates the dimensions of the invisible borders within the
- window frames in Windows 10, using an empirical expression that
- reproduces the measured values for standard DPI settings.
+ window frames which only exist on Windows 10 and onwards.
*/
static QMargins invisibleMargins(QPoint screenPoint)
{
- if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10) {
- POINT pt = {screenPoint.x(), screenPoint.y()};
- if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
- if (QWindowsContext::shcoredll.isValid()) {
- UINT dpiX;
- UINT dpiY;
- if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, 0, &dpiX, &dpiY))) {
- const qreal sc = (dpiX - 96) / 96.0;
- const int gap = 7 + qRound(5*sc) - int(sc);
- return QMargins(gap, 0, gap, gap);
- }
- }
+ POINT pt = {screenPoint.x(), screenPoint.y()};
+ if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
+ UINT dpiX;
+ UINT dpiY;
+ if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
+ const int gap = getResizeBorderThickness(dpiX);
+ return QMargins(gap, 0, gap, gap);
}
}
return QMargins();
}
+[[nodiscard]] static inline QMargins invisibleMargins(const HWND hwnd)
+{
+ const UINT dpi = GetDpiForWindow(hwnd);
+ const int gap = getResizeBorderThickness(dpi);
+ return QMargins(gap, 0, gap, gap);
+}
+
/*!
\class WindowCreationData
\brief Window creation code.
@@ -489,7 +580,6 @@ static QMargins invisibleMargins(QPoint screenPoint)
\sa QWindowCreationContext
\internal
- \ingroup qt-lighthouse-win
*/
struct WindowCreationData
@@ -553,13 +643,18 @@ static inline void fixTopLevelWindowFlags(Qt::WindowFlags &flags)
flags |= Qt::FramelessWindowHint;
}
-static QScreen *screenForName(const QWindow *w, const QString &name)
+static QScreen *screenForDeviceName(const QWindow *w, const QString &name)
{
+ const auto getDeviceName = [](const QScreen *screen) -> QString {
+ if (const auto s = static_cast<const QWindowsScreen *>(screen->handle()))
+ return s->data().deviceName;
+ return {};
+ };
QScreen *winScreen = w ? w->screen() : QGuiApplication::primaryScreen();
- if (winScreen && winScreen->name() != name) {
+ if (winScreen && getDeviceName(winScreen) != name) {
const auto screens = winScreen->virtualSiblings();
for (QScreen *screen : screens) {
- if (screen->name() == name)
+ if (getDeviceName(screen) == name)
return screen;
}
}
@@ -570,7 +665,7 @@ static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &co
{
const QPoint orgPos(context->frameX - invMargins.left(), context->frameY - invMargins.top());
- if (!w || (!w->isTopLevel() && w->surfaceType() != QWindow::OpenGLSurface))
+ if (!w || w->type() != Qt::Window)
return orgPos;
// Workaround for QTBUG-50371
@@ -703,52 +798,70 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
style = WS_CHILD;
}
- // if (!testAttribute(Qt::WA_PaintUnclipped))
- // ### Commented out for now as it causes some problems, but
- // this should be correct anyway, so dig some more into this
-#ifdef Q_FLATTEN_EXPOSE
- if (windowIsOpenGL(w)) // a bit incorrect since the is-opengl status may change from false to true at any time later on
- style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; // see SetPixelFormat
-#else
- style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
-#endif
- if (topLevel) {
- if ((type == Qt::Window || dialog || tool)) {
- if (!(flags & Qt::FramelessWindowHint)) {
- style |= WS_POPUP;
- if (flags & Qt::MSWindowsFixedSizeDialogHint) {
- style |= WS_DLGFRAME;
- } else {
- style |= WS_THICKFRAME;
- }
- if (flags & Qt::WindowTitleHint)
- style |= WS_CAPTION; // Contains WS_DLGFRAME
- }
- if (flags & Qt::WindowSystemMenuHint)
- style |= WS_SYSMENU;
- else if (dialog && (flags & Qt::WindowCloseButtonHint) && !(flags & Qt::FramelessWindowHint)) {
- style |= WS_SYSMENU | WS_BORDER; // QTBUG-2027, dialogs without system menu.
- exStyle |= WS_EX_DLGMODALFRAME;
+ style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
+
+ if (topLevel) {
+ if ((type == Qt::Window || dialog || tool)) {
+ if (!(flags & Qt::FramelessWindowHint)) {
+ style |= WS_POPUP;
+ if (flags & Qt::MSWindowsFixedSizeDialogHint) {
+ style |= WS_DLGFRAME;
+ } else {
+ style |= WS_THICKFRAME;
}
- if (flags & Qt::WindowMinimizeButtonHint)
- style |= WS_MINIMIZEBOX;
- if (shouldShowMaximizeButton(w, flags))
- style |= WS_MAXIMIZEBOX;
- if (tool)
- exStyle |= WS_EX_TOOLWINDOW;
- if (flags & Qt::WindowContextHelpButtonHint)
- exStyle |= WS_EX_CONTEXTHELP;
- } else {
- exStyle |= WS_EX_TOOLWINDOW;
+ if (flags & Qt::WindowTitleHint)
+ style |= WS_CAPTION; // Contains WS_DLGFRAME
+ }
+ if (flags & Qt::WindowSystemMenuHint)
+ style |= WS_SYSMENU;
+ else if (dialog && (flags & Qt::WindowCloseButtonHint) && !(flags & Qt::FramelessWindowHint)) {
+ style |= WS_SYSMENU | WS_BORDER; // QTBUG-2027, dialogs without system menu.
+ exStyle |= WS_EX_DLGMODALFRAME;
}
+ const bool showMinimizeButton = flags & Qt::WindowMinimizeButtonHint;
+ if (showMinimizeButton)
+ style |= WS_MINIMIZEBOX;
+ const bool showMaximizeButton = shouldShowMaximizeButton(w, flags);
+ if (showMaximizeButton)
+ style |= WS_MAXIMIZEBOX;
+ if (showMinimizeButton || showMaximizeButton)
+ style |= WS_SYSMENU;
+ if (tool)
+ exStyle |= WS_EX_TOOLWINDOW;
+ if ((flags & Qt::WindowContextHelpButtonHint) && !showMinimizeButton
+ && !showMaximizeButton)
+ exStyle |= WS_EX_CONTEXTHELP;
+ } else {
+ exStyle |= WS_EX_TOOLWINDOW;
+ }
- // make mouse events fall through this window
- // NOTE: WS_EX_TRANSPARENT flag can make mouse inputs fall through a layered window
- if (flagsIn & Qt::WindowTransparentForInput)
- exStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
+ // make mouse events fall through this window
+ // NOTE: WS_EX_TRANSPARENT flag can make mouse inputs fall through a layered window
+ if (flagsIn & Qt::WindowTransparentForInput)
+ exStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
+
+ // Currently only compatible with D3D surfaces, use it with care.
+ if (qEnvironmentVariableIntValue("QT_QPA_DISABLE_REDIRECTION_SURFACE"))
+ exStyle |= WS_EX_NOREDIRECTIONBITMAP;
}
}
+static inline bool shouldApplyDarkFrame(const QWindow *w)
+{
+ if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
+ return false;
+ // the application has explicitly opted out of dark frames
+ if (!QWindowsIntegration::instance()->darkModeHandling().testFlag(QWindowsApplication::DarkModeWindowFrames))
+ return false;
+
+ // if the application supports a dark border, and the palette is dark (window background color
+ // is darker than the text), then turn dark-border support on, otherwise use a light border.
+ auto *dWindow = QWindowPrivate::get(const_cast<QWindow*>(w));
+ const QPalette windowPal = dWindow->windowPalette();
+ return windowPal.color(QPalette::WindowText).lightness()
+ > windowPal.color(QPalette::Window).lightness();
+}
+
QWindowsWindowData
WindowCreationData::create(const QWindow *w, const WindowData &data, QString title) const
{
@@ -777,11 +890,12 @@ QWindowsWindowData
style, exStyle));
QWindowsContext::instance()->setWindowCreationContext(context);
- const bool hasFrame = (style & (WS_DLGFRAME | WS_THICKFRAME));
+ const bool hasFrame = (style & (WS_DLGFRAME | WS_THICKFRAME))
+ && !(result.flags & Qt::FramelessWindowHint);
QMargins invMargins = topLevel && hasFrame && QWindowsGeometryHint::positionIncludesFrame(w)
? invisibleMargins(QPoint(context->frameX, context->frameY)) : QMargins();
- qCDebug(lcQpaWindows).nospace()
+ qCDebug(lcQpaWindow).nospace()
<< "CreateWindowEx: " << w << " class=" << windowClassName << " title=" << title
<< '\n' << *this << "\nrequested: " << rect << ": "
<< context->frameWidth << 'x' << context->frameHeight
@@ -807,7 +921,7 @@ QWindowsWindowData
pos.x(), pos.y(),
context->frameWidth, context->frameHeight,
parentHandle, nullptr, appinst, nullptr);
- qCDebug(lcQpaWindows).nospace()
+ qCDebug(lcQpaWindow).nospace()
<< "CreateWindowEx: returns " << w << ' ' << result.hwnd << " obtained geometry: "
<< context->obtainedPos << context->obtainedSize << ' ' << context->margins;
@@ -816,6 +930,9 @@ QWindowsWindowData
return result;
}
+ if (QWindowsTheme::instance()->colorScheme() == Qt::ColorScheme::Dark && shouldApplyDarkFrame(w))
+ QWindowsWindow::setDarkBorderToWindow(result.hwnd, true);
+
if (mirrorParentWidth != 0) {
context->obtainedPos.setX(mirrorParentWidth - context->obtainedSize.width()
- context->obtainedPos.x());
@@ -824,6 +941,7 @@ QWindowsWindowData
QRect obtainedGeometry(context->obtainedPos, context->obtainedSize);
result.geometry = obtainedGeometry;
+ result.restoreGeometry = frameGeometry(result.hwnd, topLevel);
result.fullFrameMargins = context->margins;
result.embedded = embedded;
result.hasFrame = hasFrame;
@@ -844,7 +962,7 @@ void WindowCreationData::applyWindowFlags(HWND hwnd) const
const LONG_PTR newExStyle = exStyle;
if (newExStyle != oldExStyle)
SetWindowLongPtr(hwnd, GWL_EXSTYLE, newExStyle);
- qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << hwnd << *this
+ qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << hwnd << *this
<< "\n Style from " << debugWinStyle(DWORD(oldStyle)) << "\n to "
<< debugWinStyle(DWORD(newStyle)) << "\n ExStyle from "
<< debugWinExStyle(DWORD(oldExStyle)) << " to "
@@ -898,6 +1016,21 @@ static QSize toNativeSizeConstrained(QSize dip, const QScreen *s)
return dip;
}
+// Helper for checking if frame adjustment needs to be skipped
+// NOTE: Unmaximized frameless windows will skip margins calculation
+static bool shouldOmitFrameAdjustment(const Qt::WindowFlags flags, DWORD style)
+{
+ return flags.testFlag(Qt::FramelessWindowHint) && !(style & WS_MAXIMIZE);
+}
+
+// Helper for checking if frame adjustment needs to be skipped
+// NOTE: Unmaximized frameless windows will skip margins calculation
+static bool shouldOmitFrameAdjustment(const Qt::WindowFlags flags, HWND hwnd)
+{
+ DWORD style = hwnd != nullptr ? DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)) : 0;
+ return flags.testFlag(Qt::FramelessWindowHint) && !(style & WS_MAXIMIZE);
+}
+
/*!
\class QWindowsGeometryHint
\brief Stores geometry constraints and provides utility functions.
@@ -906,79 +1039,86 @@ static QSize toNativeSizeConstrained(QSize dip, const QScreen *s)
into account.
\internal
- \ingroup qt-lighthouse-win
*/
-QMargins QWindowsGeometryHint::frameOnPrimaryScreen(DWORD style, DWORD exStyle)
+QMargins QWindowsGeometryHint::frameOnPrimaryScreen(const QWindow *w, DWORD style, DWORD exStyle)
{
+ if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
+ return {};
RECT rect = {0,0,0,0};
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
if (AdjustWindowRectEx(&rect, style, FALSE, exStyle) == FALSE)
qErrnoWarning("%s: AdjustWindowRectEx failed", __FUNCTION__);
const QMargins result(qAbs(rect.left), qAbs(rect.top),
qAbs(rect.right), qAbs(rect.bottom));
- qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << " style="
+ qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << " style="
<< Qt::showbase << Qt::hex << style << " exStyle=" << exStyle << Qt::dec << Qt::noshowbase
<< ' ' << rect << ' ' << result;
return result;
}
-QMargins QWindowsGeometryHint::frameOnPrimaryScreen(HWND hwnd)
+QMargins QWindowsGeometryHint::frameOnPrimaryScreen(const QWindow *w, HWND hwnd)
{
- return frameOnPrimaryScreen(DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
+ return frameOnPrimaryScreen(w, DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE)));
}
-QMargins QWindowsGeometryHint::frame(DWORD style, DWORD exStyle, qreal dpi)
+QMargins QWindowsGeometryHint::frame(const QWindow *w, DWORD style, DWORD exStyle, qreal dpi)
{
- if (QWindowsContext::user32dll.adjustWindowRectExForDpi == nullptr)
- return frameOnPrimaryScreen(style, exStyle);
+ if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
+ return {};
RECT rect = {0,0,0,0};
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
- if (QWindowsContext::user32dll.adjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
- unsigned(qRound(dpi))) == FALSE) {
+ if (AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE) {
qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
}
const QMargins result(qAbs(rect.left), qAbs(rect.top),
qAbs(rect.right), qAbs(rect.bottom));
- qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << " style="
+ qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << " style="
<< Qt::showbase << Qt::hex << style << " exStyle=" << exStyle << Qt::dec << Qt::noshowbase
<< " dpi=" << dpi
<< ' ' << rect << ' ' << result;
return result;
}
-QMargins QWindowsGeometryHint::frame(HWND hwnd, DWORD style, DWORD exStyle)
+QMargins QWindowsGeometryHint::frame(const QWindow *w, HWND hwnd, DWORD style, DWORD exStyle)
{
+ if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
+ return {};
if (QWindowsScreenManager::isSingleScreen())
- return frameOnPrimaryScreen(style, exStyle);
- auto screenManager = QWindowsContext::instance()->screenManager();
+ return frameOnPrimaryScreen(w, style, exStyle);
+ auto &screenManager = QWindowsContext::instance()->screenManager();
auto screen = screenManager.screenForHwnd(hwnd);
if (!screen)
screen = screenManager.screens().value(0);
const auto dpi = screen ? screen->logicalDpi().first : qreal(96);
- return frame(style, exStyle, dpi);
+ return frame(w, style, exStyle, dpi);
+}
+
+QMargins QWindowsGeometryHint::frame(const QWindow *w, HWND hwnd)
+{
+ return frame(w, hwnd, DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
+ DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE)));
}
// For newly created windows.
QMargins QWindowsGeometryHint::frame(const QWindow *w, const QRect &geometry,
DWORD style, DWORD exStyle)
{
- if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
+ if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
return {};
- if (!QWindowsContext::user32dll.adjustWindowRectExForDpi
- || QWindowsScreenManager::isSingleScreen()
+ if (QWindowsScreenManager::isSingleScreen()
|| !QWindowsContext::shouldHaveNonClientDpiScaling(w)) {
- return frameOnPrimaryScreen(style, exStyle);
+ return frameOnPrimaryScreen(w, style, exStyle);
}
qreal dpi = 96;
- auto screenManager = QWindowsContext::instance()->screenManager();
+ auto &screenManager = QWindowsContext::instance()->screenManager();
auto screen = screenManager.screenAtDp(geometry.center());
if (!screen)
screen = screenManager.screens().value(0);
if (screen)
dpi = screen->logicalDpi().first;
- return QWindowsGeometryHint::frame(style, exStyle, dpi);
+ return QWindowsGeometryHint::frame(w, style, exStyle, dpi);
}
bool QWindowsGeometryHint::handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result)
@@ -994,7 +1134,7 @@ bool QWindowsGeometryHint::handleCalculateSize(const QMargins &customMargins, co
ncp->rgrc[0].right -= customMargins.right();
ncp->rgrc[0].bottom -= customMargins.bottom();
result = nullptr;
- qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << oldClientArea << '+' << customMargins << "-->"
+ qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << oldClientArea << '+' << customMargins << "-->"
<< ncp->rgrc[0] << ' ' << ncp->rgrc[1] << ' ' << ncp->rgrc[2]
<< ' ' << ncp->lppos->cx << ',' << ncp->lppos->cy;
return true;
@@ -1030,7 +1170,7 @@ void QWindowsGeometryHint::applyToMinMaxInfo(const QWindow *w,
QSize minimumSize;
QSize maximumSize;
frameSizeConstraints(w, screen, margins, &minimumSize, &maximumSize);
- qCDebug(lcQpaWindows).nospace() << '>' << __FUNCTION__ << '<' << " min="
+ qCDebug(lcQpaWindow).nospace() << '>' << __FUNCTION__ << '<' << " min="
<< minimumSize.width() << ',' << minimumSize.height()
<< " max=" << maximumSize.width() << ',' << maximumSize.height()
<< " margins=" << margins
@@ -1045,7 +1185,7 @@ void QWindowsGeometryHint::applyToMinMaxInfo(const QWindow *w,
mmi->ptMaxTrackSize.x = maximumSize.width();
if (maximumSize.height() < QWINDOWSIZE_MAX)
mmi->ptMaxTrackSize.y = maximumSize.height();
- qCDebug(lcQpaWindows).nospace() << '<' << __FUNCTION__ << " out " << *mmi;
+ qCDebug(lcQpaWindow).nospace() << '<' << __FUNCTION__ << " out " << *mmi;
}
void QWindowsGeometryHint::applyToMinMaxInfo(const QWindow *w,
@@ -1076,12 +1216,11 @@ bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w)
\since 5.6
\internal
- \ingroup qt-lighthouse-win
*/
bool QWindowsBaseWindow::isRtlLayout(HWND hwnd)
{
- return (GetWindowLongPtrW(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) != 0;
+ return (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) != 0;
}
QWindowsBaseWindow *QWindowsBaseWindow::baseWindowOf(const QWindow *w)
@@ -1117,7 +1256,21 @@ QRect QWindowsBaseWindow::geometry_sys() const
QMargins QWindowsBaseWindow::frameMargins_sys() const
{
- return QWindowsGeometryHint::frame(handle(), style(), exStyle());
+ return QWindowsGeometryHint::frame(window(), handle(), style(), exStyle());
+}
+
+std::optional<QWindowsBaseWindow::TouchWindowTouchTypes>
+ QWindowsBaseWindow::touchWindowTouchTypes_sys() const
+{
+ ULONG touchFlags = 0;
+ if (IsTouchWindow(handle(), &touchFlags) == FALSE)
+ return {};
+ TouchWindowTouchTypes result;
+ if ((touchFlags & TWF_FINETOUCH) != 0)
+ result.setFlag(TouchWindowTouchType::FineTouch);
+ if ((touchFlags & TWF_WANTPALM) != 0)
+ result.setFlag(TouchWindowTouchType::WantPalmTouch);
+ return result;
}
void QWindowsBaseWindow::hide_sys() // Normal hide, do not activate other windows.
@@ -1128,7 +1281,7 @@ void QWindowsBaseWindow::hide_sys() // Normal hide, do not activate other window
void QWindowsBaseWindow::raise_sys()
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window();
+ qCDebug(lcQpaWindow) << __FUNCTION__ << this << window();
const Qt::WindowType type = window()->type();
if (type == Qt::Popup
|| type == Qt::SubWindow // Special case for QTBUG-63121: MDI subwindows with WindowStaysOnTopHint
@@ -1139,14 +1292,14 @@ void QWindowsBaseWindow::raise_sys()
void QWindowsBaseWindow::lower_sys()
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window();
+ qCDebug(lcQpaWindow) << __FUNCTION__ << this << window();
if (!(window()->flags() & Qt::WindowStaysOnTopHint))
SetWindowPos(handle(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}
void QWindowsBaseWindow::setWindowTitle_sys(const QString &title)
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << title;
+ qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << title;
SetWindowText(handle(), reinterpret_cast<const wchar_t *>(title.utf16()));
}
@@ -1160,12 +1313,32 @@ QPoint QWindowsBaseWindow::mapFromGlobal(const QPoint &pos) const
return QWindowsGeometryHint::mapFromGlobal(handle(), pos);
}
+void QWindowsBaseWindow::setHasBorderInFullScreen(bool)
+{
+ Q_UNIMPLEMENTED();
+}
+
+bool QWindowsBaseWindow::hasBorderInFullScreen() const
+{
+ Q_UNIMPLEMENTED();
+ return false;
+}
+
+QMargins QWindowsBaseWindow::customMargins() const
+{
+ return {};
+}
+
+void QWindowsBaseWindow::setCustomMargins(const QMargins &)
+{
+ Q_UNIMPLEMENTED();
+}
+
/*!
\class QWindowsDesktopWindow
\brief Window wrapping GetDesktopWindow not allowing any manipulation.
\since 5.6
\internal
- \ingroup qt-lighthouse-win
*/
/*!
@@ -1178,7 +1351,6 @@ QPoint QWindowsBaseWindow::mapFromGlobal(const QPoint &pos) const
\since 5.6
\internal
- \ingroup qt-lighthouse-win
*/
QWindowsForeignWindow::QWindowsForeignWindow(QWindow *window, HWND hwnd)
@@ -1186,6 +1358,8 @@ QWindowsForeignWindow::QWindowsForeignWindow(QWindow *window, HWND hwnd)
, m_hwnd(hwnd)
, m_topLevelStyle(0)
{
+ if (QPlatformWindow::parent())
+ setParent(QPlatformWindow::parent());
}
void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
@@ -1194,7 +1368,7 @@ void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
const HWND newParent = newParentWindow ? reinterpret_cast<HWND>(newParentWindow->winId()) : HWND(nullptr);
const bool isTopLevel = !newParent;
const DWORD oldStyle = style();
- qCDebug(lcQpaWindows) << __FUNCTION__ << window() << "newParent="
+ qCDebug(lcQpaWindow) << __FUNCTION__ << window() << "newParent="
<< newParentWindow << newParent << "oldStyle=" << debugWinStyle(oldStyle);
SetParent(m_hwnd, newParent);
if (wasTopLevel != isTopLevel) { // Top level window flags need to be set/cleared manually.
@@ -1212,7 +1386,7 @@ void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
void QWindowsForeignWindow::setVisible(bool visible)
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << window() << visible;
+ qCDebug(lcQpaWindow) << __FUNCTION__ << window() << visible;
if (visible)
ShowWindow(handle(), SW_SHOWNOACTIVATE);
else
@@ -1237,7 +1411,6 @@ void QWindowsForeignWindow::setVisible(bool visible)
\sa WindowCreationData, QWindowsContext
\internal
- \ingroup qt-lighthouse-win
*/
QWindowCreationContext::QWindowCreationContext(const QWindow *w, const QScreen *s,
@@ -1250,13 +1423,16 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w, const QScreen *
requestedGeometry(geometry),
obtainedPos(geometryIn.topLeft()),
obtainedSize(geometryIn.size()),
- margins(QWindowsGeometryHint::frame(w, geometry, style, exStyle)),
- customMargins(cm)
+ margins(QWindowsGeometryHint::frame(w, geometry, style, exStyle))
{
// Geometry of toplevels does not consider window frames.
// TODO: No concept of WA_wasMoved yet that would indicate a
// CW_USEDEFAULT unless set. For now, assume that 0,0 means 'default'
// for toplevels.
+
+ if (!(w->flags() & Qt::FramelessWindowHint))
+ customMargins = cm;
+
if (geometry.isValid()
|| !qt_window_private(const_cast<QWindow *>(w))->resizeAutomatic) {
frameX = geometry.x();
@@ -1275,7 +1451,7 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w, const QScreen *
}
}
- qCDebug(lcQpaWindows).nospace()
+ qCDebug(lcQpaWindow).nospace()
<< __FUNCTION__ << ' ' << w << ' ' << geometry
<< " pos incl. frame=" << QWindowsGeometryHint::positionIncludesFrame(w)
<< " frame=" << frameWidth << 'x' << frameHeight << '+'
@@ -1295,7 +1471,7 @@ void QWindowCreationContext::applyToMinMaxInfo(MINMAXINFO *mmi) const
\list
\li Raster type: handleWmPaint() is implemented to
to bitblt the image. The DC can be accessed
- via getDC/Relase DC, which has a special handling
+ via getDC/releaseDC, which has special handling
when within a paint event (in that case, the DC obtained
from BeginPaint() is returned).
@@ -1307,18 +1483,17 @@ void QWindowCreationContext::applyToMinMaxInfo(MINMAXINFO *mmi) const
\endlist
\internal
- \ingroup qt-lighthouse-win
*/
const char *QWindowsWindow::embeddedNativeParentHandleProperty = "_q_embedded_native_parent_handle";
const char *QWindowsWindow::hasBorderInFullScreenProperty = "_q_has_border_in_fullscreen";
bool QWindowsWindow::m_borderInFullScreenDefault = false;
+bool QWindowsWindow::m_inSetgeometry = false;
QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) :
QWindowsBaseWindow(aWindow),
m_data(data),
- m_cursor(new CursorHandle),
- m_format(aWindow->requestedFormat())
+ m_cursor(new CursorHandle)
#if QT_CONFIG(vulkan)
, m_vkSurface(VK_NULL_HANDLE)
#endif
@@ -1327,21 +1502,23 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
const Qt::WindowType type = aWindow->type();
if (type == Qt::Desktop)
return; // No further handling for Qt::Desktop
-#ifndef QT_NO_OPENGL
- if (aWindow->surfaceType() == QWindow::OpenGLSurface) {
- if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL)
- setFlag(OpenGLSurface);
- else
- setFlag(OpenGL_ES2);
- }
-#endif // QT_NO_OPENGL
+ if (aWindow->surfaceType() == QWindow::Direct3DSurface)
+ setFlag(Direct3DSurface);
+#if QT_CONFIG(opengl)
+ if (aWindow->surfaceType() == QWindow::OpenGLSurface)
+ setFlag(OpenGLSurface);
+#endif
#if QT_CONFIG(vulkan)
if (aWindow->surfaceType() == QSurface::VulkanSurface)
setFlag(VulkanSurface);
#endif
updateDropSite(window()->isTopLevel());
- registerTouchWindow();
+ // Register touch unless if the flags are already set by a hook
+ // such as HCBT_CREATEWND
+ if (!touchWindowTouchTypes_sys().has_value())
+ registerTouchWindow();
+
const qreal opacity = qt_window_private(aWindow)->opacity;
if (!qFuzzyCompare(opacity, qreal(1.0)))
setOpacity(opacity);
@@ -1358,6 +1535,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
QWindowsWindow::~QWindowsWindow()
{
setFlag(WithinDestroy);
+ QWindowsThemeCache::clearThemeCache(m_data.hwnd);
if (testFlag(TouchRegistered))
UnregisterTouchWindow(m_data.hwnd);
destroyWindow();
@@ -1378,14 +1556,20 @@ void QWindowsWindow::initialize()
if (w->type() != Qt::Desktop) {
const Qt::WindowState state = w->windowState();
const QRect obtainedGeometry(creationContext->obtainedPos, creationContext->obtainedSize);
+ QPlatformScreen *obtainedScreen = screenForGeometry(obtainedGeometry);
+ if (obtainedScreen && screen() != obtainedScreen)
+ QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(w, obtainedScreen->screen());
if (state != Qt::WindowMaximized && state != Qt::WindowFullScreen
&& creationContext->requestedGeometryIn != obtainedGeometry) {
QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, obtainedGeometry);
}
- QPlatformScreen *obtainedScreen = screenForGeometry(obtainedGeometry);
- if (obtainedScreen && screen() != obtainedScreen)
- QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(w, obtainedScreen->screen());
}
+ QWindowsWindow::setSavedDpi(GetDpiForWindow(handle()));
+}
+
+QSurfaceFormat QWindowsWindow::format() const
+{
+ return window()->requestedFormat();
}
void QWindowsWindow::fireExpose(const QRegion &region, bool force)
@@ -1397,9 +1581,14 @@ void QWindowsWindow::fireExpose(const QRegion &region, bool force)
QWindowSystemInterface::handleExposeEvent(window(), region);
}
+void QWindowsWindow::fireFullExpose(bool force)
+{
+ fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), force);
+}
+
void QWindowsWindow::destroyWindow()
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << m_data.hwnd;
+ qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << m_data.hwnd;
if (m_data.hwnd) { // Stop event dispatching before Window is destroyed.
setFlag(WithinDestroy);
// Clear any transient child relationships as Windows will otherwise destroy them (QTBUG-35499, QTBUG-36666)
@@ -1506,7 +1695,7 @@ QScreen *QWindowsWindow::forcedScreenForGLWindow(const QWindow *w)
forceToScreen = GpuDescription::detect().gpuSuitableScreen;
m_screenForGLInitialized = true;
}
- return forceToScreen.isEmpty() ? nullptr : screenForName(w, forceToScreen);
+ return forceToScreen.isEmpty() ? nullptr : screenForDeviceName(w, forceToScreen);
}
// Returns topmost QWindowsWindow ancestor even if there are embedded windows in the chain.
@@ -1548,7 +1737,7 @@ QWindowsWindowData
void QWindowsWindow::setVisible(bool visible)
{
const QWindow *win = window();
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << win << m_data.hwnd << visible;
+ qCDebug(lcQpaWindow) << __FUNCTION__ << this << win << m_data.hwnd << visible;
if (m_data.hwnd) {
if (visible) {
show_sys();
@@ -1557,7 +1746,7 @@ void QWindowsWindow::setVisible(bool visible)
// over the rendering of the window
// There is nobody waiting for this, so we don't need to flush afterwards.
if (isLayered())
- fireExpose(QRect(0, 0, win->width(), win->height()));
+ fireFullExpose();
// QTBUG-44928, QTBUG-7386: This is to resolve the problem where popups are
// opened from the system tray and not being implicitly activated
@@ -1728,7 +1917,7 @@ void QWindowsWindow::show_sys() const
void QWindowsWindow::setParent(const QPlatformWindow *newParent)
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << window() << newParent;
+ qCDebug(lcQpaWindow) << __FUNCTION__ << window() << newParent;
if (m_data.hwnd)
setParent_sys(newParent);
@@ -1779,12 +1968,110 @@ void QWindowsWindow::handleHidden()
void QWindowsWindow::handleCompositionSettingsChanged()
{
const QWindow *w = window();
- if ((w->surfaceType() == QWindow::OpenGLSurface || w->surfaceType() == QWindow::VulkanSurface)
- && w->format().hasAlpha()) {
+ if ((w->surfaceType() == QWindow::OpenGLSurface
+ || w->surfaceType() == QWindow::VulkanSurface
+ || w->surfaceType() == QWindow::Direct3DSurface)
+ && w->format().hasAlpha())
+ {
applyBlurBehindWindow(handle());
}
}
+qreal QWindowsWindow::dpiRelativeScale(const UINT dpi) const
+{
+ return QHighDpiScaling::roundScaleFactor(qreal(dpi) / QWindowsScreen::baseDpi) /
+ QHighDpiScaling::roundScaleFactor(qreal(savedDpi()) / QWindowsScreen::baseDpi);
+}
+
+void QWindowsWindow::handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT *result)
+{
+ // We want to keep QWindow's device independent size constant across the
+ // DPI change. To accomplish this, scale QPlatformWindow's native size
+ // by the change of DPI (e.g. 120 -> 144 = 1.2), also taking any scale
+ // factor rounding into account. The win32 window size includes the margins;
+ // add the margins for the new DPI to the window size.
+ const UINT dpi = UINT(wParam);
+ const qreal scale = dpiRelativeScale(dpi);
+ const QMargins margins = fullFrameMargins();
+ if (!(m_data.flags & Qt::FramelessWindowHint)) {
+ // We need to update the custom margins to match the current DPI, because
+ // we don't want our users manually hook into this message just to set a
+ // new margin, but here we can't call setCustomMargins() directly, that
+ // function will change the window geometry which conflicts with what we
+ // are currently doing.
+ m_data.customMargins *= scale;
+ }
+
+ const QSize windowSize = (geometry().size() * scale).grownBy((margins * scale) + customMargins());
+ SIZE *size = reinterpret_cast<SIZE *>(lParam);
+ size->cx = windowSize.width();
+ size->cy = windowSize.height();
+ *result = true; // Inform Windows that we've set a size
+}
+
+void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+ const UINT dpi = HIWORD(wParam);
+ const qreal scale = dpiRelativeScale(dpi);
+ setSavedDpi(dpi);
+
+ QWindowsThemeCache::clearThemeCache(hwnd);
+
+ // Send screen change first, so that the new screen is set during any following resize
+ checkForScreenChanged(QWindowsWindow::FromDpiChange);
+
+ if (!IsZoomed(hwnd))
+ m_data.restoreGeometry.setSize(m_data.restoreGeometry.size() * scale);
+
+ // We get WM_DPICHANGED in one of two situations:
+ //
+ // 1. The DPI change is a "spontaneous" DPI change as a result of e.g.
+ // the user dragging the window to a new screen. In this case Windows
+ // first sends WM_GETDPISCALEDSIZE, where we set the new window size,
+ // followed by this event where we apply the suggested window geometry
+ // to the native window. This will make sure the window tracks the mouse
+ // cursor during screen change, and also that the window size is scaled
+ // according to the DPI change.
+ //
+ // 2. The DPI change is a result of a setGeometry() call. In this case
+ // Qt has already scaled the window size for the new DPI. Further, Windows
+ // does not call WM_GETDPISCALEDSIZE, and also applies its own scaling
+ // to the already scaled window size. Since there is no need to set the
+ // window geometry again, and the provided geometry is incorrect, we omit
+ // making the SetWindowPos() call.
+ if (!m_inSetgeometry) {
+ updateFullFrameMargins();
+ const auto prcNewWindow = reinterpret_cast<RECT *>(lParam);
+ SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top,
+ prcNewWindow->right - prcNewWindow->left,
+ prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
+ // If the window does not have a frame, WM_MOVE and WM_SIZE won't be
+ // called which prevents the content from being scaled appropriately
+ // after a DPI change.
+ if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
+ handleGeometryChange();
+ }
+
+ // Re-apply mask now that we have a new DPI, which have resulted in
+ // a new scale factor.
+ setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
+}
+
+void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
+{
+ const UINT dpi = GetDpiForWindow(hwnd);
+ const qreal scale = dpiRelativeScale(dpi);
+ setSavedDpi(dpi);
+
+ checkForScreenChanged(QWindowsWindow::FromDpiChange);
+
+ // Child windows do not get WM_GETDPISCALEDSIZE messages to inform
+ // Windows about the new size, so we need to manually scale them.
+ QRect currentGeometry = geometry();
+ QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
+ setGeometry(scaledGeometry);
+}
+
static QRect normalFrameGeometry(HWND hwnd)
{
WINDOWPLACEMENT wp;
@@ -1803,7 +2090,7 @@ QRect QWindowsWindow::normalGeometry() const
m_savedFrameGeometry.isValid() && (window()->windowStates() & Qt::WindowFullScreen);
const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd);
const QMargins margins = fakeFullScreen
- ? QWindowsGeometryHint::frame(handle(), m_savedStyle, 0)
+ ? QWindowsGeometryHint::frame(window(), handle(), m_savedStyle, 0)
: fullFrameMargins();
return frame.isValid() ? frame.marginsRemoved(margins) : frame;
}
@@ -1855,6 +2142,8 @@ static QString msgUnableToSetGeometry(const QWindowsWindow *platformWindow,
void QWindowsWindow::setGeometry(const QRect &rectIn)
{
+ QBoolBlocker b(m_inSetgeometry);
+
QRect rect = rectIn;
// This means it is a call from QWindow::setFramePosition() and
// the coordinates include the frame (size is still the contents rectangle).
@@ -1862,8 +2151,12 @@ void QWindowsWindow::setGeometry(const QRect &rectIn)
const QMargins margins = frameMargins();
rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
}
+
if (m_windowState & Qt::WindowMinimized)
m_data.geometry = rect; // Otherwise set by handleGeometryChange() triggered by event.
+ else
+ setWindowState(Qt::WindowNoState);// Update window state to WindowNoState unless minimized
+
if (m_data.hwnd) {
// A ResizeEvent with resulting geometry will be sent. If we cannot
// achieve that size (for example, window title minimal constraint),
@@ -1874,7 +2167,7 @@ void QWindowsWindow::setGeometry(const QRect &rectIn)
if (m_data.geometry != rect && (isVisible() || QLibraryInfo::isDebugBuild())) {
const auto warning =
msgUnableToSetGeometry(this, rectIn, m_data.geometry,
- m_data.fullFrameMargins, m_data.customMargins);
+ fullFrameMargins(), customMargins());
qWarning("%s: %s", __FUNCTION__, qPrintable(warning));
}
} else {
@@ -1889,8 +2182,41 @@ void QWindowsWindow::handleMoved()
handleGeometryChange();
}
-void QWindowsWindow::handleResized(int wParam)
+void QWindowsWindow::handleResized(int wParam, LPARAM lParam)
{
+ /* Prevents borderless windows from covering the taskbar when maximized. */
+ if ((m_data.flags.testFlag(Qt::FramelessWindowHint)
+ || (m_data.flags.testFlag(Qt::CustomizeWindowHint) && !m_data.flags.testFlag(Qt::WindowTitleHint)))
+ && IsZoomed(m_data.hwnd)) {
+ const int resizedWidth = LOWORD(lParam);
+ const int resizedHeight = HIWORD(lParam);
+
+ const HMONITOR monitor = MonitorFromWindow(m_data.hwnd, MONITOR_DEFAULTTOPRIMARY);
+ MONITORINFO monitorInfo = {};
+ monitorInfo.cbSize = sizeof(MONITORINFO);
+ GetMonitorInfoW(monitor, &monitorInfo);
+
+ int correctLeft = monitorInfo.rcMonitor.left;
+ int correctTop = monitorInfo.rcMonitor.top;
+ int correctWidth = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
+ int correctHeight = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
+
+ if (!m_data.flags.testFlag(Qt::FramelessWindowHint)) {
+ const int borderWidth = invisibleMargins(m_data.hwnd).left();
+ correctLeft -= borderWidth;
+ correctTop -= borderWidth;
+ correctWidth += borderWidth * 2;
+ correctHeight += borderWidth * 2;
+ }
+
+ if (resizedWidth != correctWidth || resizedHeight != correctHeight) {
+ qCDebug(lcQpaWindow) << __FUNCTION__ << "correcting: " << resizedWidth << "x"
+ << resizedHeight << " -> " << correctWidth << "x" << correctHeight;
+ SetWindowPos(m_data.hwnd, nullptr, correctLeft, correctTop, correctWidth, correctHeight,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+ }
+
switch (wParam) {
case SIZE_MAXHIDE: // Some other window affected.
case SIZE_MAXSHOW:
@@ -1900,12 +2226,13 @@ void QWindowsWindow::handleResized(int wParam)
handleWindowStateChange(m_windowState | Qt::WindowMinimized);
return;
case SIZE_MAXIMIZED:
+ handleGeometryChange();
if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry))
handleWindowStateChange(Qt::WindowMaximized | (isFullScreen_sys() ? Qt::WindowFullScreen
: Qt::WindowNoState));
- handleGeometryChange();
break;
case SIZE_RESTORED:
+ handleGeometryChange();
if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry)) {
if (isFullScreen_sys())
handleWindowStateChange(
@@ -1914,7 +2241,6 @@ void QWindowsWindow::handleResized(int wParam)
else if (m_windowState != Qt::WindowNoState && !testFlag(MaximizeToFullScreen))
handleWindowStateChange(Qt::WindowNoState);
}
- handleGeometryChange();
break;
}
}
@@ -1926,44 +2252,43 @@ static inline bool equalDpi(const QDpi &d1, const QDpi &d2)
void QWindowsWindow::checkForScreenChanged(ScreenChangeMode mode)
{
- if (parent() || QWindowsScreenManager::isSingleScreen())
+ if ((parent() && !parent()->isForeignWindow()) || QWindowsScreenManager::isSingleScreen())
return;
QPlatformScreen *currentScreen = screen();
+ auto topLevel = isTopLevel_sys() ? m_data.hwnd : GetAncestor(m_data.hwnd, GA_ROOT);
const QWindowsScreen *newScreen =
- QWindowsContext::instance()->screenManager().screenForHwnd(m_data.hwnd);
+ QWindowsContext::instance()->screenManager().screenForHwnd(topLevel);
+
if (newScreen == nullptr || newScreen == currentScreen)
return;
// For screens with different DPI: postpone until WM_DPICHANGE
- if (mode == FromGeometryChange
- && !equalDpi(currentScreen->logicalDpi(), newScreen->logicalDpi())) {
+ // Check on currentScreen as it can be 0 when resuming a session (QTBUG-80436).
+ const bool changingDpi = !equalDpi(QDpi(savedDpi(), savedDpi()), newScreen->logicalDpi());
+ if (mode == FromGeometryChange && currentScreen != nullptr && changingDpi)
return;
- }
- qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
- << ' ' << window() << " \"" << currentScreen->name()
+
+ qCDebug(lcQpaWindow).noquote().nospace() << __FUNCTION__
+ << ' ' << window() << " \"" << (currentScreen ? currentScreen->name() : QString())
<< "\"->\"" << newScreen->name() << '"';
- if (mode == FromGeometryChange)
- setFlag(SynchronousGeometryChangeEvent);
updateFullFrameMargins();
- QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
+ QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(window(), newScreen->screen());
}
void QWindowsWindow::handleGeometryChange()
{
const QRect previousGeometry = m_data.geometry;
m_data.geometry = geometry_sys();
- if (testFlag(WithinDpiChanged)
- && QWindowsContext::instance()->screenManager().screenForHwnd(m_data.hwnd) != screen()) {
- return; // QGuiApplication will send resize when screen actually changes
- }
+ updateFullFrameMargins();
QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry);
- // QTBUG-32121: OpenGL/normal windows (with exception of ANGLE) do not receive
- // expose events when shrinking, synthesize.
- if (!testFlag(OpenGL_ES2) && isExposed()
+ // QTBUG-32121: OpenGL/normal windows (with exception of ANGLE
+ // which we no longer support in Qt 6) do not receive expose
+ // events when shrinking, synthesize.
+ if (isExposed()
&& m_data.geometry.size() != previousGeometry.size() // Exclude plain move
// One dimension grew -> Windows will send expose, no need to synthesize.
&& !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) {
- fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true);
+ fireFullExpose(true);
}
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
@@ -1972,6 +2297,9 @@ void QWindowsWindow::handleGeometryChange()
if (testFlag(SynchronousGeometryChangeEvent))
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
+ if (!testFlag(ResizeMoveActive))
+ updateRestoreGeometry();
+
if (!wasSync)
clearFlag(SynchronousGeometryChangeEvent);
qCDebug(lcQpaEvents) << __FUNCTION__ << this << window() << m_data.geometry;
@@ -1982,7 +2310,7 @@ void QWindowsBaseWindow::setGeometry_sys(const QRect &rect) const
const QMargins margins = fullFrameMargins();
const QRect frameGeometry = rect + margins;
- qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << window()
+ qCDebug(lcQpaWindow) << '>' << __FUNCTION__ << window()
<< "\n from " << geometry_sys() << " frame: "
<< margins << " to " <<rect
<< " new frame: " << frameGeometry;
@@ -2013,7 +2341,7 @@ void QWindowsBaseWindow::setGeometry_sys(const QRect &rect) const
result = MoveWindow(hwnd, x, frameGeometry.y(),
frameGeometry.width(), frameGeometry.height(), true);
}
- qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << window()
+ qCDebug(lcQpaWindow) << '<' << __FUNCTION__ << window()
<< "\n resulting " << result << geometry_sys();
}
@@ -2035,7 +2363,7 @@ HDC QWindowsWindow::getDC()
}
/*!
- Relases the HDC for the window or does nothing in
+ Releases the HDC for the window or does nothing in
case it was obtained from WinAPI BeginPaint within a WM_PAINT event.
\sa getDC()
@@ -2049,12 +2377,6 @@ void QWindowsWindow::releaseDC()
}
}
-static inline bool dwmIsCompositionEnabled()
-{
- BOOL dWmCompositionEnabled = FALSE;
- return SUCCEEDED(DwmIsCompositionEnabled(&dWmCompositionEnabled)) && dWmCompositionEnabled == TRUE;
-}
-
static inline bool isSoftwareGl()
{
#if QT_CONFIG(dynamicgl)
@@ -2066,38 +2388,32 @@ static inline bool isSoftwareGl()
}
bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
- WPARAM, LPARAM)
+ WPARAM, LPARAM, LRESULT *result)
{
- if (message == WM_ERASEBKGND) // Backing store - ignored.
+ if (message == WM_ERASEBKGND) { // Backing store - ignored.
+ *result = 1;
return true;
+ }
// QTBUG-75455: Suppress WM_PAINT sent to invisible windows when setting WS_EX_LAYERED
- if (!window()->isVisible() && (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) != 0)
+ if (!window()->isVisible() && (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) != 0)
return false;
// Ignore invalid update bounding rectangles
- RECT updateRect;
- if (!GetUpdateRect(m_data.hwnd, &updateRect, FALSE))
+ if (!GetUpdateRect(m_data.hwnd, 0, FALSE))
return false;
PAINTSTRUCT ps;
- // GL software rendering (QTBUG-58178) and Windows 7/Aero off with some AMD cards
+ // GL software rendering (QTBUG-58178) with some AMD cards
// (QTBUG-60527) need InvalidateRect() to suppress artifacts while resizing.
- if (testFlag(OpenGLSurface) && (isSoftwareGl() || !dwmIsCompositionEnabled()))
+ if (testFlag(OpenGLSurface) && isSoftwareGl())
InvalidateRect(hwnd, nullptr, false);
BeginPaint(hwnd, &ps);
- // Observed painting problems with Aero style disabled (QTBUG-7865).
- if (Q_UNLIKELY(!dwmIsCompositionEnabled())
- && ((testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered)) || testFlag(VulkanSurface)))
- {
- SelectClipRgn(ps.hdc, nullptr);
- }
-
// If the a window is obscured by another window (such as a child window)
// we still need to send isExposed=true, for compatibility.
// Our tests depend on it.
fireExpose(QRegion(qrectFromRECT(ps.rcPaint)), true);
- if (qSizeOfRect(updateRect) == m_data.geometry.size() && !QWindowsContext::instance()->asyncExpose())
+ if (!QWindowsContext::instance()->asyncExpose())
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
EndPaint(hwnd, &ps);
@@ -2111,7 +2427,7 @@ void QWindowsWindow::setWindowTitle(const QString &title)
void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
{
- qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << this << window() << "\n from: "
+ qCDebug(lcQpaWindow) << '>' << __FUNCTION__ << this << window() << "\n from: "
<< m_data.flags << "\n to: " << flags;
const QRect oldGeometry = geometry();
if (m_data.flags != flags) {
@@ -2129,7 +2445,7 @@ void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
if (oldGeometry != newGeometry)
handleGeometryChange();
- qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << "\n returns: "
+ qCDebug(lcQpaWindow) << '<' << __FUNCTION__ << "\n returns: "
<< m_data.flags << " geometry " << oldGeometry << "->" << newGeometry;
}
@@ -2144,12 +2460,14 @@ QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
QWindowsWindowData result = m_data;
result.flags = creationData.flags;
result.embedded = creationData.embedded;
+ result.hasFrame = (creationData.style & (WS_DLGFRAME | WS_THICKFRAME))
+ && !(creationData.flags & Qt::FramelessWindowHint);
return result;
}
void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window()
+ qCDebug(lcQpaWindow) << __FUNCTION__ << this << window()
<< "\n from " << m_windowState << " to " << state;
m_windowState = state;
QWindowSystemInterface::handleWindowStateChanged(window(), state);
@@ -2157,12 +2475,20 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
handleHidden();
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); // Tell QQuickWindow to stop rendering now.
} else {
+ if (state & Qt::WindowMaximized) {
+ WINDOWPLACEMENT windowPlacement{};
+ windowPlacement.length = sizeof(WINDOWPLACEMENT);
+ GetWindowPlacement(m_data.hwnd, &windowPlacement);
+ const RECT geometry = RECTfromQRect(m_data.restoreGeometry);
+ windowPlacement.rcNormalPosition = geometry;
+ SetWindowPlacement(m_data.hwnd, &windowPlacement);
+ }
// QTBUG-17548: We send expose events when receiving WM_Paint, but for
// layered windows and transient children, we won't receive any WM_Paint.
QWindow *w = window();
bool exposeEventsSent = false;
if (isLayered()) {
- fireExpose(QRegion(0, 0, w->width(), w->height()));
+ fireFullExpose();
exposeEventsSent = true;
}
const QWindowList allWindows = QGuiApplication::allWindows();
@@ -2170,7 +2496,7 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
if (child != w && child->isVisible() && child->transientParent() == w) {
QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(child);
if (platformWindow && platformWindow->isLayered()) {
- platformWindow->fireExpose(QRegion(0, 0, child->width(), child->height()));
+ platformWindow->fireFullExpose();
exposeEventsSent = true;
}
}
@@ -2180,6 +2506,11 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
}
}
+void QWindowsWindow::updateRestoreGeometry()
+{
+ m_data.restoreGeometry = normalFrameGeometry(m_data.hwnd);
+}
+
void QWindowsWindow::setWindowState(Qt::WindowStates state)
{
if (m_data.hwnd) {
@@ -2216,7 +2547,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
const Qt::WindowStates oldState = m_windowState;
if (oldState == newState)
return;
- qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << this << window()
+ qCDebug(lcQpaWindow) << '>' << __FUNCTION__ << this << window()
<< " from " << oldState << " to " << newState;
const bool visible = isVisible();
@@ -2224,11 +2555,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
if (stateChange & Qt::WindowFullScreen) {
if (newState & Qt::WindowFullScreen) {
-#ifndef Q_FLATTEN_EXPOSE
UINT newStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
-#else
- UINT newStyle = WS_POPUP;
-#endif
// Save geometry and style to be restored when fullscreen
// is turned off again, since on Windows, it is not a real
// Window state but emulated by changing geometry and style.
@@ -2251,26 +2578,26 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
if (testFlag(HasBorderInFullScreen))
newStyle |= WS_BORDER;
setStyle(newStyle);
- // Use geometry of QWindow::screen() within creation or the virtual screen the
- // window is in (QTBUG-31166, QTBUG-30724).
- const QScreen *screen = window()->screen();
- if (!screen)
- screen = QGuiApplication::primaryScreen();
- const QRect r = screen ? QHighDpi::toNativePixels(screen->geometry(), window()) : m_savedFrameGeometry;
-
+ const HMONITOR monitor = MonitorFromWindow(m_data.hwnd, MONITOR_DEFAULTTONEAREST);
+ MONITORINFO monitorInfo = {};
+ monitorInfo.cbSize = sizeof(MONITORINFO);
+ GetMonitorInfoW(monitor, &monitorInfo);
+ const QRect screenGeometry(monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top,
+ monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left,
+ monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top);
if (newState & Qt::WindowMinimized) {
- setMinimizedGeometry(m_data.hwnd, r);
+ setMinimizedGeometry(m_data.hwnd, screenGeometry);
if (stateChange & Qt::WindowMaximized)
setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
} else {
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent);
- SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
+ SetWindowPos(m_data.hwnd, HWND_TOP, screenGeometry.left(), screenGeometry.top(), screenGeometry.width(), screenGeometry.height(), swpf);
if (!wasSync)
clearFlag(SynchronousGeometryChangeEvent);
clearFlag(MaximizeToFullScreen);
- QWindowSystemInterface::handleGeometryChange(window(), r);
+ QWindowSystemInterface::handleGeometryChange(window(), screenGeometry);
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
}
} else {
@@ -2284,8 +2611,10 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
if (!screen)
screen = QGuiApplication::primaryScreen();
// That area of the virtual desktop might not be covered by a screen anymore.
- if (!screen->geometry().intersects(m_savedFrameGeometry))
- m_savedFrameGeometry.moveTo(screen->geometry().topLeft());
+ if (const auto platformScreen = screen->handle()) {
+ if (!platformScreen->geometry().intersects(m_savedFrameGeometry))
+ m_savedFrameGeometry.moveTo(platformScreen->geometry().topLeft());
+ }
if (newState & Qt::WindowMinimized) {
setMinimizedGeometry(m_data.hwnd, m_savedFrameGeometry);
@@ -2340,12 +2669,12 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
}
}
- qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << this << window() << newState;
+ qCDebug(lcQpaWindow) << '<' << __FUNCTION__ << this << window() << newState;
}
void QWindowsWindow::setStyle(unsigned s) const
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << debugWinStyle(s);
+ qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << debugWinStyle(s);
setFlag(WithinSetStyle);
SetWindowLongPtr(m_data.hwnd, GWL_STYLE, s);
clearFlag(WithinSetStyle);
@@ -2353,14 +2682,16 @@ void QWindowsWindow::setStyle(unsigned s) const
void QWindowsWindow::setExStyle(unsigned s) const
{
- qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << ' ' << this << ' ' << window()
- << " 0x" << QByteArray::number(s, 16);
+ qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << debugWinExStyle(s);
SetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE, s);
}
bool QWindowsWindow::windowEvent(QEvent *event)
{
switch (event->type()) {
+ case QEvent::ApplicationPaletteChange:
+ setDarkBorder(QWindowsTheme::instance()->colorScheme() == Qt::ColorScheme::Dark);
+ break;
case QEvent::WindowBlocked: // Blocked by another modal window.
setEnabled(false);
setFlag(BlockedByModal);
@@ -2380,12 +2711,24 @@ bool QWindowsWindow::windowEvent(QEvent *event)
void QWindowsWindow::propagateSizeHints()
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window();
+ qCDebug(lcQpaWindow) << __FUNCTION__ << this << window();
}
bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &margins)
{
auto *windowPos = reinterpret_cast<WINDOWPOS *>(message->lParam);
+ const QRect suggestedFrameGeometry(windowPos->x, windowPos->y,
+ windowPos->cx, windowPos->cy);
+ const QRect suggestedGeometry = suggestedFrameGeometry - margins;
+
+ // Tell Windows to discard the entire contents of the client area, as re-using
+ // parts of the client area would lead to jitter during resize.
+ // Check the suggestedGeometry against the current one to only discard during
+ // resize, and not a plain move. We also look for SWP_NOSIZE since that, too,
+ // implies an identical size, and comparing QRects wouldn't work with null cx/cy
+ if (!(windowPos->flags & SWP_NOSIZE) && suggestedGeometry.size() != qWindow->geometry().size())
+ windowPos->flags |= SWP_NOCOPYBITS;
+
if ((windowPos->flags & SWP_NOZORDER) == 0) {
if (QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(qWindow)) {
QWindow *parentWindow = qWindow->parent();
@@ -2398,11 +2741,8 @@ bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *
}
if (!qWindow->isTopLevel()) // Implement hasHeightForWidth().
return false;
- if ((windowPos->flags & (SWP_NOCOPYBITS | SWP_NOSIZE)))
+ if (windowPos->flags & SWP_NOSIZE)
return false;
- const QRect suggestedFrameGeometry(windowPos->x, windowPos->y,
- windowPos->cx, windowPos->cy);
- const QRect suggestedGeometry = suggestedFrameGeometry - margins;
const QRectF correctedGeometryF = QPlatformWindow::closestAcceptableGeometry(qWindow, suggestedGeometry);
if (!correctedGeometryF.isValid())
return false;
@@ -2424,42 +2764,90 @@ bool QWindowsWindow::handleGeometryChanging(MSG *message) const
void QWindowsWindow::setFullFrameMargins(const QMargins &newMargins)
{
+ if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
+ return;
if (m_data.fullFrameMargins != newMargins) {
- qCDebug(lcQpaWindows) << __FUNCTION__ << window() << m_data.fullFrameMargins << "->" << newMargins;
+ qCDebug(lcQpaWindow) << __FUNCTION__ << window() << m_data.fullFrameMargins << "->" << newMargins;
m_data.fullFrameMargins = newMargins;
}
}
void QWindowsWindow::updateFullFrameMargins()
{
- // Normally obtained from WM_NCCALCSIZE
+ // QTBUG-82580: If a native menu is present, force a WM_NCCALCSIZE.
+ if (GetMenu(m_data.hwnd))
+ QWindowsContext::forceNcCalcSize(m_data.hwnd);
+ else
+ calculateFullFrameMargins();
+}
+
+void QWindowsWindow::calculateFullFrameMargins()
+{
+ if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
+ return;
+
+ // QTBUG-113736: systemMargins depends on AdjustWindowRectExForDpi. This doesn't take into
+ // account possible external modifications to the titlebar, as with ExtendsContentIntoTitleBar()
+ // from the Windows App SDK. We can fix this by comparing the WindowRect (which includes the
+ // frame) to the ClientRect. If a 'typical' frame is detected, i.e. only the titlebar has been
+ // modified, we can safely adjust the frame by deducting the bottom margin to the total Y
+ // difference between the two rects, to get the actual size of the titlebar and prevent
+ // unwanted client area slicing.
+
+ RECT windowRect{};
+ RECT clientRect{};
+ GetWindowRect(handle(), &windowRect);
+ GetClientRect(handle(), &clientRect);
+
+ // QTBUG-117704 It is also possible that the user has manually removed the frame (for example
+ // by handling WM_NCCALCSIZE). If that is the case, i.e., the client area and the window area
+ // have identical sizes, we don't want to override the user-defined margins.
+
+ if (qrectFromRECT(windowRect).size() == qrectFromRECT(clientRect).size())
+ return;
+
+ // Normally obtained from WM_NCCALCSIZE. This calculation only works
+ // when no native menu is present.
const auto systemMargins = testFlag(DisableNonClientScaling)
- ? QWindowsGeometryHint::frameOnPrimaryScreen(m_data.hwnd)
+ ? QWindowsGeometryHint::frameOnPrimaryScreen(window(), m_data.hwnd)
: frameMargins_sys();
- setFullFrameMargins(systemMargins + m_data.customMargins);
+ const QMargins actualMargins = systemMargins + customMargins();
+
+ const int yDiff = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
+ const bool typicalFrame = (actualMargins.left() == actualMargins.right())
+ && (actualMargins.right() == actualMargins.bottom());
+
+ const QMargins adjustedMargins = typicalFrame ?
+ QMargins(actualMargins.left(), (yDiff - actualMargins.bottom()),
+ actualMargins.right(), actualMargins.bottom())
+ : actualMargins;
+
+ setFullFrameMargins(adjustedMargins);
}
QMargins QWindowsWindow::frameMargins() const
{
QMargins result = fullFrameMargins();
if (isTopLevel() && m_data.hasFrame)
- result -= invisibleMargins(geometry().topLeft());
+ result -= invisibleMargins(m_data.hwnd);
return result;
}
QMargins QWindowsWindow::fullFrameMargins() const
{
+ if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
+ return {};
return m_data.fullFrameMargins;
}
void QWindowsWindow::setOpacity(qreal level)
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << level;
+ qCDebug(lcQpaWindow) << __FUNCTION__ << level;
if (!qFuzzyCompare(m_opacity, level)) {
m_opacity = level;
if (m_data.hwnd)
setWindowOpacity(m_data.hwnd, m_data.flags,
- window()->format().hasAlpha(), testFlag(OpenGLSurface) || testFlag(VulkanSurface),
+ window()->format().hasAlpha(), testFlag(OpenGLSurface) || testFlag(VulkanSurface) || testFlag(Direct3DSurface),
level);
}
}
@@ -2514,40 +2902,76 @@ void QWindowsWindow::setMask(const QRegion &region)
void QWindowsWindow::requestActivateWindow()
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window();
- // 'Active' state handling is based in focus since it needs to work for
- // child windows as well.
- if (m_data.hwnd) {
- const DWORD currentThread = GetCurrentThreadId();
- bool attached = false;
- DWORD foregroundThread = 0;
-
- // QTBUG-14062, QTBUG-37435: Windows normally only flashes the taskbar entry
- // when activating windows of inactive applications. Attach to the input of the
- // currently active window while setting the foreground window to always activate
- // the window when desired.
- if (QGuiApplication::applicationState() != Qt::ApplicationActive
- && QWindowsNativeInterface::windowActivationBehavior() == QWindowsWindowFunctions::AlwaysActivateWindow) {
- if (const HWND foregroundWindow = GetForegroundWindow()) {
- foregroundThread = GetWindowThreadProcessId(foregroundWindow, nullptr);
- if (foregroundThread && foregroundThread != currentThread)
- attached = AttachThreadInput(foregroundThread, currentThread, TRUE) == TRUE;
- if (attached) {
- if (!window()->flags().testFlag(Qt::WindowStaysOnBottomHint)
- && !window()->flags().testFlag(Qt::WindowStaysOnTopHint)
- && window()->type() != Qt::ToolTip) {
- const UINT swpFlags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER;
- SetWindowPos(m_data.hwnd, HWND_TOPMOST, 0, 0, 0, 0, swpFlags);
- SetWindowPos(m_data.hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, swpFlags);
- }
- }
- }
- }
+ qCDebug(lcQpaWindow) << __FUNCTION__ << this << window();
+
+ if (!m_data.hwnd)
+ return;
+
+ const auto activationBehavior = QWindowsIntegration::instance()->windowActivationBehavior();
+ if (QGuiApplication::applicationState() == Qt::ApplicationActive
+ || activationBehavior != QWindowsApplication::AlwaysActivateWindow) {
SetForegroundWindow(m_data.hwnd);
SetFocus(m_data.hwnd);
- if (attached)
- AttachThreadInput(foregroundThread, currentThread, FALSE);
+ return;
}
+
+ // Force activate this window. The following code will bring the window to the
+ // foreground and activate it. If the window is hidden, it will show up. If
+ // the window is minimized, it will restore to the previous position.
+
+ // But first we need some sanity checks.
+ if (m_data.flags & Qt::WindowStaysOnBottomHint) {
+ qCWarning(lcQpaWindow) <<
+ "Windows with Qt::WindowStaysOnBottomHint can't be brought to the foreground.";
+ return;
+ }
+ if (m_data.flags & Qt::WindowStaysOnTopHint) {
+ qCWarning(lcQpaWindow) <<
+ "Windows with Qt::WindowStaysOnTopHint will always be on the foreground.";
+ return;
+ }
+ if (window()->type() == Qt::ToolTip) {
+ qCWarning(lcQpaWindow) << "ToolTip windows should not be activated.";
+ return;
+ }
+
+ // We need to show the window first, otherwise we won't be able to bring it to front.
+ if (!IsWindowVisible(m_data.hwnd))
+ ShowWindow(m_data.hwnd, SW_SHOW);
+
+ if (IsIconic(m_data.hwnd)) {
+ ShowWindow(m_data.hwnd, SW_RESTORE);
+ // When the window is restored, it will always become the foreground window.
+ // So return early here, we don't need the following code to bring it to front.
+ return;
+ }
+
+ // OK, our window is not minimized, so now we will try to bring it to front manually.
+ const HWND oldForegroundWindow = GetForegroundWindow();
+ if (!oldForegroundWindow) // It may be NULL, according to MS docs.
+ return;
+
+ // First try to send a message to the current foreground window to check whether
+ // it is currently hanging or not.
+ if (SendMessageTimeoutW(oldForegroundWindow, WM_NULL, 0, 0,
+ SMTO_BLOCK | SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, 1000, nullptr) == 0) {
+ qCWarning(lcQpaWindow) << "The foreground window hangs, can't activate current window.";
+ return;
+ }
+
+ const DWORD windowThreadProcessId = GetWindowThreadProcessId(oldForegroundWindow, nullptr);
+ const DWORD currentThreadId = GetCurrentThreadId();
+
+ AttachThreadInput(windowThreadProcessId, currentThreadId, TRUE);
+ const auto cleanup = qScopeGuard([windowThreadProcessId, currentThreadId](){
+ AttachThreadInput(windowThreadProcessId, currentThreadId, FALSE);
+ });
+
+ BringWindowToTop(m_data.hwnd);
+
+ // Activate the window too. This will force us to the virtual desktop this
+ // window is on, if it's on another virtual desktop.
+ SetActiveWindow(m_data.hwnd);
}
bool QWindowsWindow::setKeyboardGrabEnabled(bool grab)
@@ -2556,7 +2980,7 @@ bool QWindowsWindow::setKeyboardGrabEnabled(bool grab)
qWarning("%s: No handle", __FUNCTION__);
return false;
}
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << grab;
+ qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << grab;
QWindowsContext *context = QWindowsContext::instance();
if (grab) {
@@ -2570,7 +2994,7 @@ bool QWindowsWindow::setKeyboardGrabEnabled(bool grab)
bool QWindowsWindow::setMouseGrabEnabled(bool grab)
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << window() << grab;
+ qCDebug(lcQpaWindow) << __FUNCTION__ << window() << grab;
if (!m_data.hwnd) {
qWarning("%s: No handle", __FUNCTION__);
return false;
@@ -2593,37 +3017,41 @@ bool QWindowsWindow::setMouseGrabEnabled(bool grab)
return grab;
}
-static inline DWORD cornerToWinOrientation(Qt::Corner corner)
+static inline DWORD edgesToWinOrientation(Qt::Edges edges)
{
- switch (corner) {
- case Qt::TopLeftCorner:
- return 0xf004; // SZ_SIZETOPLEFT;
- case Qt::TopRightCorner:
- return 0xf005; // SZ_SIZETOPRIGHT
- case Qt::BottomLeftCorner:
- return 0xf007; // SZ_SIZEBOTTOMLEFT
- case Qt::BottomRightCorner:
- return 0xf008; // SZ_SIZEBOTTOMRIGHT
- }
- return 0;
+ if (edges == Qt::LeftEdge)
+ return 0xf001; // SC_SIZELEFT;
+ else if (edges == (Qt::RightEdge))
+ return 0xf002; // SC_SIZERIGHT
+ else if (edges == (Qt::TopEdge))
+ return 0xf003; // SC_SIZETOP
+ else if (edges == (Qt::TopEdge | Qt::LeftEdge))
+ return 0xf004; // SC_SIZETOPLEFT
+ else if (edges == (Qt::TopEdge | Qt::RightEdge))
+ return 0xf005; // SC_SIZETOPRIGHT
+ else if (edges == (Qt::BottomEdge))
+ return 0xf006; // SC_SIZEBOTTOM
+ else if (edges == (Qt::BottomEdge | Qt::LeftEdge))
+ return 0xf007; // SC_SIZEBOTTOMLEFT
+ else if (edges == (Qt::BottomEdge | Qt::RightEdge))
+ return 0xf008; // SC_SIZEBOTTOMRIGHT
+
+ return 0xf000; // SC_SIZE
}
-bool QWindowsWindow::startSystemResize(const QPoint &, Qt::Corner corner)
+bool QWindowsWindow::startSystemResize(Qt::Edges edges)
{
- if (!GetSystemMenu(m_data.hwnd, FALSE))
+ if (Q_UNLIKELY(window()->flags().testFlag(Qt::MSWindowsFixedSizeDialogHint)))
return false;
ReleaseCapture();
- PostMessage(m_data.hwnd, WM_SYSCOMMAND, cornerToWinOrientation(corner), 0);
+ PostMessage(m_data.hwnd, WM_SYSCOMMAND, edgesToWinOrientation(edges), 0);
setFlag(SizeGripOperation);
return true;
}
-bool QWindowsWindow::startSystemMove(const QPoint &)
+bool QWindowsWindow::startSystemMove()
{
- if (!GetSystemMenu(m_data.hwnd, FALSE))
- return false;
-
ReleaseCapture();
PostMessage(m_data.hwnd, WM_SYSCOMMAND, 0xF012 /*SC_DRAGMOVE*/, 0);
return true;
@@ -2638,52 +3066,10 @@ void QWindowsWindow::setFrameStrutEventsEnabled(bool enabled)
}
}
-static int getBorderWidth(const QPlatformScreen *screen)
-{
- NONCLIENTMETRICS ncm;
- QWindowsContext::nonClientMetricsForScreen(&ncm, screen);
- return ncm.iBorderWidth + ncm.iPaddedBorderWidth + 2;
-}
-
void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
{
- // We don't apply the min/max size hint as we change the dpi, because we did not adjust the
- // QScreen of the window yet so we don't have the min/max with the right ratio
- if (!testFlag(QWindowsWindow::WithinDpiChanged))
- QWindowsGeometryHint::applyToMinMaxInfo(window(), fullFrameMargins(), mmi);
-
- // This block fixes QTBUG-8361, QTBUG-4362: Frameless/title-less windows shouldn't cover the
- // taskbar when maximized
- if ((testFlag(WithinMaximize) || window()->windowStates().testFlag(Qt::WindowMinimized))
- && (m_data.flags.testFlag(Qt::FramelessWindowHint)
- || (m_data.flags.testFlag(Qt::CustomizeWindowHint) && !m_data.flags.testFlag(Qt::WindowTitleHint)))) {
- const QScreen *screen = window()->screen();
-
- // Documentation of MINMAXINFO states that it will only work for the primary screen
- if (screen && screen == QGuiApplication::primaryScreen()) {
- const QRect availableGeometry = QHighDpi::toNativePixels(screen->availableGeometry(), screen);
- mmi->ptMaxSize.y = availableGeometry.height();
-
- // Width, because you can have the taskbar on the sides too.
- mmi->ptMaxSize.x = availableGeometry.width();
-
- // If you have the taskbar on top, or on the left you don't want it at (0,0):
- mmi->ptMaxPosition.x = availableGeometry.x();
- mmi->ptMaxPosition.y = availableGeometry.y();
- if (!m_data.flags.testFlag(Qt::FramelessWindowHint)) {
- const int borderWidth = getBorderWidth(screen->handle());
- mmi->ptMaxSize.x += borderWidth * 2;
- mmi->ptMaxSize.y += borderWidth * 2;
- mmi->ptMaxTrackSize = mmi->ptMaxSize;
- mmi->ptMaxPosition.x -= borderWidth;
- mmi->ptMaxPosition.y -= borderWidth;
- }
- } else if (!screen){
- qWarning("window()->screen() returned a null screen");
- }
- }
-
- qCDebug(lcQpaWindows) << __FUNCTION__ << window() << *mmi;
+ QWindowsGeometryHint::applyToMinMaxInfo(window(), fullFrameMargins(), mmi);
+ qCDebug(lcQpaWindow) << __FUNCTION__ << window() << *mmi;
}
bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *result) const
@@ -2712,12 +3098,7 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re
return true;
}
if (localPos.y() < 0) {
- // We want to return HTCAPTION/true only over the outer sizing frame, not the entire title bar,
- // otherwise the title bar buttons (close, etc.) become unresponsive on Windows 7 (QTBUG-78262).
- // However, neither frameMargins() nor GetSystemMetrics(SM_CYSIZEFRAME), etc., give the correct
- // sizing frame height in all Windows versions/scales. This empirical constant seems to work, though.
- const int sizingHeight = 9;
- const int topResizeBarPos = sizingHeight - frameMargins().top();
+ const int topResizeBarPos = invisibleMargins(m_data.hwnd).left() - frameMargins().top();
if (localPos.y() < topResizeBarPos) {
*result = HTCAPTION; // Extend caption over top resize bar, let's user move the window.
return true;
@@ -2791,9 +3172,16 @@ void QWindowsWindow::applyCursor()
void QWindowsWindow::setCursor(const CursorHandlePtr &c)
{
#ifndef QT_NO_CURSOR
- if (c->handle() != m_cursor->handle()) {
+ bool changed = c->handle() != m_cursor->handle();
+ // QTBUG-98856: Cursors can get out of sync after restoring override
+ // cursors on native windows. Force an update.
+ if (testFlag(RestoreOverrideCursor)) {
+ clearFlag(RestoreOverrideCursor);
+ changed = true;
+ }
+ if (changed) {
const bool apply = applyNewCursor(window());
- qCDebug(lcQpaWindows) << window() << __FUNCTION__
+ qCDebug(lcQpaWindow) << window() << __FUNCTION__
<< c->handle() << " doApply=" << apply;
m_cursor = c;
if (apply)
@@ -2862,7 +3250,8 @@ void QWindowsWindow::setEnabled(bool enabled)
static HICON createHIcon(const QIcon &icon, int xSize, int ySize)
{
if (!icon.isNull()) {
- const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize)));
+ // QTBUG-90363, request DPR=1 for the title bar.
+ const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize)), 1);
if (!pm.isNull())
return qt_pixmapToWinHICON(pm);
}
@@ -2892,6 +3281,30 @@ bool QWindowsWindow::isTopLevel() const
return window()->isTopLevel() && !m_data.embedded;
}
+enum : WORD {
+ DwmwaUseImmersiveDarkMode = 20,
+ DwmwaUseImmersiveDarkModeBefore20h1 = 19
+};
+
+bool QWindowsWindow::setDarkBorderToWindow(HWND hwnd, bool d)
+{
+ const BOOL darkBorder = d ? TRUE : FALSE;
+ const bool ok =
+ SUCCEEDED(DwmSetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &darkBorder, sizeof(darkBorder)))
+ || SUCCEEDED(DwmSetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &darkBorder, sizeof(darkBorder)));
+ if (!ok)
+ qCWarning(lcQpaWindow, "%s: Unable to set %s window border.", __FUNCTION__, d ? "dark" : "light");
+ return ok;
+}
+
+void QWindowsWindow::setDarkBorder(bool d)
+{
+ // respect explicit opt-out and incompatible palettes or styles
+ d = d && shouldApplyDarkFrame(window());
+
+ setDarkBorderToWindow(m_data.hwnd, d);
+}
+
QWindowsMenuBar *QWindowsWindow::menuBar() const
{
return m_menuBar.data();
@@ -2902,6 +3315,13 @@ void QWindowsWindow::setMenuBar(QWindowsMenuBar *mb)
m_menuBar = mb;
}
+QMargins QWindowsWindow::customMargins() const
+{
+ if (m_data.flags & Qt::FramelessWindowHint)
+ return {};
+ return m_data.customMargins;
+}
+
/*!
\brief Sets custom margins to be added to the default margins determined by
the windows style in the handling of the WM_NCCALCSIZE message.
@@ -2914,6 +3334,10 @@ void QWindowsWindow::setMenuBar(QWindowsMenuBar *mb)
void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
{
+ if (m_data.flags & Qt::FramelessWindowHint) {
+ qCWarning(lcQpaWindow) << "You should not set custom margins for a frameless window.";
+ return;
+ }
if (newCustomMargins != m_data.customMargins) {
const QMargins oldCustomMargins = m_data.customMargins;
m_data.customMargins = newCustomMargins;
@@ -2922,7 +3346,7 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
const QPoint topLeft = currentFrameGeometry.topLeft();
QRect newFrame = currentFrameGeometry.marginsRemoved(oldCustomMargins) + m_data.customMargins;
newFrame.moveTo(topLeft);
- qCDebug(lcQpaWindows) << __FUNCTION__ << oldCustomMargins << "->" << newCustomMargins
+ qCDebug(lcQpaWindow) << __FUNCTION__ << oldCustomMargins << "->" << newCustomMargins
<< currentFrameGeometry << "->" << newFrame;
SetWindowPos(m_data.hwnd, nullptr, newFrame.x(), newFrame.y(), newFrame.width(), newFrame.height(), SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE);
}
@@ -2946,9 +3370,9 @@ void *QWindowsWindow::surface(void *nativeConfig, int *err)
return &m_vkSurface;
}
#elif defined(QT_NO_OPENGL)
- Q_UNUSED(err)
- Q_UNUSED(nativeConfig)
- return 0;
+ Q_UNUSED(err);
+ Q_UNUSED(nativeConfig);
+ return nullptr;
#endif
#ifndef QT_NO_OPENGL
if (!m_surface) {
@@ -2957,6 +3381,8 @@ void *QWindowsWindow::surface(void *nativeConfig, int *err)
}
return m_surface;
+#else
+ return nullptr;
#endif
}
@@ -2979,46 +3405,28 @@ void QWindowsWindow::invalidateSurface()
#endif // QT_NO_OPENGL
}
-void QWindowsWindow::setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes)
+void QWindowsWindow::registerTouchWindow()
{
- if (!window->handle())
+ if ((QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch) == 0)
return;
- static_cast<QWindowsWindow *>(window->handle())->registerTouchWindow(touchTypes);
-}
-void QWindowsWindow::registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes)
-{
- if ((QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch)
- && !testFlag(TouchRegistered)) {
- ULONG touchFlags = 0;
- const bool ret = IsTouchWindow(m_data.hwnd, &touchFlags);
- // Return if it is not a touch window or the flags are already set by a hook
- // such as HCBT_CREATEWND
- if (ret || touchFlags != 0)
+ // Initially register or re-register to change the flags
+ const auto touchTypes = QWindowsIntegration::instance()->touchWindowTouchType();
+ if (testFlag(TouchRegistered)) {
+ const auto currentTouchTypes = touchWindowTouchTypes_sys();
+ if (currentTouchTypes.has_value() && currentTouchTypes.value() == touchTypes)
return;
- if (RegisterTouchWindow(m_data.hwnd, ULONG(touchTypes)))
- setFlag(TouchRegistered);
- else
- qErrnoWarning("RegisterTouchWindow() failed for window '%s'.", qPrintable(window()->objectName()));
}
-}
-void QWindowsWindow::aboutToMakeCurrent()
-{
-#ifndef QT_NO_OPENGL
- // For RasterGLSurface windows, that become OpenGL windows dynamically, it might be
- // time to set up some GL specifics. This is particularly important for layered
- // windows (WS_EX_LAYERED due to alpha > 0).
- const bool isCompositing = qt_window_private(window())->compositing;
- if (isCompositing != testFlag(Compositing)) {
- if (isCompositing)
- setFlag(Compositing);
- else
- clearFlag(Compositing);
-
- updateGLWindowSettings(window(), m_data.hwnd, m_data.flags, m_opacity);
- }
-#endif
+ ULONG touchFlags = 0;
+ if (touchTypes.testFlag(TouchWindowTouchType::FineTouch))
+ touchFlags |= TWF_FINETOUCH;
+ if (touchTypes.testFlag(TouchWindowTouchType::WantPalmTouch))
+ touchFlags |= TWF_WANTPALM;
+ if (RegisterTouchWindow(m_data.hwnd, touchFlags))
+ setFlag(TouchRegistered);
+ else
+ qErrnoWarning("RegisterTouchWindow() failed for window '%s'.", qPrintable(window()->objectName()));
}
void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border)
@@ -3034,9 +3442,14 @@ void QWindowsWindow::setHasBorderInFullScreenDefault(bool border)
m_borderInFullScreenDefault = border;
}
+bool QWindowsWindow::hasBorderInFullScreen() const
+{
+ return testFlag(HasBorderInFullScreen);
+}
+
void QWindowsWindow::setHasBorderInFullScreen(bool border)
{
- if (testFlag(HasBorderInFullScreen) == border)
+ if (hasBorderInFullScreen() == border)
return;
if (border)
setFlag(HasBorderInFullScreen);
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 1f8800272b..024711e7f3 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -1,56 +1,23 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSWINDOW_H
#define QWINDOWSWINDOW_H
#include <QtCore/qt_windows.h>
#include <QtCore/qpointer.h>
+#include "qwindowsapplication.h"
#include "qwindowscursor.h"
#include <qpa/qplatformwindow.h>
-#include <QtPlatformHeaders/qwindowswindowfunctions.h>
+#include <qpa/qplatformwindow_p.h>
#if QT_CONFIG(vulkan)
#include "qwindowsvulkaninstance.h"
#endif
+#include <optional>
+
QT_BEGIN_NAMESPACE
class QWindowsOleDropTarget;
@@ -59,10 +26,11 @@ class QDebug;
struct QWindowsGeometryHint
{
- static QMargins frameOnPrimaryScreen(DWORD style, DWORD exStyle);
- static QMargins frameOnPrimaryScreen(HWND hwnd);
- static QMargins frame(DWORD style, DWORD exStyle, qreal dpi);
- static QMargins frame(HWND hwnd, DWORD style, DWORD exStyle);
+ static QMargins frameOnPrimaryScreen(const QWindow *w, DWORD style, DWORD exStyle);
+ static QMargins frameOnPrimaryScreen(const QWindow *w, HWND hwnd);
+ static QMargins frame(const QWindow *w, DWORD style, DWORD exStyle, qreal dpi);
+ static QMargins frame(const QWindow *w, HWND hwnd, DWORD style, DWORD exStyle);
+ static QMargins frame(const QWindow *w, HWND hwnd);
static QMargins frame(const QWindow *w, const QRect &geometry,
DWORD style, DWORD exStyle);
static bool handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result);
@@ -110,6 +78,7 @@ struct QWindowsWindowData
{
Qt::WindowFlags flags;
QRect geometry;
+ QRect restoreGeometry;
QMargins fullFrameMargins; // Do not use directly for windows, see FrameDirty.
QMargins customMargins; // User-defined, additional frame for NCCALCSIZE
HWND hwnd = nullptr;
@@ -121,10 +90,14 @@ struct QWindowsWindowData
const QString &title);
};
-class QWindowsBaseWindow : public QPlatformWindow
+class QWindowsBaseWindow : public QPlatformWindow,
+ public QNativeInterface::Private::QWindowsWindow
{
Q_DISABLE_COPY_MOVE(QWindowsBaseWindow)
public:
+ using TouchWindowTouchType = QNativeInterface::Private::QWindowsApplication::TouchWindowTouchType;
+ using TouchWindowTouchTypes = QNativeInterface::Private::QWindowsApplication::TouchWindowTouchTypes;
+
explicit QWindowsBaseWindow(QWindow *window) : QPlatformWindow(window) {}
WId winId() const override { return WId(handle()); }
@@ -134,6 +107,12 @@ public:
QPoint mapFromGlobal(const QPoint &pos) const override;
virtual QMargins fullFrameMargins() const { return frameMargins_sys(); }
+ void setHasBorderInFullScreen(bool border) override;
+ bool hasBorderInFullScreen() const override;
+
+ QMargins customMargins() const override;
+ void setCustomMargins(const QMargins &margins) override;
+
using QPlatformWindow::screenForGeometry;
virtual HWND handle() const = 0;
@@ -153,6 +132,7 @@ protected:
QRect geometry_sys() const;
void setGeometry_sys(const QRect &rect) const;
QMargins frameMargins_sys() const;
+ std::optional<TouchWindowTouchTypes> touchWindowTouchTypes_sys() const;
void hide_sys();
void raise_sys();
void lower_sys();
@@ -205,7 +185,6 @@ public:
WithinSetParent = 0x2,
WithinSetGeometry = 0x8,
OpenGLSurface = 0x10,
- OpenGL_ES2 = 0x20,
OpenGLDoubleBuffered = 0x40,
OpenGlPixelFormatInitialized = 0x80,
BlockedByModal = 0x100,
@@ -222,10 +201,11 @@ public:
MaximizeToFullScreen = 0x80000,
Compositing = 0x100000,
HasBorderInFullScreen = 0x200000,
- WithinDpiChanged = 0x400000,
- VulkanSurface = 0x800000,
- ResizeMoveActive = 0x1000000,
- DisableNonClientScaling = 0x2000000
+ VulkanSurface = 0x400000,
+ ResizeMoveActive = 0x800000,
+ DisableNonClientScaling = 0x1000000,
+ Direct3DSurface = 0x2000000,
+ RestoreOverrideCursor = 0x4000000
};
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
@@ -235,10 +215,12 @@ public:
using QPlatformWindow::screenForGeometry;
- QSurfaceFormat format() const override { return m_format; }
+ QSurfaceFormat format() const override;
void setGeometry(const QRect &rect) override;
QRect geometry() const override { return m_data.geometry; }
QRect normalGeometry() const override;
+ QRect restoreGeometry() const { return m_data.restoreGeometry; }
+ void updateRestoreGeometry();
void setVisible(bool visible) override;
bool isVisible() const;
@@ -277,8 +259,8 @@ public:
bool setMouseGrabEnabled(bool grab) override;
inline bool hasMouseCapture() const { return GetCapture() == m_data.hwnd; }
- bool startSystemResize(const QPoint &pos, Qt::Corner corner) override;
- bool startSystemMove(const QPoint &pos) override;
+ bool startSystemResize(Qt::Edges edges) override;
+ bool startSystemMove() override;
void setFrameStrutEventsEnabled(bool enabled) override;
bool frameStrutEventsEnabled() const override { return testFlag(FrameStrutEventsEnabled); }
@@ -287,21 +269,27 @@ public:
HWND handle() const override { return m_data.hwnd; }
bool isTopLevel() const override;
+ static bool setDarkBorderToWindow(HWND hwnd, bool d);
+ void setDarkBorder(bool d);
+
QWindowsMenuBar *menuBar() const;
void setMenuBar(QWindowsMenuBar *mb);
- QMargins customMargins() const { return m_data.customMargins; }
- void setCustomMargins(const QMargins &m);
+ QMargins customMargins() const override;
+ void setCustomMargins(const QMargins &m) override;
void setStyle(unsigned s) const;
void setExStyle(unsigned s) const;
- bool handleWmPaint(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+ bool handleWmPaint(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
void handleMoved();
- void handleResized(int wParam);
+ void handleResized(int wParam, LPARAM lParam);
void handleHidden();
void handleCompositionSettingsChanged();
+ void handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT *result);
+ void handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam);
+ void handleDpiChangedAfterParent(HWND hwnd);
static void displayChanged();
static void settingsChanged();
@@ -311,6 +299,7 @@ public:
static inline void *userDataOf(HWND hwnd);
static inline void setUserDataOf(HWND hwnd, void *ud);
+ static bool hasNoNativeFrame(HWND hwnd, Qt::WindowFlags flags);
static bool setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity);
bool isLayered() const;
@@ -335,7 +324,6 @@ public:
void *surface(void *nativeConfig, int *err);
void invalidateSurface() override;
- void aboutToMakeCurrent();
void setAlertState(bool enabled) override;
bool isAlertState() const override { return testFlag(AlertState); }
@@ -345,16 +333,20 @@ public:
enum ScreenChangeMode { FromGeometryChange, FromDpiChange };
void checkForScreenChanged(ScreenChangeMode mode = FromGeometryChange);
- static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes);
- void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch);
+ void registerTouchWindow();
static void setHasBorderInFullScreenStatic(QWindow *window, bool border);
static void setHasBorderInFullScreenDefault(bool border);
- void setHasBorderInFullScreen(bool border);
+ void setHasBorderInFullScreen(bool border) override;
+ bool hasBorderInFullScreen() const override;
static QString formatWindowTitle(const QString &title);
static const char *embeddedNativeParentHandleProperty;
static const char *hasBorderInFullScreenProperty;
+ void setSavedDpi(int dpi) { m_savedDpi = dpi; }
+ int savedDpi() const { return m_savedDpi; }
+ qreal dpiRelativeScale(const UINT dpi) const;
+
private:
inline void show_sys() const;
inline QWindowsWindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const;
@@ -370,6 +362,8 @@ private:
void handleWindowStateChange(Qt::WindowStates state);
inline void destroyIcon();
void fireExpose(const QRegion &region, bool force=false);
+ void fireFullExpose(bool force=false);
+ void calculateFullFrameMargins();
mutable QWindowsWindowData m_data;
QPointer<QWindowsMenuBar> m_menuBar;
@@ -383,10 +377,10 @@ private:
QWindowsOleDropTarget *m_dropTarget = nullptr;
unsigned m_savedStyle = 0;
QRect m_savedFrameGeometry;
- const QSurfaceFormat m_format;
HICON m_iconSmall = nullptr;
HICON m_iconBig = nullptr;
void *m_surface = nullptr;
+ int m_savedDpi = 96;
static bool m_screenForGLInitialized;
@@ -395,6 +389,7 @@ private:
VkSurfaceKHR m_vkSurface = VK_NULL_HANDLE;
#endif
static bool m_borderInFullScreenDefault;
+ static bool m_inSetgeometry;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
index c7c0deab3f..1abb412ccd 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
#include "qwindowsuiaaccessibility.h"
+#include "qwindowsuiautomation.h"
#include "qwindowsuiamainprovider.h"
#include "qwindowsuiautils.h"
@@ -50,12 +15,15 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtCore/qt_windows.h>
#include <qpa/qplatformintegration.h>
-#include <QtWindowsUIAutomationSupport/private/qwindowsuiawrapper_p.h>
+
+#include <QtCore/private/qwinregistry_p.h>
QT_BEGIN_NAMESPACE
using namespace QWindowsUiAutomation;
+using namespace Qt::Literals::StringLiterals;
+bool QWindowsUiaAccessibility::m_accessibleActive = false;
QWindowsUiaAccessibility::QWindowsUiaAccessibility()
{
@@ -70,6 +38,7 @@ bool QWindowsUiaAccessibility::handleWmGetObject(HWND hwnd, WPARAM wParam, LPARA
{
// Start handling accessibility internally
QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true);
+ m_accessibleActive = true;
// Ignoring all requests while starting up / shutting down
if (QCoreApplication::startingUp() || QCoreApplication::closingDown())
@@ -78,29 +47,83 @@ bool QWindowsUiaAccessibility::handleWmGetObject(HWND hwnd, WPARAM wParam, LPARA
if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) {
if (QAccessibleInterface *accessible = window->accessibleRoot()) {
QWindowsUiaMainProvider *provider = QWindowsUiaMainProvider::providerForAccessible(accessible);
- *lResult = QWindowsUiaWrapper::instance()->returnRawElementProvider(hwnd, wParam, lParam, provider);
+ *lResult = UiaReturnRawElementProvider(hwnd, wParam, lParam, provider);
return true;
}
}
return false;
}
+// Retrieve sound name by checking the icon property of a message box
+// should it be the event object.
+static QString alertSound(const QObject *object)
+{
+ if (object->inherits("QMessageBox")) {
+ enum MessageBoxIcon { // Keep in sync with QMessageBox::Icon
+ Information = 1,
+ Warning = 2,
+ Critical = 3
+ };
+ switch (object->property("icon").toInt()) {
+ case Information:
+ return QStringLiteral("SystemAsterisk");
+ case Warning:
+ return QStringLiteral("SystemExclamation");
+ case Critical:
+ return QStringLiteral("SystemHand");
+ }
+ return QString();
+ }
+ return QStringLiteral("SystemAsterisk");
+}
+
+static QString soundFileName(const QString &soundName)
+{
+ const QString key = "AppEvents\\Schemes\\Apps\\.Default\\"_L1
+ + soundName + "\\.Current"_L1;
+ return QWinRegistryKey(HKEY_CURRENT_USER, key).stringValue(L"");
+}
+
+static void playSystemSound(const QString &soundName)
+{
+ if (!soundName.isEmpty() && !soundFileName(soundName).isEmpty()) {
+ PlaySound(reinterpret_cast<const wchar_t *>(soundName.utf16()), nullptr,
+ SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT);
+ }
+}
+
// Handles accessibility update notifications.
void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
{
if (!event)
return;
- QAccessibleInterface *accessible = event->accessibleInterface();
- if (!isActive() || !accessible || !accessible->isValid())
+ // Always handle system sound events
+ switch (event->type()) {
+ case QAccessible::PopupMenuStart:
+ playSystemSound(QStringLiteral("MenuPopup"));
+ break;
+ case QAccessible::MenuCommand:
+ playSystemSound(QStringLiteral("MenuCommand"));
+ break;
+ case QAccessible::Alert:
+ playSystemSound(alertSound(event->object()));
+ break;
+ default:
+ break;
+ }
+
+ // Ignore events sent before the first UI Automation
+ // request or while QAccessible is being activated.
+ if (!m_accessibleActive)
return;
- // Ensures QWindowsUiaWrapper is properly initialized.
- if (!QWindowsUiaWrapper::instance()->ready())
+ QAccessibleInterface *accessible = event->accessibleInterface();
+ if (!isActive() || !accessible || !accessible->isValid())
return;
// No need to do anything when nobody is listening.
- if (!QWindowsUiaWrapper::instance()->clientsAreListening())
+ if (!UiaClientsAreListening())
return;
switch (event->type()) {
@@ -113,6 +136,9 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
case QAccessible::ValueChanged:
QWindowsUiaMainProvider::notifyValueChange(static_cast<QAccessibleValueChangeEvent *>(event));
break;
+ case QAccessible::NameChanged:
+ QWindowsUiaMainProvider::notifyNameChange(event);
+ break;
case QAccessible::SelectionAdd:
QWindowsUiaMainProvider::notifySelectionChange(event);
break;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h
index 48b4f9fa6a..2e8ee585da 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIAACCESSIBILITY_H
#define QWINDOWSUIAACCESSIBILITY_H
@@ -43,6 +7,7 @@
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
+#include <QtCore/qt_windows.h>
#include "qwindowscontext.h"
#include <qpa/qplatformaccessibility.h>
@@ -56,6 +21,8 @@ public:
virtual ~QWindowsUiaAccessibility();
static bool handleWmGetObject(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult);
void notifyAccessibilityUpdate(QAccessibleEvent *event) override;
+private:
+ static bool m_accessibleActive;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp
index 53c647512a..9abfcae247 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
index a20df28e3f..032679ab10 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIABASEPROVIDER_H
#define QWINDOWSUIABASEPROVIDER_H
@@ -46,8 +10,8 @@
#include <QtGui/qaccessible.h>
#include <QtCore/qpointer.h>
-#include <qwindowscombase.h>
-#include <QtWindowsUIAutomationSupport/private/qwindowsuiawrapper_p.h>
+#include "qwindowsuiautomation.h"
+#include <QtCore/private/qcomobject_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp
new file mode 100644
index 0000000000..8eb9baa8ef
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp
@@ -0,0 +1,90 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwindowsuiaexpandcollapseprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/qaccessible.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+static bool isExpanded(QAccessibleInterface *accessible)
+{
+ Q_ASSERT(accessible);
+ if (accessible->role() == QAccessible::MenuItem)
+ return accessible->childCount() > 0 && !accessible->child(0)->state().invisible;
+ else
+ return accessible->state().expandable && accessible->state().expanded;
+}
+
+QWindowsUiaExpandCollapseProvider::QWindowsUiaExpandCollapseProvider(QAccessible::Id id) :
+ QWindowsUiaBaseProvider(id)
+{
+}
+
+QWindowsUiaExpandCollapseProvider::~QWindowsUiaExpandCollapseProvider() = default;
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaExpandCollapseProvider::Expand()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleActionInterface *actionInterface = accessible->actionInterface();
+ if (!actionInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if (!isExpanded(accessible))
+ actionInterface->doAction(QAccessibleActionInterface::showMenuAction());
+
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaExpandCollapseProvider::Collapse()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleActionInterface *actionInterface = accessible->actionInterface();
+ if (!actionInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if (isExpanded(accessible))
+ actionInterface->doAction(QAccessibleActionInterface::showMenuAction());
+
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaExpandCollapseProvider::get_ExpandCollapseState(__RPC__out ExpandCollapseState *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = ExpandCollapseState_LeafNode;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = isExpanded(accessible) ? ExpandCollapseState_Expanded : ExpandCollapseState_Collapsed;
+
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.h
new file mode 100644
index 0000000000..b384eb521c
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.h
@@ -0,0 +1,33 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWINDOWSUIAEXPANDCOLLAPSEPROVIDER_H
+#define QWINDOWSUIAEXPANDCOLLAPSEPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwindowsuiabaseprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Expand/Collapse control pattern provider. Used for menu items with submenus.
+class QWindowsUiaExpandCollapseProvider : public QWindowsUiaBaseProvider,
+ public QComObject<IExpandCollapseProvider>
+{
+ Q_DISABLE_COPY_MOVE(QWindowsUiaExpandCollapseProvider)
+public:
+ explicit QWindowsUiaExpandCollapseProvider(QAccessible::Id id);
+ virtual ~QWindowsUiaExpandCollapseProvider() override;
+
+ // IExpandCollapseProvider
+ HRESULT STDMETHODCALLTYPE Expand() override;
+ HRESULT STDMETHODCALLTYPE Collapse() override;
+ HRESULT STDMETHODCALLTYPE get_ExpandCollapseState(__RPC__out ExpandCollapseState *pRetVal) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINDOWSUIAEXPANDCOLLAPSEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp
index 93d360c40b..a76128df58 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
index 3244122038..289a867869 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIAGRIDITEMPROVIDER_H
#define QWINDOWSUIAGRIDITEMPROVIDER_H
@@ -49,7 +13,7 @@ QT_BEGIN_NAMESPACE
// Implements the Grid Item control pattern provider. Used by items within a table/tree.
class QWindowsUiaGridItemProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<IGridItemProvider>
+ public QComObject<IGridItemProvider>
{
Q_DISABLE_COPY_MOVE(QWindowsUiaGridItemProvider)
public:
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp
index cce9d8143c..9f62ef5fbe 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
index 0e5f81108e..d33bbd0429 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIAGRIDPROVIDER_H
#define QWINDOWSUIAGRIDPROVIDER_H
@@ -48,8 +12,7 @@
QT_BEGIN_NAMESPACE
// Implements the Grid control pattern provider. Used by tables/trees.
-class QWindowsUiaGridProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<IGridProvider>
+class QWindowsUiaGridProvider : public QWindowsUiaBaseProvider, public QComObject<IGridProvider>
{
Q_DISABLE_COPY_MOVE(QWindowsUiaGridProvider)
public:
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp
index d09770bc81..e22c46ac4c 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
index 7d646894a1..ec006c673e 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIAINVOKEPROVIDER_H
#define QWINDOWSUIAINVOKEPROVIDER_H
@@ -48,8 +12,7 @@
QT_BEGIN_NAMESPACE
// Implements the Invoke control pattern provider.
-class QWindowsUiaInvokeProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<IInvokeProvider>
+class QWindowsUiaInvokeProvider : public QWindowsUiaBaseProvider, public QComObject<IInvokeProvider>
{
Q_DISABLE_COPY_MOVE(QWindowsUiaInvokeProvider)
public:
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index e5a9f275ae..95ddbcced6 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
@@ -53,7 +17,7 @@
#include "qwindowsuiagridprovider.h"
#include "qwindowsuiagriditemprovider.h"
#include "qwindowsuiawindowprovider.h"
-#include "qwindowscombase.h"
+#include "qwindowsuiaexpandcollapseprovider.h"
#include "qwindowscontext.h"
#include "qwindowsuiautils.h"
#include "qwindowsuiaprovidercache.h"
@@ -62,6 +26,7 @@
#include <QtGui/qaccessible.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qwindow.h>
+#include <qpa/qplatforminputcontextfactory_p.h>
#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU)
#include <comdef.h>
@@ -73,10 +38,13 @@ QT_BEGIN_NAMESPACE
using namespace QWindowsUiAutomation;
+QMutex QWindowsUiaMainProvider::m_mutex;
-// Returns a cached instance of the provider for a specific acessible interface.
+// Returns a cached instance of the provider for a specific accessible interface.
QWindowsUiaMainProvider *QWindowsUiaMainProvider::providerForAccessible(QAccessibleInterface *accessible)
{
+ QMutexLocker locker(&m_mutex);
+
if (!accessible)
return nullptr;
@@ -93,9 +61,8 @@ QWindowsUiaMainProvider *QWindowsUiaMainProvider::providerForAccessible(QAccessi
return provider;
}
-QWindowsUiaMainProvider::QWindowsUiaMainProvider(QAccessibleInterface *a, int initialRefCount)
- : QWindowsUiaBaseProvider(QAccessible::uniqueId(a)),
- m_ref(initialRefCount)
+QWindowsUiaMainProvider::QWindowsUiaMainProvider(QAccessibleInterface *a)
+ : QWindowsUiaBaseProvider(QAccessible::uniqueId(a))
{
}
@@ -106,9 +73,13 @@ QWindowsUiaMainProvider::~QWindowsUiaMainProvider()
void QWindowsUiaMainProvider::notifyFocusChange(QAccessibleEvent *event)
{
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
- if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
- QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_AutomationFocusChangedEventId);
+ // If this is a complex element, raise event for the focused child instead.
+ if (accessible->childCount()) {
+ if (QAccessibleInterface *child = accessible->focusChild())
+ accessible = child;
}
+ if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible))
+ UiaRaiseAutomationEvent(provider, UIA_AutomationFocusChangedEventId);
}
}
@@ -125,7 +96,7 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
if (accessible->state().checked)
toggleState = accessible->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On;
setVariantI4(toggleState, &newVal);
- QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ToggleToggleStatePropertyId, oldVal, newVal);
+ UiaRaiseAutomationPropertyChangedEvent(provider, UIA_ToggleToggleStatePropertyId, oldVal, newVal);
}
}
}
@@ -134,9 +105,13 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
// Notifies window opened/closed.
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
if (accessible->state().active) {
- QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Window_WindowOpenedEventId);
+ UiaRaiseAutomationEvent(provider, UIA_Window_WindowOpenedEventId);
+ if (QAccessibleInterface *focused = accessible->focusChild()) {
+ if (QWindowsUiaMainProvider *focusedProvider = providerForAccessible(focused))
+ UiaRaiseAutomationEvent(focusedProvider, UIA_AutomationFocusChangedEventId);
+ }
} else {
- QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Window_WindowClosedEventId);
+ UiaRaiseAutomationEvent(provider, UIA_Window_WindowClosedEventId);
}
}
}
@@ -163,13 +138,13 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
}
}
}
- if (event->value().type() == QVariant::String) {
+ if (event->value().typeId() == QMetaType::QString) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
// Notifies changes in string values.
VARIANT oldVal, newVal;
clearVariant(&oldVal);
setVariantString(event->value().toString(), &newVal);
- QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
+ UiaRaiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
}
} else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
@@ -177,7 +152,24 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
VARIANT oldVal, newVal;
clearVariant(&oldVal);
setVariantDouble(valueInterface->currentValue().toDouble(), &newVal);
- QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_RangeValueValuePropertyId, oldVal, newVal);
+ UiaRaiseAutomationPropertyChangedEvent(provider, UIA_RangeValueValuePropertyId, oldVal, newVal);
+ }
+ }
+ }
+}
+
+void QWindowsUiaMainProvider::notifyNameChange(QAccessibleEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ // Restrict notification to combo boxes, which need it for accessibility,
+ // in order to avoid slowdowns with unnecessary notifications.
+ if (accessible->role() == QAccessible::ComboBox) {
+ if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ VARIANT oldVal, newVal;
+ clearVariant(&oldVal);
+ setVariantString(accessible->text(QAccessible::Name), &newVal);
+ UiaRaiseAutomationPropertyChangedEvent(provider, UIA_NamePropertyId, oldVal, newVal);
+ ::SysFreeString(newVal.bstrVal);
}
}
}
@@ -187,7 +179,7 @@ void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event)
{
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
- QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_SelectionItem_ElementSelectedEventId);
+ UiaRaiseAutomationEvent(provider, UIA_SelectionItem_ElementSelectedEventId);
}
}
}
@@ -199,13 +191,13 @@ void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
if (accessible->textInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
if (event->type() == QAccessible::TextSelectionChanged) {
- QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId);
+ UiaRaiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId);
} else if (event->type() == QAccessible::TextCaretMoved) {
if (!accessible->state().readOnly) {
- QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId);
+ UiaRaiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId);
}
} else {
- QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Text_TextChangedEventId);
+ UiaRaiseAutomationEvent(provider, UIA_Text_TextChangedEventId);
}
}
}
@@ -214,31 +206,26 @@ void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
HRESULT STDMETHODCALLTYPE QWindowsUiaMainProvider::QueryInterface(REFIID iid, LPVOID *iface)
{
- if (!iface)
- return E_INVALIDARG;
- *iface = nullptr;
-
- QAccessibleInterface *accessible = accessibleInterface();
+ HRESULT result = QComObject::QueryInterface(iid, iface);
- const bool result = qWindowsComQueryUnknownInterfaceMulti<IRawElementProviderSimple>(this, iid, iface)
- || qWindowsComQueryInterface<IRawElementProviderSimple>(this, iid, iface)
- || qWindowsComQueryInterface<IRawElementProviderFragment>(this, iid, iface)
- || (accessible && hwndForAccessible(accessible) && qWindowsComQueryInterface<IRawElementProviderFragmentRoot>(this, iid, iface));
- return result ? S_OK : E_NOINTERFACE;
-}
+ if (SUCCEEDED(result) && iid == __uuidof(IRawElementProviderFragmentRoot)) {
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (accessible && hwndForAccessible(accessible)) {
+ result = S_OK;
+ } else {
+ result = E_NOINTERFACE;
+ iface = nullptr;
+ }
+ }
-ULONG QWindowsUiaMainProvider::AddRef()
-{
- return ++m_ref;
+ return result;
}
ULONG STDMETHODCALLTYPE QWindowsUiaMainProvider::Release()
{
- if (!--m_ref) {
- delete this;
- return 0;
- }
- return m_ref;
+ QMutexLocker locker(&m_mutex);
+
+ return QComObject::Release();
}
HRESULT QWindowsUiaMainProvider::get_ProviderOptions(ProviderOptions *pRetVal)
@@ -288,21 +275,25 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow
}
break;
case UIA_TogglePatternId:
- // Checkbox controls.
- if (accessible->role() == QAccessible::CheckBox) {
+ // Checkboxes and other checkable controls.
+ if (accessible->state().checkable)
*pRetVal = new QWindowsUiaToggleProvider(id());
- }
break;
case UIA_SelectionPatternId:
- // Lists of items.
- if (accessible->role() == QAccessible::List) {
+ case UIA_SelectionPattern2Id:
+ // Selections via QAccessibleSelectionInterface or lists of items.
+ if (accessible->selectionInterface()
+ || accessible->role() == QAccessible::List
+ || accessible->role() == QAccessible::PageTabList) {
*pRetVal = new QWindowsUiaSelectionProvider(id());
}
break;
case UIA_SelectionItemPatternId:
- // Items within a list and radio buttons.
- if ((accessible->role() == QAccessible::RadioButton)
- || (accessible->role() == QAccessible::ListItem)) {
+ // Parent supports selection interface or items within a list and radio buttons.
+ if ((accessible->parent() && accessible->parent()->selectionInterface())
+ || (accessible->role() == QAccessible::RadioButton)
+ || (accessible->role() == QAccessible::ListItem)
+ || (accessible->role() == QAccessible::PageTab)) {
*pRetVal = new QWindowsUiaSelectionItemProvider(id());
}
break;
@@ -340,6 +331,16 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow
*pRetVal = new QWindowsUiaInvokeProvider(id());
}
break;
+ case UIA_ExpandCollapsePatternId:
+ // Menu items with submenus.
+ if ((accessible->role() == QAccessible::MenuItem
+ && accessible->childCount() > 0
+ && accessible->child(0)->role() == QAccessible::PopupMenu)
+ || accessible->role() == QAccessible::ComboBox
+ || (accessible->role() == QAccessible::TreeItem && accessible->state().expandable)) {
+ *pRetVal = new QWindowsUiaExpandCollapseProvider(id());
+ }
+ break;
default:
break;
}
@@ -347,6 +348,28 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow
return S_OK;
}
+void QWindowsUiaMainProvider::fillVariantArrayForRelation(QAccessibleInterface* accessible,
+ QAccessible::Relation relation, VARIANT *pRetVal)
+{
+ Q_ASSERT(accessible);
+
+ typedef QPair<QAccessibleInterface*, QAccessible::Relation> RelationPair;
+ const QList<RelationPair> relationInterfaces = accessible->relations(relation);
+ if (relationInterfaces.empty())
+ return;
+
+ SAFEARRAY *elements = SafeArrayCreateVector(VT_UNKNOWN, 0, relationInterfaces.size());
+ for (LONG i = 0; i < relationInterfaces.size(); ++i) {
+ if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(relationInterfaces.at(i).first)) {
+ SafeArrayPutElement(elements, &i, static_cast<IRawElementProviderSimple*>(childProvider));
+ childProvider->Release();
+ }
+ }
+
+ pRetVal->vt = VT_UNKNOWN | VT_ARRAY;
+ pRetVal->parray = elements;
+}
+
HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pRetVal)
{
qCDebug(lcQpaUiAutomation) << __FUNCTION__ << idProp;
@@ -377,10 +400,19 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
case UIA_ClassNamePropertyId:
// Class name.
if (QObject *o = accessible->object()) {
- QString className = QLatin1String(o->metaObject()->className());
+ QString className = QLatin1StringView(o->metaObject()->className());
setVariantString(className, pRetVal);
}
break;
+ case UIA_DescribedByPropertyId:
+ fillVariantArrayForRelation(accessible, QAccessible::DescriptionFor, pRetVal);
+ break;
+ case UIA_FlowsFromPropertyId:
+ fillVariantArrayForRelation(accessible, QAccessible::FlowsTo, pRetVal);
+ break;
+ case UIA_FlowsToPropertyId:
+ fillVariantArrayForRelation(accessible, QAccessible::FlowsFrom, pRetVal);
+ break;
case UIA_FrameworkIdPropertyId:
setVariantString(QStringLiteral("Qt"), pRetVal);
break;
@@ -392,12 +424,14 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
// Control type converted from role.
auto controlType = roleToControlTypeId(accessible->role());
- // The native OSK should be disbled if the Qt OSK is in use.
- static bool imModuleEmpty = qEnvironmentVariableIsEmpty("QT_IM_MODULE");
+ // The native OSK should be disabled if the Qt OSK is in use,
+ // or if disabled via application attribute.
+ static bool imModuleEmpty = QPlatformInputContextFactory::requested().isEmpty();
+ bool nativeVKDisabled = QCoreApplication::testAttribute(Qt::AA_DisableNativeVirtualKeyboard);
// If we want to disable the native OSK auto-showing
// we have to report text fields as non-editable.
- if (controlType == UIA_EditControlTypeId && !imModuleEmpty)
+ if (controlType == UIA_EditControlTypeId && (!imModuleEmpty || nativeVKDisabled))
controlType = UIA_TextControlTypeId;
setVariantI4(controlType, pRetVal);
@@ -445,6 +479,10 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
setVariantBool(wt == Qt::Popup || wt == Qt::ToolTip || wt == Qt::SplashScreen, pRetVal);
}
break;
+ case UIA_IsDialogPropertyId:
+ setVariantBool(accessible->role() == QAccessible::Dialog
+ || accessible->role() == QAccessible::AlertMessage, pRetVal);
+ break;
case UIA_FullDescriptionPropertyId:
setVariantString(accessible->text(QAccessible::Description), pRetVal);
break;
@@ -470,9 +508,9 @@ QString QWindowsUiaMainProvider::automationIdForAccessible(const QAccessibleInte
while (obj) {
QString name = obj->objectName();
if (name.isEmpty())
- return QString();
+ return result;
if (!result.isEmpty())
- result.prepend(QLatin1Char('.'));
+ result.prepend(u'.');
result.prepend(name);
obj = obj->parent();
}
@@ -491,7 +529,7 @@ HRESULT QWindowsUiaMainProvider::get_HostRawElementProvider(IRawElementProviderS
// Returns a host provider only for controls associated with a native window handle. Others should return NULL.
if (QAccessibleInterface *accessible = accessibleInterface()) {
if (HWND hwnd = hwndForAccessible(accessible)) {
- return QWindowsUiaWrapper::instance()->hostProviderFromHwnd(hwnd, pRetVal);
+ return UiaHostProviderFromHwnd(hwnd, pRetVal);
}
}
return S_OK;
@@ -681,26 +719,18 @@ HRESULT QWindowsUiaMainProvider::ElementProviderFromPoint(double x, double y, IR
QPoint point;
nativeUiaPointToPoint(uiaPoint, window, &point);
- if (auto targetacc = accessible->childAt(point.x(), point.y())) {
- auto acc = accessible->childAt(point.x(), point.y());
- // Reject the cases where childAt() returns a different instance in each call for the same
- // element (e.g., QAccessibleTree), as it causes an endless loop with Youdao Dictionary installed.
- if (targetacc == acc) {
- // Controls can be embedded within grouping elements. By default returns the innermost control.
- while (acc) {
- targetacc = acc;
- // For accessibility tools it may be better to return the text element instead of its subcomponents.
- if (targetacc->textInterface()) break;
- acc = targetacc->childAt(point.x(), point.y());
- if (acc != targetacc->childAt(point.x(), point.y())) {
- qCDebug(lcQpaUiAutomation) << "Non-unique childAt() for" << targetacc;
- break;
- }
- }
- *pRetVal = providerForAccessible(targetacc);
- } else {
- qCDebug(lcQpaUiAutomation) << "Non-unique childAt() for" << accessible;
+ QAccessibleInterface *targetacc = accessible->childAt(point.x(), point.y());
+
+ if (targetacc) {
+ QAccessibleInterface *acc = targetacc;
+ // Controls can be embedded within grouping elements. By default returns the innermost control.
+ while (acc) {
+ targetacc = acc;
+ // For accessibility tools it may be better to return the text element instead of its subcomponents.
+ if (targetacc->textInterface()) break;
+ acc = acc->childAt(point.x(), point.y());
}
+ *pRetVal = providerForAccessible(targetacc);
}
return S_OK;
}
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
index cdc239ed99..99db0ed318 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIAMAINPROVIDER_H
#define QWINDOWSUIAMAINPROVIDER_H
@@ -47,6 +11,7 @@
#include <QtCore/qpointer.h>
#include <QtCore/qsharedpointer.h>
+#include <QtCore/qmutex.h>
#include <QtCore/qt_windows.h>
#include <QtGui/qaccessible.h>
@@ -55,25 +20,23 @@ QT_BEGIN_NAMESPACE
// The main UI Automation class.
class QWindowsUiaMainProvider :
public QWindowsUiaBaseProvider,
- public IRawElementProviderSimple,
- public IRawElementProviderFragment,
- public IRawElementProviderFragmentRoot
+ public QComObject<IRawElementProviderSimple, IRawElementProviderFragment, IRawElementProviderFragmentRoot>
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(QWindowsUiaMainProvider)
public:
static QWindowsUiaMainProvider *providerForAccessible(QAccessibleInterface *accessible);
- explicit QWindowsUiaMainProvider(QAccessibleInterface *a, int initialRefCount = 1);
+ explicit QWindowsUiaMainProvider(QAccessibleInterface *a);
virtual ~QWindowsUiaMainProvider();
static void notifyFocusChange(QAccessibleEvent *event);
static void notifyStateChange(QAccessibleStateChangeEvent *event);
static void notifyValueChange(QAccessibleValueChangeEvent *event);
+ static void notifyNameChange(QAccessibleEvent *event);
static void notifySelectionChange(QAccessibleEvent *event);
static void notifyTextChange(QAccessibleEvent *event);
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) override;
- ULONG STDMETHODCALLTYPE AddRef() override;
ULONG STDMETHODCALLTYPE Release() override;
// IRawElementProviderSimple methods
@@ -96,7 +59,8 @@ public:
private:
QString automationIdForAccessible(const QAccessibleInterface *accessible);
- ULONG m_ref;
+ static void fillVariantArrayForRelation(QAccessibleInterface *accessible, QAccessible::Relation relation, VARIANT *pRetVal);
+ static QMutex m_mutex;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp
index c55e827a46..ba2a88bb4e 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
@@ -75,7 +39,7 @@ void QWindowsUiaProviderCache::insert(QAccessible::Id id, QWindowsUiaBaseProvide
m_providerTable[id] = provider;
m_inverseTable[provider] = id;
// Connects the destroyed signal to our slot, to remove deleted objects from the cache.
- QObject::connect(provider, &QObject::destroyed, this, &QWindowsUiaProviderCache::objectDestroyed);
+ QObject::connect(provider, &QObject::destroyed, this, &QWindowsUiaProviderCache::objectDestroyed, Qt::DirectConnection);
}
}
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h
index f66dc2c170..08f315b4e6 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIAPROVIDERCACHE_H
#define QWINDOWSUIAPROVIDERCACHE_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp
index 7c1827387a..574bb7d2d6 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
index fc82d3a2cc..ffb5ae155b 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIARANGEVALUEPROVIDER_H
#define QWINDOWSUIARANGEVALUEPROVIDER_H
@@ -49,7 +13,7 @@ QT_BEGIN_NAMESPACE
// Implements the Range Value control pattern provider.
class QWindowsUiaRangeValueProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<IRangeValueProvider>
+ public QComObject<IRangeValueProvider>
{
Q_DISABLE_COPY_MOVE(QWindowsUiaRangeValueProvider)
public:
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp
index a93a05c7bc..95bc2f7570 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
@@ -72,12 +36,20 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::Select()
if (!accessible)
return UIA_E_ELEMENTNOTAVAILABLE;
+ if (QAccessibleInterface *parent = accessible->parent()) {
+ if (QAccessibleSelectionInterface *selectionInterface = parent->selectionInterface()) {
+ selectionInterface->clear();
+ bool ok = selectionInterface->select(accessible);
+ return ok ? S_OK : S_FALSE;
+ }
+ }
+
QAccessibleActionInterface *actionInterface = accessible->actionInterface();
if (!actionInterface)
return UIA_E_ELEMENTNOTAVAILABLE;
- if (accessible->role() == QAccessible::RadioButton) {
- // For radio buttons we just invoke the selection action; others are automatically deselected.
+ if (accessible->role() == QAccessible::RadioButton || accessible->role() == QAccessible::PageTab) {
+ // For radio buttons/tabs we just invoke the selection action; others are automatically deselected.
actionInterface->doAction(QAccessibleActionInterface::pressAction());
} else {
// Toggle list item if not already selected. It must be done first to support all selection modes.
@@ -109,12 +81,19 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::AddToSelection()
if (!accessible)
return UIA_E_ELEMENTNOTAVAILABLE;
+ if (QAccessibleInterface *parent = accessible->parent()) {
+ if (QAccessibleSelectionInterface *selectionInterface = parent->selectionInterface()) {
+ bool ok = selectionInterface->select(accessible);
+ return ok ? S_OK : S_FALSE;
+ }
+ }
+
QAccessibleActionInterface *actionInterface = accessible->actionInterface();
if (!actionInterface)
return UIA_E_ELEMENTNOTAVAILABLE;
- if (accessible->role() == QAccessible::RadioButton) {
- // For radio buttons we invoke the selection action.
+ if (accessible->role() == QAccessible::RadioButton || accessible->role() == QAccessible::PageTab) {
+ // For radio buttons and tabs we invoke the selection action.
actionInterface->doAction(QAccessibleActionInterface::pressAction());
} else {
// Toggle list item if not already selected.
@@ -134,11 +113,18 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::RemoveFromSelection(
if (!accessible)
return UIA_E_ELEMENTNOTAVAILABLE;
+ if (QAccessibleInterface *parent = accessible->parent()) {
+ if (QAccessibleSelectionInterface *selectionInterface = parent->selectionInterface()) {
+ bool ok = selectionInterface->unselect(accessible);
+ return ok ? S_OK : S_FALSE;
+ }
+ }
+
QAccessibleActionInterface *actionInterface = accessible->actionInterface();
if (!actionInterface)
return UIA_E_ELEMENTNOTAVAILABLE;
- if (accessible->role() != QAccessible::RadioButton) {
+ if (accessible->role() != QAccessible::RadioButton && accessible->role() != QAccessible::PageTab) {
if (accessible->state().selected) {
actionInterface->doAction(QAccessibleActionInterface::toggleAction());
}
@@ -160,8 +146,18 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_IsSelected(BOOL
if (!accessible)
return UIA_E_ELEMENTNOTAVAILABLE;
+ if (QAccessibleInterface *parent = accessible->parent()) {
+ if (QAccessibleSelectionInterface *selectionInterface = parent->selectionInterface()) {
+ bool selected = selectionInterface->isSelected(accessible);
+ *pRetVal = selected ? TRUE : FALSE;
+ return S_OK;
+ }
+ }
+
if (accessible->role() == QAccessible::RadioButton)
*pRetVal = accessible->state().checked;
+ else if (accessible->role() == QAccessible::PageTab)
+ *pRetVal = accessible->state().focused;
else
*pRetVal = accessible->state().selected;
return S_OK;
@@ -180,16 +176,21 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContain
if (!accessible)
return UIA_E_ELEMENTNOTAVAILABLE;
+ QAccessibleInterface *parent = accessible->parent();
+ if (parent && parent->selectionInterface()) {
+ *pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent);
+ return S_OK;
+ }
+
QAccessibleActionInterface *actionInterface = accessible->actionInterface();
if (!actionInterface)
return UIA_E_ELEMENTNOTAVAILABLE;
// Radio buttons do not require a container.
- if (accessible->role() == QAccessible::ListItem) {
- if (QAccessibleInterface *parent = accessible->parent()) {
- if (parent->role() == QAccessible::List) {
- *pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent);
- }
+ if (parent) {
+ if ((accessible->role() == QAccessible::ListItem && parent->role() == QAccessible::List)
+ || (accessible->role() == QAccessible::PageTab && parent->role() == QAccessible::PageTabList)) {
+ *pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent);
}
}
return S_OK;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
index 4b59c4e40f..ee34fd9edd 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIASELECTIONITEMPROVIDER_H
#define QWINDOWSUIASELECTIONITEMPROVIDER_H
@@ -49,7 +13,7 @@ QT_BEGIN_NAMESPACE
// Implements the Selection Item control pattern provider. Used for List items and radio buttons.
class QWindowsUiaSelectionItemProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<ISelectionItemProvider>
+ public QComObject<ISelectionItemProvider>
{
Q_DISABLE_COPY_MOVE(QWindowsUiaSelectionItemProvider)
public:
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp
index fb41012cf4..37148c655a 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
@@ -49,7 +13,6 @@
#include <QtCore/qloggingcategory.h>
#include <QtCore/qstring.h>
#include <QtCore/qlist.h>
-#include <QtCore/qvector.h>
QT_BEGIN_NAMESPACE
@@ -78,12 +41,24 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::GetSelection(SAFEARRAY *
if (!accessible)
return UIA_E_ELEMENTNOTAVAILABLE;
- // First put selected items in a list, then build a safe array with the right size.
- QVector<QAccessibleInterface *> selectedList;
- for (int i = 0; i < accessible->childCount(); ++i) {
- if (QAccessibleInterface *child = accessible->child(i)) {
- if (child->state().selected) {
- selectedList.append(child);
+ // First get/create list of selected items, then build a safe array with the right size.
+ QList<QAccessibleInterface *> selectedList;
+ if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface()) {
+ selectedList = selectionInterface->selectedItems();
+ } else {
+ const int childCount = accessible->childCount();
+ selectedList.reserve(childCount);
+ for (int i = 0; i < childCount; ++i) {
+ if (QAccessibleInterface *child = accessible->child(i)) {
+ if (accessible->role() == QAccessible::PageTabList) {
+ if (child->role() == QAccessible::PageTab && child->state().focused) {
+ selectedList.append(child);
+ }
+ } else {
+ if (child->state().selected) {
+ selectedList.append(child);
+ }
+ }
}
}
}
@@ -127,18 +102,155 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_IsSelectionRequired(
if (!accessible)
return UIA_E_ELEMENTNOTAVAILABLE;
- // Initially returns false if none are selected. After the first selection, it may be required.
- bool anySelected = false;
- for (int i = 0; i < accessible->childCount(); ++i) {
- if (QAccessibleInterface *child = accessible->child(i)) {
- if (child->state().selected) {
- anySelected = true;
- break;
+ if (accessible->role() == QAccessible::PageTabList) {
+ *pRetVal = TRUE;
+ } else {
+
+ // Initially returns false if none are selected. After the first selection, it may be required.
+ bool anySelected = false;
+ if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface()) {
+ anySelected = selectionInterface->selectedItem(0) != nullptr;
+ } else {
+ for (int i = 0; i < accessible->childCount(); ++i) {
+ if (QAccessibleInterface *child = accessible->child(i)) {
+ if (child->state().selected) {
+ anySelected = true;
+ break;
+ }
+ }
+ }
+ }
+
+ *pRetVal = anySelected && !accessible->state().multiSelectable && !accessible->state().extSelectable;
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_FirstSelectedItem(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleInterface *firstSelectedChild = nullptr;
+ if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface()) {
+ firstSelectedChild = selectionInterface->selectedItem(0);
+ if (!firstSelectedChild)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+ } else {
+ int i = 0;
+ while (!firstSelectedChild && i < accessible->childCount()) {
+ if (QAccessibleInterface *child = accessible->child(i)) {
+ if (accessible->role() == QAccessible::PageTabList) {
+ if (child->role() == QAccessible::PageTab && child->state().focused)
+ firstSelectedChild = child;
+ } else if (child->state().selected) {
+ firstSelectedChild = child;
+ }
+ }
+ i++;
+ }
+ }
+
+ if (!firstSelectedChild)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(firstSelectedChild))
+ {
+ *pRetVal = static_cast<IRawElementProviderSimple *>(childProvider);
+ return S_OK;
+ }
+
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_LastSelectedItem(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleInterface *lastSelectedChild = nullptr;
+ if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface()) {
+ const int selectedItemCount = selectionInterface->selectedItemCount();
+ if (selectedItemCount <= 0)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+ lastSelectedChild = selectionInterface->selectedItem(selectedItemCount - 1);
+ } else {
+ int i = accessible->childCount() - 1;
+ while (!lastSelectedChild && i >= 0) {
+ if (QAccessibleInterface *child = accessible->child(i)) {
+ if (accessible->role() == QAccessible::PageTabList) {
+ if (child->role() == QAccessible::PageTab && child->state().focused)
+ lastSelectedChild = child;
+ } else if (child->state().selected) {
+ lastSelectedChild = child;
+ }
+ }
+ i--;
+ }
+ }
+
+ if (!lastSelectedChild)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(lastSelectedChild))
+ {
+ *pRetVal = static_cast<IRawElementProviderSimple *>(childProvider);
+ return S_OK;
+ }
+
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_CurrentSelectedItem(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ return get_FirstSelectedItem(pRetVal);
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_ItemCount(__RPC__out int *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = -1;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+
+ if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface())
+ *pRetVal = selectionInterface->selectedItemCount();
+ else {
+ int selectedCount = 0;
+ for (int i = 0; i < accessible->childCount(); i++) {
+ if (QAccessibleInterface *child = accessible->child(i)) {
+ if (accessible->role() == QAccessible::PageTabList) {
+ if (child->role() == QAccessible::PageTab && child->state().focused)
+ selectedCount++;
+ } else if (child->state().selected) {
+ selectedCount++;
+ }
}
}
+ *pRetVal = selectedCount;
}
- *pRetVal = anySelected && !accessible->state().multiSelectable && !accessible->state().extSelectable;
return S_OK;
}
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
index ee1044ec7a..7a899e4261 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIASELECTIONPROVIDER_H
#define QWINDOWSUIASELECTIONPROVIDER_H
@@ -47,9 +11,22 @@
QT_BEGIN_NAMESPACE
+namespace QtPrivate {
+
+template <>
+struct QComObjectTraits<ISelectionProvider2>
+{
+ static constexpr bool isGuidOf(REFIID riid) noexcept
+ {
+ return QComObjectTraits<ISelectionProvider2, ISelectionProvider>::isGuidOf(riid);
+ }
+};
+
+} // namespace QtPrivate
+
// Implements the Selection control pattern provider. Used for Lists.
class QWindowsUiaSelectionProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<ISelectionProvider>
+ public QComObject<ISelectionProvider2>
{
Q_DISABLE_COPY_MOVE(QWindowsUiaSelectionProvider)
public:
@@ -60,6 +37,12 @@ public:
HRESULT STDMETHODCALLTYPE GetSelection(SAFEARRAY **pRetVal) override;
HRESULT STDMETHODCALLTYPE get_CanSelectMultiple(BOOL *pRetVal) override;
HRESULT STDMETHODCALLTYPE get_IsSelectionRequired(BOOL *pRetVal) override;
+
+ // ISelectionProvider2
+ HRESULT STDMETHODCALLTYPE get_FirstSelectedItem(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_LastSelectedItem(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_CurrentSelectedItem(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_ItemCount(__RPC__out int *pRetVal) override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp
index 1348ec7cc0..f92c4b3af7 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
index 9804c35f8e..3bb0e1027e 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIATABLEITEMPROVIDER_H
#define QWINDOWSUIATABLEITEMPROVIDER_H
@@ -49,7 +13,7 @@ QT_BEGIN_NAMESPACE
// Implements the Table Item control pattern provider. Used by items within a table/tree.
class QWindowsUiaTableItemProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<ITableItemProvider>
+ public QComObject<ITableItemProvider>
{
Q_DISABLE_COPY_MOVE(QWindowsUiaTableItemProvider)
public:
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp
index 80086f1d4f..9c7ede882d 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
index a8b16035ec..8beb11decf 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIATABLEPROVIDER_H
#define QWINDOWSUIATABLEPROVIDER_H
@@ -48,8 +12,7 @@
QT_BEGIN_NAMESPACE
// Implements the Table control pattern provider. Used by tables/trees.
-class QWindowsUiaTableProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<ITableProvider>
+class QWindowsUiaTableProvider : public QWindowsUiaBaseProvider, public QComObject<ITableProvider>
{
Q_DISABLE_COPY_MOVE(QWindowsUiaTableProvider)
public:
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
index 50ecfc7ecd..172836232e 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
@@ -62,20 +26,6 @@ QWindowsUiaTextProvider::~QWindowsUiaTextProvider()
{
}
-HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::QueryInterface(REFIID iid, LPVOID *iface)
-{
- qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
-
- if (!iface)
- return E_INVALIDARG;
- *iface = nullptr;
-
- const bool result = qWindowsComQueryUnknownInterfaceMulti<ITextProvider>(this, iid, iface)
- || qWindowsComQueryInterface<ITextProvider>(this, iid, iface)
- || qWindowsComQueryInterface<ITextProvider2>(this, iid, iface);
- return result ? S_OK : E_NOINTERFACE;
-}
-
// Returns an array of providers for the selected text ranges.
HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetSelection(SAFEARRAY **pRetVal)
{
@@ -182,9 +132,10 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::RangeFromPoint(UiaPoint point
nativeUiaPointToPoint(point, window, &pt);
int offset = textInterface->offsetAtPoint(pt);
- if ((offset >= 0) && (offset < textInterface->characterCount())) {
- *pRetVal = new QWindowsUiaTextRangeProvider(id(), offset, offset);
- }
+ if (offset < 0 || offset >= textInterface->characterCount())
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = new QWindowsUiaTextRangeProvider(id(), offset, offset);
return S_OK;
}
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
index ffab48b0e8..8f886510b4 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIATEXTPROVIDER_H
#define QWINDOWSUIATEXTPROVIDER_H
@@ -48,18 +12,27 @@
QT_BEGIN_NAMESPACE
+namespace QtPrivate {
+
+template <>
+struct QComObjectTraits<ITextProvider2>
+{
+ static constexpr bool isGuidOf(REFIID riid) noexcept
+ {
+ return QComObjectTraits<ITextProvider2, ITextProvider>::isGuidOf(riid);
+ }
+};
+
+} // namespace QtPrivate
+
// Implements the Text control pattern provider. Used for text controls.
-class QWindowsUiaTextProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<ITextProvider2>
+class QWindowsUiaTextProvider : public QWindowsUiaBaseProvider, public QComObject<ITextProvider2>
{
Q_DISABLE_COPY_MOVE(QWindowsUiaTextProvider)
public:
explicit QWindowsUiaTextProvider(QAccessible::Id id);
~QWindowsUiaTextProvider();
- // IUnknown overrides
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) override;
-
// ITextProvider
HRESULT STDMETHODCALLTYPE GetSelection(SAFEARRAY **pRetVal) override;
HRESULT STDMETHODCALLTYPE GetVisibleRanges(SAFEARRAY **pRetVal) override;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
index d8b8f7281d..a62a33cfe2 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
@@ -143,7 +107,9 @@ HRESULT QWindowsUiaTextRangeProvider::ExpandToEnclosingUnit(TextUnit unit)
m_endOffset = m_startOffset + 1;
} else {
QString text = textInterface->text(0, len);
- for (int t = m_startOffset; t >= 0; --t) {
+ const int start = m_startOffset >= 0 && m_startOffset < len
+ ? m_startOffset : len - 1;
+ for (int t = start; t >= 0; --t) {
if (!isTextUnitSeparator(unit, text[t]) && ((t == 0) || isTextUnitSeparator(unit, text[t - 1]))) {
m_startOffset = t;
break;
@@ -201,6 +167,15 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTextRangeProvider::GetAttributeValue(TEXTAT
else
setVariantI4(CaretPosition_Unknown, pRetVal);
break;
+ case UIA_StrikethroughStyleAttributeId:
+ {
+ const QString value = valueForIA2Attribute(textInterface, QStringLiteral("text-line-through-type"));
+ if (value.isEmpty())
+ break;
+ const TextDecorationLineStyle uiaLineStyle = uiaLineStyleForIA2LineStyle(value);
+ setVariantI4(uiaLineStyle, pRetVal);
+ break;
+ }
default:
break;
}
@@ -341,14 +316,14 @@ HRESULT QWindowsUiaTextRangeProvider::Move(TextUnit unit, int count, int *pRetVa
int len = textInterface->characterCount();
- if (len < 1)
+ if (len < 1 || count == 0) // MSDN: "Zero has no effect."
return S_OK;
if (unit == TextUnit_Character) {
// Moves the start point, ensuring it lies within the bounds.
- int start = qBound(0, m_startOffset + count, len - 1);
+ int start = qBound(0, m_startOffset + count, len);
// If range was initially empty, leaves it as is; otherwise, normalizes it to one char.
- m_endOffset = (m_endOffset > m_startOffset) ? start + 1 : start;
+ m_endOffset = (m_endOffset > m_startOffset) ? qMin(start + 1, len) : start;
*pRetVal = start - m_startOffset; // Returns the actually moved distance.
m_startOffset = start;
} else {
@@ -419,7 +394,7 @@ HRESULT QWindowsUiaTextRangeProvider::MoveEndpointByUnit(TextPatternRangeEndpoin
if (unit == TextUnit_Character) {
if (endpoint == TextPatternRangeEndpoint_Start) {
- int boundedValue = qBound(0, m_startOffset + count, len - 1);
+ int boundedValue = qBound(0, m_startOffset + count, len);
*pRetVal = boundedValue - m_startOffset;
m_startOffset = boundedValue;
m_endOffset = qBound(m_startOffset, m_endOffset, len);
@@ -443,7 +418,9 @@ HRESULT QWindowsUiaTextRangeProvider::MoveEndpointByUnit(TextPatternRangeEndpoin
}
m_endOffset = qBound(m_startOffset, m_endOffset, len);
} else {
- for (int t = m_startOffset - 1; (t >= 0) && (moved > count); --t) {
+ const int start = m_startOffset >= 0 && m_startOffset <= len
+ ? m_startOffset : len;
+ for (int t = start - 1; (t >= 0) && (moved > count); --t) {
if (!isTextUnitSeparator(unit, text[t]) && ((t == 0) || isTextUnitSeparator(unit, text[t - 1]))) {
m_startOffset = t;
--moved;
@@ -549,6 +526,42 @@ HRESULT QWindowsUiaTextRangeProvider::unselect()
return S_OK;
}
+// helper method to retrieve the value of the given IAccessible2 text attribute,
+// or an empty string if not set
+QString QWindowsUiaTextRangeProvider::valueForIA2Attribute(QAccessibleTextInterface *textInterface,
+ const QString &key)
+{
+ Q_ASSERT(textInterface);
+
+ int startOffset;
+ int endOffset;
+ const QString attributes = textInterface->attributes(m_startOffset, &startOffset, &endOffset);
+ // don't report if attributes don't apply for the whole range
+ if (startOffset > m_startOffset || endOffset < m_endOffset)
+ return {};
+
+ for (auto attr : QStringTokenizer{attributes, u';'})
+ {
+ const QList<QStringView> items = attr.split(u':', Qt::SkipEmptyParts, Qt::CaseSensitive);
+ if (items.count() == 2 && items[0] == key)
+ return items[1].toString();
+ }
+
+ return {};
+}
+
+TextDecorationLineStyle QWindowsUiaTextRangeProvider::uiaLineStyleForIA2LineStyle(const QString &ia2LineStyle)
+{
+ if (ia2LineStyle == QStringLiteral("none"))
+ return TextDecorationLineStyle_None;
+ if (ia2LineStyle == QStringLiteral("single"))
+ return TextDecorationLineStyle_Single;
+ if (ia2LineStyle == QStringLiteral("double"))
+ return TextDecorationLineStyle_Double;
+
+ return TextDecorationLineStyle_Other;
+}
+
QT_END_NAMESPACE
#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
index 3b4ec63ceb..a37429a603 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIATEXTRANGEPROVIDER_H
#define QWINDOWSUIATEXTRANGEPROVIDER_H
@@ -49,7 +13,7 @@ QT_BEGIN_NAMESPACE
// Implements the Text Range control pattern provider. Used for text controls.
class QWindowsUiaTextRangeProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<ITextRangeProvider>
+ public QComObject<ITextRangeProvider>
{
Q_DISABLE_COPY_MOVE(QWindowsUiaTextRangeProvider)
public:
@@ -78,6 +42,8 @@ public:
private:
HRESULT unselect();
+ QString valueForIA2Attribute(QAccessibleTextInterface *textInterface, const QString &key);
+ TextDecorationLineStyle uiaLineStyleForIA2LineStyle(const QString &ia2LineStyle);
int m_startOffset;
int m_endOffset;
};
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp
index 32445e4ffb..694debd492 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
index 892b635b41..17150dfbe0 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIATOGGLEPROVIDER_H
#define QWINDOWSUIATOGGLEPROVIDER_H
@@ -48,8 +12,7 @@
QT_BEGIN_NAMESPACE
// Implements the Toggle control pattern provider. Used for checkboxes.
-class QWindowsUiaToggleProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<IToggleProvider>
+class QWindowsUiaToggleProvider : public QWindowsUiaBaseProvider, public QComObject<IToggleProvider>
{
Q_DISABLE_COPY_MOVE(QWindowsUiaToggleProvider)
public:
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
index ab04384616..78ab3e890e 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
@@ -132,22 +96,19 @@ void setVariantString(const QString &value, VARIANT *variant)
void rectToNativeUiaRect(const QRect &rect, const QWindow *w, UiaRect *uiaRect)
{
if (w && uiaRect) {
- const qreal factor = QHighDpiScaling::factor(w);
- uiaRect->left = qreal(rect.x()) * factor;
- uiaRect->top = qreal(rect.y()) * factor;
- uiaRect->width = qreal(rect.width()) * factor;
- uiaRect->height = qreal(rect.height()) * factor;
+ QRectF r = QHighDpi::toNativePixels(QRectF(rect), w);
+ uiaRect->left =r.x();
+ uiaRect->top = r.y();
+ uiaRect->width = r.width();
+ uiaRect->height = r.height();
}
}
// Scales a point from native coordinates, according to high dpi settings.
void nativeUiaPointToPoint(const UiaPoint &uiaPoint, const QWindow *w, QPoint *point)
{
- if (w && point) {
- const qreal factor = QHighDpiScaling::factor(w);
- point->setX(int(std::lround(uiaPoint.x / factor)));
- point->setY(int(std::lround(uiaPoint.y / factor)));
- }
+ if (w && point)
+ *point = QHighDpi::fromNativePixels(QPoint(uiaPoint.x, uiaPoint.y), w);
}
// Maps an accessibility role ID to an UI Automation control type ID.
@@ -161,7 +122,7 @@ long roleToControlTypeId(QAccessible::Role role)
{QAccessible::Sound, UIA_CustomControlTypeId},
{QAccessible::Cursor, UIA_CustomControlTypeId},
{QAccessible::Caret, UIA_CustomControlTypeId},
- {QAccessible::AlertMessage, UIA_CustomControlTypeId},
+ {QAccessible::AlertMessage, UIA_WindowControlTypeId},
{QAccessible::Window, UIA_WindowControlTypeId},
{QAccessible::Client, UIA_GroupControlTypeId},
{QAccessible::PopupMenu, UIA_MenuControlTypeId},
@@ -215,6 +176,9 @@ long roleToControlTypeId(QAccessible::Role role)
{QAccessible::PageTabList, UIA_TabControlTypeId},
{QAccessible::Clock, UIA_CustomControlTypeId},
{QAccessible::Splitter, UIA_CustomControlTypeId},
+ {QAccessible::Paragraph, UIA_TextControlTypeId},
+ {QAccessible::WebDocument, UIA_DocumentControlTypeId},
+ {QAccessible::Heading, UIA_TextControlTypeId},
};
return mapping.value(role, UIA_CustomControlTypeId);
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h
index 6a482f6c1c..bf90211cec 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIAUTILS_H
#define QWINDOWSUIAUTILS_H
@@ -48,7 +12,7 @@
#include <QtGui/qaccessible.h>
#include <QtGui/qwindow.h>
#include <QtCore/qrect.h>
-#include <QtWindowsUIAutomationSupport/private/qwindowsuiawrapper_p.h>
+#include "qwindowsuiautomation.h"
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp
new file mode 100644
index 0000000000..1593a07202
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp
@@ -0,0 +1,74 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwindowsuiautomation.h"
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+
+template<typename T, typename... TArg>
+struct winapi_func
+{
+ using func_t = T(WINAPI*)(TArg...);
+ const func_t func;
+ const T error_value;
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wcast-function-type"
+#endif
+ winapi_func(const char *lib_name, const char *func_name, func_t func_proto,
+ T error_value = T(__HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND))) :
+ func(reinterpret_cast<func_t>(GetProcAddress(LoadLibraryA(lib_name), func_name))),
+ error_value(error_value)
+ {
+ std::ignore = func_proto;
+ }
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
+ T invoke(TArg... arg)
+ {
+ if (!func)
+ return error_value;
+ return func(arg...);
+ }
+};
+
+#define FN(fn) #fn,fn
+
+BOOL WINAPI UiaClientsAreListening()
+{
+ static auto func = winapi_func("uiautomationcore", FN(UiaClientsAreListening), BOOL(false));
+ return func.invoke();
+}
+
+LRESULT WINAPI UiaReturnRawElementProvider(
+ HWND hwnd, WPARAM wParam, LPARAM lParam, IRawElementProviderSimple *el)
+{
+ static auto func = winapi_func("uiautomationcore", FN(UiaReturnRawElementProvider));
+ return func.invoke(hwnd, wParam, lParam, el);
+}
+
+HRESULT WINAPI UiaHostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider)
+{
+ static auto func = winapi_func("uiautomationcore", FN(UiaHostProviderFromHwnd));
+ return func.invoke(hwnd, ppProvider);
+}
+
+HRESULT WINAPI UiaRaiseAutomationPropertyChangedEvent(
+ IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue)
+{
+ static auto func = winapi_func("uiautomationcore", FN(UiaRaiseAutomationPropertyChangedEvent));
+ return func.invoke(pProvider, id, oldValue, newValue);
+}
+
+HRESULT WINAPI UiaRaiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id)
+{
+ static auto func = winapi_func("uiautomationcore", FN(UiaRaiseAutomationEvent));
+ return func.invoke(pProvider, id);
+}
+
+#endif // defined(__MINGW32__) || defined(__MINGW64__)
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h
new file mode 100644
index 0000000000..a192b9b0fb
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h
@@ -0,0 +1,70 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWINDOWSUIAUTOMATION_H
+#define QWINDOWSUIAUTOMATION_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include <uiautomation.h>
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+
+#define UIA_SelectionPattern2Id 10034
+#define UIA_IsReadOnlyAttributeId 40015
+#define UIA_StrikethroughStyleAttributeId 40026
+#define UIA_CaretPositionAttributeId 40038
+
+enum CaretPosition {
+ CaretPosition_Unknown = 0,
+ CaretPosition_EndOfLine = 1,
+ CaretPosition_BeginningOfLine = 2
+};
+
+enum TextDecorationLineStyle {
+ TextDecorationLineStyle_None = 0,
+ TextDecorationLineStyle_Single = 1,
+ TextDecorationLineStyle_WordsOnly = 2,
+ TextDecorationLineStyle_Double = 3,
+ TextDecorationLineStyle_Dot = 4,
+ TextDecorationLineStyle_Dash = 5,
+ TextDecorationLineStyle_DashDot = 6,
+ TextDecorationLineStyle_DashDotDot = 7,
+ TextDecorationLineStyle_Wavy = 8,
+ TextDecorationLineStyle_ThickSingle = 9,
+ TextDecorationLineStyle_DoubleWavy = 11,
+ TextDecorationLineStyle_ThickWavy = 12,
+ TextDecorationLineStyle_LongDash = 13,
+ TextDecorationLineStyle_ThickDash = 14,
+ TextDecorationLineStyle_ThickDashDot = 15,
+ TextDecorationLineStyle_ThickDashDotDot = 16,
+ TextDecorationLineStyle_ThickDot = 17,
+ TextDecorationLineStyle_ThickLongDash = 18,
+ TextDecorationLineStyle_Other = -1
+};
+
+BOOL WINAPI UiaClientsAreListening();
+
+#ifndef __ISelectionProvider2_INTERFACE_DEFINED__
+#define __ISelectionProvider2_INTERFACE_DEFINED__
+DEFINE_GUID(IID_ISelectionProvider2, 0x14f68475, 0xee1c, 0x44f6, 0xa8, 0x69, 0xd2, 0x39, 0x38, 0x1f, 0x0f, 0xe7);
+MIDL_INTERFACE("14f68475-ee1c-44f6-a869-d239381f0fe7")
+ISelectionProvider2 : public ISelectionProvider
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE get_FirstSelectedItem(__RPC__deref_out_opt IRawElementProviderSimple **retVal) = 0;
+ virtual HRESULT STDMETHODCALLTYPE get_LastSelectedItem(__RPC__deref_out_opt IRawElementProviderSimple **retVal) = 0;
+ virtual HRESULT STDMETHODCALLTYPE get_CurrentSelectedItem(__RPC__deref_out_opt IRawElementProviderSimple **retVal) = 0;
+ virtual HRESULT STDMETHODCALLTYPE get_ItemCount(__RPC__out int *retVal) = 0;
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ISelectionProvider2, 0x14f68475, 0xee1c, 0x44f6, 0xa8, 0x69, 0xd2, 0x39, 0x38, 0x1f, 0x0f, 0xe7)
+#endif
+#endif // __ISelectionProvider2_INTERFACE_DEFINED__
+
+#endif // defined(__MINGW32__) || defined(__MINGW64__)
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINDOWSUIAUTOMATION_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp
index 8651bcff60..77f40cc2cc 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
@@ -72,7 +36,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaValueProvider::SetValue(LPCWSTR val)
return UIA_E_ELEMENTNOTAVAILABLE;
// First sets the value as a text.
- QString strVal = QString::fromUtf16(reinterpret_cast<const ushort *>(val));
+ QString strVal = QString::fromUtf16(reinterpret_cast<const char16_t *>(val));
accessible->setText(QAccessible::Value, strVal);
// Then, if the control supports the value interface (range value)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
index 3edfe7a08b..8c0a6b8ee7 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIAVALUEPROVIDER_H
#define QWINDOWSUIAVALUEPROVIDER_H
@@ -49,8 +13,7 @@ QT_BEGIN_NAMESPACE
// Implements the Value control pattern provider.
// Supported for all controls that can return text(QAccessible::Value).
-class QWindowsUiaValueProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<IValueProvider>
+class QWindowsUiaValueProvider : public QWindowsUiaBaseProvider, public QComObject<IValueProvider>
{
Q_DISABLE_COPY_MOVE(QWindowsUiaValueProvider)
public:
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.cpp
index 3738aa72ff..d86face0db 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.h
index 343fb275f7..89a1655232 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSUIAWINDOWPROVIDER_H
#define QWINDOWSUIAWINDOWPROVIDER_H
@@ -47,8 +11,7 @@
QT_BEGIN_NAMESPACE
-class QWindowsUiaWindowProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<IWindowProvider>
+class QWindowsUiaWindowProvider : public QWindowsUiaBaseProvider, public QComObject<IWindowProvider>
{
Q_DISABLE_COPY(QWindowsUiaWindowProvider)
public:
diff --git a/src/plugins/platforms/windows/uiautomation/uiautomation.pri b/src/plugins/platforms/windows/uiautomation/uiautomation.pri
deleted file mode 100644
index ee9332e7ea..0000000000
--- a/src/plugins/platforms/windows/uiautomation/uiautomation.pri
+++ /dev/null
@@ -1,44 +0,0 @@
-qtHaveModule(windowsuiautomation_support-private): \
- QT += windowsuiautomation_support-private
-
-SOURCES += \
- $$PWD/qwindowsuiaaccessibility.cpp \
- $$PWD/qwindowsuiaprovidercache.cpp \
- $$PWD/qwindowsuiamainprovider.cpp \
- $$PWD/qwindowsuiabaseprovider.cpp \
- $$PWD/qwindowsuiavalueprovider.cpp \
- $$PWD/qwindowsuiatextprovider.cpp \
- $$PWD/qwindowsuiatextrangeprovider.cpp \
- $$PWD/qwindowsuiatoggleprovider.cpp \
- $$PWD/qwindowsuiaselectionprovider.cpp \
- $$PWD/qwindowsuiaselectionitemprovider.cpp \
- $$PWD/qwindowsuiainvokeprovider.cpp \
- $$PWD/qwindowsuiarangevalueprovider.cpp \
- $$PWD/qwindowsuiatableprovider.cpp \
- $$PWD/qwindowsuiatableitemprovider.cpp \
- $$PWD/qwindowsuiagridprovider.cpp \
- $$PWD/qwindowsuiagriditemprovider.cpp \
- $$PWD/qwindowsuiawindowprovider.cpp \
- $$PWD/qwindowsuiautils.cpp
-
-HEADERS += \
- $$PWD/qwindowsuiaaccessibility.h \
- $$PWD/qwindowsuiaprovidercache.h \
- $$PWD/qwindowsuiamainprovider.h \
- $$PWD/qwindowsuiabaseprovider.h \
- $$PWD/qwindowsuiavalueprovider.h \
- $$PWD/qwindowsuiatextprovider.h \
- $$PWD/qwindowsuiatextrangeprovider.h \
- $$PWD/qwindowsuiatoggleprovider.h \
- $$PWD/qwindowsuiaselectionprovider.h \
- $$PWD/qwindowsuiaselectionitemprovider.h \
- $$PWD/qwindowsuiainvokeprovider.h \
- $$PWD/qwindowsuiarangevalueprovider.h \
- $$PWD/qwindowsuiatableprovider.h \
- $$PWD/qwindowsuiatableitemprovider.h \
- $$PWD/qwindowsuiagridprovider.h \
- $$PWD/qwindowsuiagriditemprovider.h \
- $$PWD/qwindowsuiawindowprovider.h \
- $$PWD/qwindowsuiautils.h
-
-mingw: QMAKE_USE *= uuid
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
deleted file mode 100644
index 95ba961df1..0000000000
--- a/src/plugins/platforms/windows/windows.pri
+++ /dev/null
@@ -1,130 +0,0 @@
-# Note: OpenGL32 must precede Gdi32 as it overwrites some functions.
-LIBS += -lwinspool -limm32 -loleaut32
-
-QT_FOR_CONFIG += gui
-
-qtConfig(opengl):!qtConfig(opengles2):!qtConfig(dynamicgl): LIBS *= -lopengl32
-
-mingw: QMAKE_USE *= uuid
-# For the dialog helpers:
-LIBS += -lshlwapi -lwtsapi32
-
-QMAKE_USE_PRIVATE += \
- advapi32 \
- d3d9/nolink \
- ole32 \
- shell32 \
- user32 \
- winmm
-
-DEFINES *= QT_NO_CAST_FROM_ASCII QT_NO_FOREACH
-
-SOURCES += \
- $$PWD/qwindowswindow.cpp \
- $$PWD/qwindowsintegration.cpp \
- $$PWD/qwindowscontext.cpp \
- $$PWD/qwindowsscreen.cpp \
- $$PWD/qwindowskeymapper.cpp \
- $$PWD/qwindowsmousehandler.cpp \
- $$PWD/qwindowspointerhandler.cpp \
- $$PWD/qwindowsole.cpp \
- $$PWD/qwindowsdropdataobject.cpp \
- $$PWD/qwindowsmime.cpp \
- $$PWD/qwindowsinternalmimedata.cpp \
- $$PWD/qwindowscursor.cpp \
- $$PWD/qwindowsinputcontext.cpp \
- $$PWD/qwindowstheme.cpp \
- $$PWD/qwindowsmenu.cpp \
- $$PWD/qwindowsdialoghelpers.cpp \
- $$PWD/qwindowsservices.cpp \
- $$PWD/qwindowsnativeinterface.cpp \
- $$PWD/qwindowsopengltester.cpp \
- $$PWD/qwin10helpers.cpp
-
-HEADERS += \
- $$PWD/qwindowscombase.h \
- $$PWD/qwindowswindow.h \
- $$PWD/qwindowsintegration.h \
- $$PWD/qwindowscontext.h \
- $$PWD/qwindowsscreen.h \
- $$PWD/qwindowskeymapper.h \
- $$PWD/qwindowsmousehandler.h \
- $$PWD/qwindowspointerhandler.h \
- $$PWD/qtwindowsglobal.h \
- $$PWD/qwindowsole.h \
- $$PWD/qwindowsdropdataobject.h \
- $$PWD/qwindowsmime.h \
- $$PWD/qwindowsinternalmimedata.h \
- $$PWD/qwindowscursor.h \
- $$PWD/qwindowsinputcontext.h \
- $$PWD/qwindowstheme.h \
- $$PWD/qwindowsmenu.h \
- $$PWD/qwindowsdialoghelpers.h \
- $$PWD/qwindowsservices.h \
- $$PWD/qwindowsnativeinterface.h \
- $$PWD/qwindowsopengltester.h \
- $$PWD/qwindowsthreadpoolrunner.h \
- $$PWD/qwin10helpers.h
-
-INCLUDEPATH += $$PWD
-
-qtConfig(opengl): HEADERS += $$PWD/qwindowsopenglcontext.h
-
-qtConfig(opengles2) {
- SOURCES += $$PWD/qwindowseglcontext.cpp
- HEADERS += $$PWD/qwindowseglcontext.h
-} else: qtConfig(opengl) {
- SOURCES += $$PWD/qwindowsglcontext.cpp
- HEADERS += $$PWD/qwindowsglcontext.h
-}
-
-# Dynamic GL needs both WGL and EGL
-qtConfig(dynamicgl) {
- SOURCES += $$PWD/qwindowseglcontext.cpp
- HEADERS += $$PWD/qwindowseglcontext.h
-}
-
-qtConfig(systemtrayicon) {
- SOURCES += $$PWD/qwindowssystemtrayicon.cpp
- HEADERS += $$PWD/qwindowssystemtrayicon.h
-}
-
-qtConfig(vulkan) {
- SOURCES += $$PWD/qwindowsvulkaninstance.cpp
- HEADERS += $$PWD/qwindowsvulkaninstance.h
-}
-
-qtConfig(clipboard) {
- SOURCES += $$PWD/qwindowsclipboard.cpp
- HEADERS += $$PWD/qwindowsclipboard.h
- # drag and drop on windows only works if a clipboard is available
- qtConfig(draganddrop) {
- HEADERS += $$PWD/qwindowsdrag.h
- SOURCES += $$PWD/qwindowsdrag.cpp
- }
-}
-
-qtConfig(tabletevent) {
- INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/wintab
- HEADERS += $$PWD/qwindowstabletsupport.h
- SOURCES += $$PWD/qwindowstabletsupport.cpp
-}
-
-qtConfig(sessionmanager) {
- SOURCES += $$PWD/qwindowssessionmanager.cpp
- HEADERS += $$PWD/qwindowssessionmanager.h
-}
-
-qtConfig(imageformat_png):RESOURCES += $$PWD/cursors.qrc
-
-RESOURCES += $$PWD/openglblacklists.qrc
-
-qtConfig(accessibility): include($$PWD/uiautomation/uiautomation.pri)
-
-qtConfig(combined-angle-lib) {
- DEFINES *= LIBEGL_NAME=$${LIBQTANGLE_NAME}
- DEFINES *= LIBGLESV2_NAME=$${LIBQTANGLE_NAME}
-} else {
- DEFINES *= LIBEGL_NAME=$${LIBEGL_NAME}
- DEFINES *= LIBGLESV2_NAME=$${LIBGLESV2_NAME}
-}
diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro
deleted file mode 100644
index 50a3bb41a9..0000000000
--- a/src/plugins/platforms/windows/windows.pro
+++ /dev/null
@@ -1,32 +0,0 @@
-TARGET = qwindows
-
-QT += \
- core-private gui-private \
- eventdispatcher_support-private \
- fontdatabase_support-private theme_support-private
-
-qtConfig(accessibility): QT += accessibility_support-private
-qtConfig(vulkan): QT += vulkan_support-private
-
-LIBS += -ldwmapi
-QMAKE_USE_PRIVATE += gdi32
-
-include(windows.pri)
-
-SOURCES += \
- main.cpp \
- qwindowsbackingstore.cpp \
- qwindowsgdiintegration.cpp \
- qwindowsgdinativeinterface.cpp
-
-HEADERS += \
- qwindowsbackingstore.h \
- qwindowsgdiintegration.h \
- qwindowsgdinativeinterface.h
-
-OTHER_FILES += windows.json
-
-PLUGIN_TYPE = platforms
-PLUGIN_CLASS_NAME = QWindowsIntegrationPlugin
-!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
-load(qt_plugin)