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/.prev_CMakeLists.txt199
-rw-r--r--src/plugins/platforms/windows/CMakeLists.txt61
-rw-r--r--src/plugins/platforms/windows/cursors.qrc25
-rw-r--r--src/plugins/platforms/windows/main.cpp44
-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.cpp71
-rw-r--r--src/plugins/platforms/windows/qwindowsapplication.h51
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp51
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.h40
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.cpp55
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.h40
-rw-r--r--src/plugins/platforms/windows/qwindowscombase.h116
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp630
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h142
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp86
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h40
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp266
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.h42
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp139
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.h46
-rw-r--r--src/plugins/platforms/windows/qwindowsdropdataobject.cpp50
-rw-r--r--src/plugins/platforms/windows/qwindowsdropdataobject.h40
-rw-r--r--src/plugins/platforms/windows/qwindowsgdiintegration.cpp44
-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.cpp83
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h42
-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.cpp337
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h57
-rw-r--r--src/plugins/platforms/windows/qwindowsinternalmimedata.cpp54
-rw-r--r--src/plugins/platforms/windows/qwindowsinternalmimedata.h40
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp203
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.h48
-rw-r--r--src/plugins/platforms/windows/qwindowsmenu.cpp45
-rw-r--r--src/plugins/platforms/windows/qwindowsmenu.h41
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.h94
-rw-r--r--src/plugins/platforms/windows/qwindowsmimeregistry.cpp (renamed from src/plugins/platforms/windows/qwindowsmime.cpp)441
-rw-r--r--src/plugins/platforms/windows/qwindowsmimeregistry.h58
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp102
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.h51
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp40
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.h40
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp48
-rw-r--r--src/plugins/platforms/windows/qwindowsole.h46
-rw-r--r--src/plugins/platforms/windows/qwindowsopenglcontext.h40
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp63
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.h40
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp280
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.h61
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp530
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h68
-rw-r--r--src/plugins/platforms/windows/qwindowsservices.cpp133
-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.cpp129
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.h42
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp332
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.h87
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp670
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h51
-rw-r--r--src/plugins/platforms/windows/qwindowsthreadpoolrunner.h40
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.cpp40
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.h40
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp1077
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h85
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp63
-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.cpp56
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.h42
-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.cpp249
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h51
-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.cpp215
-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.cpp60
-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.cpp40
-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.pri43
-rw-r--r--src/plugins/platforms/windows/windows.pri116
-rw-r--r--src/plugins/platforms/windows/windows.pro28
118 files changed, 4519 insertions, 6999 deletions
diff --git a/src/plugins/platforms/windows/.prev_CMakeLists.txt b/src/plugins/platforms/windows/.prev_CMakeLists.txt
deleted file mode 100644
index cbb7bbcaa8..0000000000
--- a/src/plugins/platforms/windows/.prev_CMakeLists.txt
+++ /dev/null
@@ -1,199 +0,0 @@
-# Generated from windows.pro.
-
-#####################################################################
-## QWindowsIntegrationPlugin Plugin:
-#####################################################################
-
-qt_internal_add_plugin(QWindowsIntegrationPlugin
- OUTPUT_NAME qwindows
- TYPE platforms
- SOURCES
- main.cpp
- qtwindowsglobal.h
- qwin10helpers.cpp qwin10helpers.h
- qwindowsapplication.cpp qwindowsapplication.h
- qwindowsbackingstore.cpp qwindowsbackingstore.h
- qwindowscombase.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
- qwindowsinputcontext.cpp qwindowsinputcontext.h
- qwindowsintegration.cpp qwindowsintegration.h
- qwindowsinternalmimedata.cpp qwindowsinternalmimedata.h
- qwindowskeymapper.cpp qwindowskeymapper.h
- qwindowsmenu.cpp qwindowsmenu.h
- qwindowsmime.cpp qwindowsmime.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
- DEFINES
- QT_NO_CAST_FROM_ASCII
- QT_NO_FOREACH
- INCLUDE_DIRECTORIES
- ${CMAKE_CURRENT_SOURCE_DIR}
- LIBRARIES
- advapi32
- gdi32
- ole32
- shell32
- user32
- winmm
- PUBLIC_LIBRARIES
- Qt::Core
- Qt::CorePrivate
- Qt::Gui
- Qt::GuiPrivate
- dwmapi
- imm32
- oleaut32
- shlwapi
- winspool
- wtsapi32
-)
-
-# 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}
-)
-
-
-#### Keys ignored in scope 1:.:.:windows.pro:<TRUE>:
-# OTHER_FILES = "windows.json"
-
-## Scopes:
-#####################################################################
-
-qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_opengl
- SOURCES
- qwindowsglcontext.cpp qwindowsglcontext.h
- qwindowsopenglcontext.h
- PUBLIC_LIBRARIES
- Qt::OpenGLPrivate
-)
-
-#### Keys ignored in scope 3:.:.:windows.pro:NOT TARGET___equals____ss_QT_DEFAULT_QPA_PLUGIN:
-# PLUGIN_EXTENDS = "-"
-
-qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_opengl AND NOT QT_FEATURE_dynamicgl
- PUBLIC_LIBRARIES
- opengl32
-)
-
-qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION MINGW
- PUBLIC_LIBRARIES
- uuid
-)
-
-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
- ${QT_SOURCE_TREE}/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/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
-)
-
-qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION MINGW AND QT_FEATURE_accessibility
- PUBLIC_LIBRARIES
- uuid
-)
diff --git a/src/plugins/platforms/windows/CMakeLists.txt b/src/plugins/platforms/windows/CMakeLists.txt
index 2f1182190d..4b92317978 100644
--- a/src/plugins/platforms/windows/CMakeLists.txt
+++ b/src/plugins/platforms/windows/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from windows.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## QWindowsIntegrationPlugin Plugin:
@@ -6,27 +7,27 @@
qt_internal_add_plugin(QWindowsIntegrationPlugin
OUTPUT_NAME qwindows
- TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES windows # special case
+ 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
- qwindowscombase.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
- qwindowsmime.cpp qwindowsmime.h
+ qwindowsmimeregistry.cpp qwindowsmimeregistry.h
qwindowsmousehandler.cpp qwindowsmousehandler.h
qwindowsnativeinterface.cpp qwindowsnativeinterface.h
qwindowsole.cpp qwindowsole.h
@@ -37,29 +38,35 @@ qt_internal_add_plugin(QWindowsIntegrationPlugin
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
- advapi32
- gdi32
- ole32
- shell32
- user32
- winmm
- PUBLIC_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:
@@ -77,10 +84,6 @@ qt_internal_add_resource(QWindowsIntegrationPlugin "openglblacklists"
${openglblacklists_resource_files}
)
-
-#### Keys ignored in scope 1:.:.:windows.pro:<TRUE>:
-# OTHER_FILES = "windows.json"
-
## Scopes:
#####################################################################
@@ -88,21 +91,20 @@ qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_opengl
SOURCES
qwindowsglcontext.cpp qwindowsglcontext.h
qwindowsopenglcontext.h
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::OpenGLPrivate
)
-#### Keys ignored in scope 3:.:.:windows.pro:NOT TARGET___equals____ss_QT_DEFAULT_QPA_PLUGIN:
-# PLUGIN_EXTENDS = "-"
-
qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_opengl AND NOT QT_FEATURE_dynamicgl
- PUBLIC_LIBRARIES
+ LIBRARIES
opengl32
)
qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION MINGW
- PUBLIC_LIBRARIES
+ LIBRARIES
uuid
+ NO_PCH_SOURCES
+ qwindowspointerhandler.cpp
)
qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_systemtrayicon
@@ -129,7 +131,7 @@ qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_tablete
SOURCES
qwindowstabletsupport.cpp qwindowstabletsupport.h
INCLUDE_DIRECTORIES
- ${QT_SOURCE_TREE}/src/3rdparty/wintab
+ ${QtBase_SOURCE_DIR}/src/3rdparty/wintab
)
qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_sessionmanager
@@ -173,6 +175,7 @@ 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
@@ -194,7 +197,17 @@ qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_accessi
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
- PUBLIC_LIBRARIES
+ 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 a3f81ec9fc..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,6 +9,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\title Qt platform plugin for Windows
@@ -106,7 +72,7 @@ public:
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
index fc495d999f..42e34ac99f 100644
--- a/src/plugins/platforms/windows/qwindowsapplication.cpp
+++ b/src/plugins/platforms/windows/qwindowsapplication.cpp
@@ -1,50 +1,20 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 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 "qwindowsapplication.h"
#include "qwindowsclipboard.h"
#include "qwindowscontext.h"
-#include "qwindowsmime.h"
+#include "qwindowsmimeregistry.h"
#include "qwin10helpers.h"
#include "qwindowsopengltester.h"
+#include "qwindowswindow.h"
+#include "qwindowsintegration.h"
+#include "qwindowstheme.h"
-#include <QtCore/QVariant>
+#include <QtCore/qvariant.h>
+#include <QtCore/private/qfunctions_win_p.h>
+
+#include <QtGui/qpalette.h>
QT_BEGIN_NAMESPACE
@@ -72,6 +42,11 @@ void QWindowsApplication::setWindowActivationBehavior(WindowActivationBehavior b
m_windowActivationBehavior = behavior;
}
+void QWindowsApplication::setHasBorderInFullScreenDefault(bool border)
+{
+ QWindowsWindow::setHasBorderInFullScreenDefault(border);
+}
+
bool QWindowsApplication::isTabletMode() const
{
#if QT_CONFIG(clipboard)
@@ -97,11 +72,6 @@ bool QWindowsApplication::setWinTabEnabled(bool enabled)
return enabled ? ctx->initTablet() : ctx->disposeTablet();
}
-bool QWindowsApplication::isDarkMode() const
-{
- return QWindowsContext::isDarkMode();
-}
-
QWindowsApplication::DarkModeHandling QWindowsApplication::darkModeHandling() const
{
return m_darkModeHandling;
@@ -112,13 +82,13 @@ void QWindowsApplication::setDarkModeHandling(QWindowsApplication::DarkModeHandl
m_darkModeHandling = handling;
}
-void QWindowsApplication::registerMime(QPlatformInterface::Private::QWindowsMime *mime)
+void QWindowsApplication::registerMime(QWindowsMimeConverter *mime)
{
if (auto ctx = QWindowsContext::instance())
ctx->mimeConverter().registerMime(mime);
}
-void QWindowsApplication::unregisterMime(QPlatformInterface::Private::QWindowsMime *mime)
+void QWindowsApplication::unregisterMime(QWindowsMimeConverter *mime)
{
if (auto ctx = QWindowsContext::instance())
ctx->mimeConverter().unregisterMime(mime);
@@ -126,7 +96,7 @@ void QWindowsApplication::unregisterMime(QPlatformInterface::Private::QWindowsMi
int QWindowsApplication::registerMimeType(const QString &mime)
{
- return QWindowsMimeConverter::registerMimeType(mime);
+ return QWindowsMimeRegistry::registerMimeType(mime);
}
HWND QWindowsApplication::createMessageWindow(const QString &classNameTemplate,
@@ -168,4 +138,9 @@ QVariant QWindowsApplication::gpuList() const
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
index 25a0cc7437..0918df91af 100644
--- a/src/plugins/platforms/windows/qwindowsapplication.h
+++ b/src/plugins/platforms/windows/qwindowsapplication.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 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
#ifndef QWINDOWSAPPLICATION_H
#define QWINDOWSAPPLICATION_H
@@ -44,7 +8,7 @@
QT_BEGIN_NAMESPACE
-class QWindowsApplication : public QPlatformInterface::Private::QWindowsApplication
+class QWindowsApplication : public QNativeInterface::Private::QWindowsApplication
{
public:
void setTouchWindowTouchType(TouchWindowTouchTypes type) override;
@@ -53,17 +17,18 @@ public:
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;
- bool isDarkMode() const override;
DarkModeHandling darkModeHandling() const override;
void setDarkModeHandling(DarkModeHandling handling) override;
- void registerMime(QPlatformInterface::Private::QWindowsMime *mime) override;
- void unregisterMime(QPlatformInterface::Private::QWindowsMime *mime) override;
+ void registerMime(QWindowsMimeConverter *mime) override;
+ void unregisterMime(QWindowsMimeConverter *mime) override;
int registerMimeType(const QString &mime) override;
@@ -77,6 +42,8 @@ public:
QVariant gpu() const override;
QVariant gpuList() const override;
+ void populateLightSystemPalette(QPalette &palette) const override;
+
private:
WindowActivationBehavior m_windowActivationBehavior = DefaultActivateWindow;
TouchWindowTouchTypes m_touchWindowTouchTypes = NormalTouch;
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
index e9d1915201..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"
@@ -91,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()};
@@ -154,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);
@@ -183,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 01377a55e0..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,6 +16,7 @@
#include <QtCore/qthread.h>
#include <QtCore/qvariant.h>
#include <QtCore/qurl.h>
+#include <QtCore/private/qsystemerror_p.h>
#include <QtGui/private/qwindowsguieventdispatcher_p.h>
@@ -191,12 +155,9 @@ void QWindowsClipboard::registerViewer()
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);
@@ -210,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);
@@ -340,7 +301,7 @@ void QWindowsClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode)
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 749ad50234..0000000000
--- a/src/plugins/platforms/windows/qwindowscombase.h
+++ /dev/null
@@ -1,116 +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) override
- {
- *iface = nullptr;
- return qWindowsComQueryInterface<IUnknown>(this, id, iface) || qWindowsComQueryInterface<ComInterface>(this, id, iface)
- ? S_OK : E_NOINTERFACE;
- }
-
- ULONG STDMETHODCALLTYPE AddRef() override { return ++m_ref; }
-
- ULONG STDMETHODCALLTYPE Release() override
- {
- if (!--m_ref) {
- delete this;
- return 0;
- }
- return m_ref;
- }
-
-private:
- ULONG m_ref;
-};
-
-// Clang does not consider __declspec(nothrow) as nothrow
-QT_WARNING_DISABLE_CLANG("-Wmicrosoft-exception-spec")
-QT_WARNING_DISABLE_CLANG("-Wmissing-exception-spec")
-
-QT_END_NAMESPACE
-
-#endif // QWINDOWSCOMBASE_H
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 1e5b247f0f..de65a2171d 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.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 "qwindowscontext.h"
#include "qwindowsintegration.h"
@@ -47,7 +11,7 @@
#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"
@@ -77,25 +41,30 @@
#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 <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")
@@ -106,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;
@@ -151,97 +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
-*/
-
-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;
/*!
@@ -253,20 +132,18 @@ QWindowsContext *QWindowsContext::m_instance = nullptr;
\internal
*/
-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)
@@ -277,17 +154,14 @@ struct QWindowsContextPrivate {
bool m_asyncExpose = false;
HPOWERNOTIFY m_powerNotification = nullptr;
HWND m_powerDummyWindow = nullptr;
- static bool m_darkMode;
+ static bool m_v2DpiAware;
};
-bool QWindowsContextPrivate::m_darkMode = false;
+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);
@@ -296,10 +170,9 @@ QWindowsContextPrivate::QWindowsContextPrivate()
m_systemInfo |= QWindowsContext::SI_RTL_Extensions;
m_keyMapper.setUseRTLExtensions(true);
}
- m_darkMode = QWindowsTheme::queryDarkMode();
if (FAILED(m_oleInitializeResult)) {
qWarning() << "QWindowsContext: OleInitialize() failed: "
- << QWindowsContext::comErrorString(m_oleInitializeResult);
+ << QSystemError::windowsComString(m_oleInitializeResult);
}
}
@@ -329,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)
@@ -349,19 +226,16 @@ bool QWindowsContext::initTouch(unsigned integrationOptions)
return true;
const bool usePointerHandler = (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) != 0;
auto touchDevice = usePointerHandler ? d->m_pointerHandler.touchDevice() : d->m_mouseHandler.touchDevice();
- if (!touchDevice) {
+ if (touchDevice.isNull()) {
const bool mouseEmulation =
(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch) == 0;
touchDevice = QWindowsPointerHandler::createTouchDevice(mouseEmulation);
}
- if (!touchDevice)
+ if (touchDevice.isNull())
return false;
- if (usePointerHandler)
- d->m_pointerHandler.setTouchDevice(touchDevice);
- else
- d->m_mouseHandler.setTouchDevice(touchDevice);
-
- QWindowSystemInterface::registerInputDevice(touchDevice);
+ d->m_pointerHandler.setTouchDevice(touchDevice);
+ d->m_mouseHandler.setTouchDevice(touchDevice);
+ QWindowSystemInterface::registerInputDevice(touchDevice.data());
d->m_systemInfo |= QWindowsContext::SI_SupportsTouch;
@@ -375,7 +249,7 @@ void QWindowsContext::registerTouchWindows()
{
if (QGuiApplicationPrivate::is_app_running
&& (d->m_systemInfo & QWindowsContext::SI_SupportsTouch) != 0) {
- for (QWindowsWindow *w : qAsConst(d->m_windows))
+ for (QWindowsWindow *w : std::as_const(d->m_windows))
w->registerTouchWindow();
}
}
@@ -405,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;
}
@@ -478,39 +346,119 @@ void QWindowsContext::setDetectAltGrModifier(bool a)
d->m_keyMapper.setDetectAltGrModifier(a);
}
-int QWindowsContext::processDpiAwareness()
-{
- int result;
- if (QWindowsContext::shcoredll.getProcessDpiAwareness
- && SUCCEEDED(QWindowsContext::shcoredll.getProcessDpiAwareness(nullptr, &result))) {
- return result;
+[[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 -1;
+ return nullptr;
}
-void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness)
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, 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");
- }
+ 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;
}
+ d.nospace().noquote() << message;
+ return d;
}
+#endif
-bool QWindowsContext::isDarkMode()
+bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwareness)
{
- return QWindowsContextPrivate::m_darkMode;
+ 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()
@@ -528,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.possibleKeys(e);
+ return &d->m_keyMapper;
+}
+
+QWindowsContext::HandleBaseWindowHash &QWindowsContext::windows()
+{
+ return d->m_windows;
}
QSharedPointer<QWindowCreationContext> QWindowsContext::setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx)
@@ -577,6 +530,8 @@ QString QWindowsContext::classNamePrefix()
# define xstr(s) str(s)
# define str(s) #s
str << xstr(QT_NAMESPACE);
+# undef str
+# undef xstr
#endif
}
return result;
@@ -614,30 +569,30 @@ QString QWindowsContext::registerWindowClass(const QWindow *w)
}
// Create a unique name for the flag combination
QString cname = classNamePrefix();
- cname += QLatin1String("QWindow");
+ 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,
@@ -696,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;
@@ -706,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));
}
@@ -718,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);
- char16_t *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);
@@ -838,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;
@@ -895,7 +835,7 @@ bool QWindowsContext::isSessionLocked()
return result;
}
-QWindowsMimeConverter &QWindowsContext::mimeConverter() const
+QWindowsMimeRegistry &QWindowsContext::mimeConverter() const
{
return d->m_mimeConverter;
}
@@ -933,98 +873,6 @@ 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)
-{
- 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).toUtf8();
- result += ')';
- return result;
-}
-
void QWindowsContext::forceNcCalcSize(HWND hwnd)
{
// Force WM_NCCALCSIZE to adjust margin
@@ -1035,8 +883,8 @@ void QWindowsContext::forceNcCalcSize(HWND hwnd)
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;
}
@@ -1077,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
@@ -1137,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.
@@ -1153,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);
@@ -1234,26 +1080,12 @@ 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: {
QWindowsWindow::settingsChanged();
- const bool darkMode = QWindowsTheme::queryDarkMode();
- if (darkMode != QWindowsContextPrivate::m_darkMode) {
- QWindowsContextPrivate::m_darkMode = darkMode;
- auto integration = QWindowsIntegration::instance();
- if (integration->darkModeHandling().testFlag(QWindowsApplication::DarkModeWindowFrames)) {
- for (QWindowsWindow *w : d->m_windows)
- w->setDarkBorder(QWindowsContextPrivate::m_darkMode);
- }
- if (integration->darkModeHandling().testFlag(QWindowsApplication::DarkModeStyle)) {
- QWindowsTheme::instance()->refresh();
- for (QWindowsWindow *w : d->m_windows)
- QWindowSystemInterface::handleThemeChange(w->window());
- }
+ // 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();
}
@@ -1270,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);
@@ -1309,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();
@@ -1339,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));
@@ -1349,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))
@@ -1413,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());
@@ -1454,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();
@@ -1515,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;
}
@@ -1557,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);
}
}
@@ -1587,7 +1426,7 @@ bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg)
}
QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos,
- QWindowsKeyMapper::queryKeyboardModifiers());
+ keyMapper()->queryKeyboardModifiers());
return true;
}
#endif
@@ -1608,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);
@@ -1617,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)
@@ -1637,12 +1475,6 @@ void QWindowsContext::setAsyncExpose(bool value)
d->m_asyncExpose = value;
}
-QPointingDevice *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 =
@@ -1718,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();
@@ -1737,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;
@@ -1752,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 0cc5f0f595..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 QPointingDevice;
-
-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 QWindowsContext
{
Q_DISABLE_COPY_MOVE(QWindowsContext)
public:
+ using HandleBaseWindowHash = QHash<HWND, QWindowsWindow *>;
enum SystemInfoFlags
{
@@ -196,8 +88,6 @@ public:
static QWindowsContext *instance();
- static QString windowsErrorMessage(unsigned long errorCode);
-
void addWindow(HWND, QWindowsWindow *w);
void removeWindow(HWND);
@@ -225,10 +115,10 @@ public:
QSharedPointer<QWindowCreationContext> windowCreationContext() const;
static void setTabletAbsoluteRange(int a);
- void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness);
- static int processDpiAwareness();
- static bool isDarkMode();
+ static bool setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwareness);
+ static QtWindows::DpiAwareness processDpiAwareness();
+ static QtWindows::DpiAwareness windowDpiAwareness(HWND hwnd);
void setDetectAltGrModifier(bool a);
@@ -236,18 +126,16 @@ 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);
@@ -266,8 +154,6 @@ public:
static DWORD readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue);
- QPointingDevice *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 fe8b6f7085..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,7 @@
#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>
@@ -65,8 +30,7 @@ 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
@@ -79,10 +43,10 @@ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c)
: bitmapCacheKey(c.pixmap().cacheKey()), maskCacheKey(0)
{
if (!bitmapCacheKey) {
- Q_ASSERT(!c.bitmap(Qt::ReturnByValue).isNull());
- Q_ASSERT(!c.mask(Qt::ReturnByValue).isNull());
- bitmapCacheKey = c.bitmap(Qt::ReturnByValue).cacheKey();
- maskCacheKey = c.mask(Qt::ReturnByValue).cacheKey();
+ Q_ASSERT(!c.bitmap().isNull());
+ Q_ASSERT(!c.mask().isNull());
+ bitmapCacheKey = c.bitmap().cacheKey();
+ maskCacheKey = c.mask().cacheKey();
}
}
@@ -141,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)
@@ -159,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());
@@ -167,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(Qt::ReturnByValue).isNull());
- QImage bbits = cursor.bitmap(Qt::ReturnByValue).toImage();
- QImage mbits = cursor.mask(Qt::ReturnByValue).toImage();
+ 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);
@@ -474,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
@@ -652,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()
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index fc2a111aac..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
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 0312bde563..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"
@@ -70,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(u'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)
@@ -142,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
/*!
@@ -150,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
@@ -214,20 +164,25 @@ private:
*/
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;
}
}
@@ -254,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();
}
@@ -283,6 +238,7 @@ private:
void QWindowsDialogThread::run()
{
qCDebug(lcQpaDialogs) << '>' << __FUNCTION__;
+ QComHelper comInit(COINIT_APARTMENTTHREADED);
m_dialog->exec(m_owner);
qCDebug(lcQpaDialogs) << '<' << __FUNCTION__;
}
@@ -339,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;
}
@@ -501,7 +423,7 @@ inline void QWindowsFileDialogSharedData::fromOptions(const QSharedPointer<QFile
class QWindowsNativeFileDialogBase;
-class QWindowsNativeFileDialogEventHandler : public QWindowsComBase<IFileDialogEvents>
+class QWindowsNativeFileDialogEventHandler : public QComObject<IFileDialogEvents>
{
Q_DISABLE_COPY_MOVE(QWindowsNativeFileDialogEventHandler)
public:
@@ -594,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
@@ -634,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);
}
@@ -668,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 };
@@ -691,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;
@@ -1055,7 +987,7 @@ static QList<FilterSpec> filterSpecs(const QStringList &filters,
#if QT_CONFIG(regularexpression)
filterSpec.filter.replace(filterSeparatorRE, separator);
#else
- filterSpec.filter.replace(QLatin1Char(' '), QLatin1Char(';'));
+ filterSpec.filter.replace(u' ', u';');
#endif
filterSpec.description = filterString;
if (hideFilterDetails && openingParenPos != -1) { // Do not show pattern in description
@@ -1269,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);
@@ -1405,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);
}
@@ -1427,7 +1359,7 @@ QString tempFilePattern(QString name)
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)))
@@ -1441,14 +1373,14 @@ QString tempFilePattern(QString 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();
}
@@ -1619,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
@@ -1653,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
@@ -1707,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);
@@ -1719,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,
@@ -1780,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) {
@@ -1801,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);
}
@@ -1823,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])
@@ -1903,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));
@@ -2045,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);
@@ -2059,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)
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
index 55167ad36d..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,
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index f46adf9132..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>
@@ -203,7 +169,7 @@ static Qt::MouseButtons lastButtons = Qt::NoButton;
\internal
*/
-class QWindowsOleDropSource : public QWindowsComBase<IDropSource>
+class QWindowsOleDropSource : public QComObject<IDropSource>
{
public:
enum Mode {
@@ -384,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;
}
}
@@ -420,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
@@ -562,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,
@@ -647,7 +614,6 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
*/
bool QWindowsDrag::m_canceled = false;
-bool QWindowsDrag::m_dragging = false;
QWindowsDrag::QWindowsDrag() = default;
@@ -680,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?
@@ -695,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 33b583b479..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,7 +23,7 @@ public:
IDataObject *retrieveDataObject() const override;
};
-class QWindowsOleDropTarget : public QWindowsComBase<IDropTarget>
+class QWindowsOleDropTarget : public QComObject<IDropTarget>
{
public:
explicit QWindowsOleDropTarget(QWindow *w);
@@ -94,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; }
@@ -105,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 a06a14a980..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.
@@ -89,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 407c809243..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
diff --git a/src/plugins/platforms/windows/qwindowsgdiintegration.cpp b/src/plugins/platforms/windows/qwindowsgdiintegration.cpp
index bb24060dbe..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"
@@ -45,10 +9,6 @@
#include <QtCore/qdebug.h>
#include <QtGui/private/qpixmap_raster_p.h>
-#if QT_CONFIG(opengl)
-#include <QtOpenGL/qpa/qplatformbackingstoreopenglsupport.h>
-#endif
-
QT_BEGIN_NAMESPACE
class QWindowsGdiIntegrationPrivate
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 8c41cc135d..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"
@@ -47,7 +11,7 @@
#include <QtGui/qcolorspace.h>
#include <QtGui/qguiapplication.h>
#include <qpa/qplatformnativeinterface.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"));
@@ -574,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;
@@ -590,9 +563,9 @@ static int choosePixelFormat(HDC hdc,
}
// must be the last
bool srgbRequested = format.colorSpace() == QColorSpace::SRgb;
- int srgbValuePosition = 0;
+ int srgbCapableKeyPosition = 0;
if (srgbRequested) {
- srgbValuePosition = i;
+ srgbCapableKeyPosition = i;
iAttributes[i++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT;
iAttributes[i++] = TRUE;
}
@@ -606,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) {
@@ -615,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;
}
@@ -1291,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));
@@ -1329,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 2970f3d333..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
@@ -200,7 +164,7 @@ public:
static QWindowsOpengl32DLL opengl32;
};
-class QWindowsGLContext : public QWindowsOpenGLContext, public QPlatformInterface::QWGLContext
+class QWindowsGLContext : public QWindowsOpenGLContext, public QNativeInterface::QWGLContext
{
public:
explicit QWindowsGLContext(QOpenGLStaticContext *staticContext, QOpenGLContext *context);
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 03be0b9451..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>
@@ -198,7 +161,6 @@ bool QWindowsInputContext::hasCapability(Capability capability) const
void QWindowsInputContext::reset()
{
- QPlatformInputContext::reset();
if (!m_compositionContext.hwnd)
return;
qCDebug(lcQpaInputMethods) << __FUNCTION__;
@@ -275,25 +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");
- bool nativeVKDisabled = QCoreApplication::testAttribute(Qt::AA_DisableNativeVirtualKeyboard);
- if ((imModuleEmpty && !nativeVKDisabled)
- && 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 6ec5f6e37f..e1961c9976 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"
@@ -84,6 +48,11 @@
#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_NO_OPENGL)
@@ -92,6 +61,16 @@
#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);
@@ -99,38 +78,7 @@ 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.
-
-*/
+using namespace Qt::StringLiterals;
struct QWindowsIntegrationPrivate
{
@@ -161,7 +109,7 @@ 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;
@@ -171,7 +119,7 @@ bool parseIntOption(const QString &parameter,const QLatin1String &option,
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"
@@ -183,19 +131,19 @@ bool parseIntOption(const QString &parameter,const QLatin1String &option,
return true;
}
-using DarkModeHandlingFlag = QPlatformInterface::Private::QWindowsApplication::DarkModeHandlingFlag;
-using DarkModeHandling = QPlatformInterface::Private::QWindowsApplication::DarkModeHandling;
+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(u"fontengine=")) {
- if (param.endsWith(u"directwrite")) {
- options |= QWindowsIntegration::FontDatabaseDirectWrite;
+ if (param.endsWith(u"gdi")) {
+ options |= QWindowsIntegration::FontDatabaseGDI;
} else if (param.endsWith(u"freetype")) {
options |= QWindowsIntegration::FontDatabaseFreeType;
} else if (param.endsWith(u"native")) {
@@ -217,9 +165,10 @@ static inline unsigned parseOptions(const QStringList &paramList,
options |= QWindowsIntegration::DontUseColorFonts;
} 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 (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 == u"menus=none") {
@@ -228,8 +177,11 @@ static inline unsigned parseOptions(const QStringList &paramList,
options |= QWindowsIntegration::DontUseWMPointer;
} 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);
@@ -245,11 +197,12 @@ void QWindowsIntegrationPrivate::parseOptions(QWindowsIntegration *q, const QStr
initOpenGlBlacklistResources();
static bool dpiAwarenessSet = false;
- // 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;
+ // Default to per-monitor-v2 awareness (if available)
+ QtWindows::DpiAwareness dpiAwareness = QtWindows::DpiAwareness::PerMonitorVersion2;
+
int tabletAbsoluteRange = -1;
- DarkModeHandling darkModeHandling;
+ DarkModeHandling darkModeHandling = DarkModeHandlingFlag::DarkModeWindowFrames
+ | DarkModeHandlingFlag::DarkModeStyle;
m_options = ::parseOptions(paramList, &tabletAbsoluteRange, &dpiAwareness, &darkModeHandling);
q->setDarkModeHandling(darkModeHandling);
QWindowsFontDatabase::setFontOptions(m_options);
@@ -260,12 +213,12 @@ void QWindowsIntegrationPrivate::parseOptions(QWindowsIntegration *q, const QStr
QCoreApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents);
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;
@@ -292,7 +245,7 @@ QWindowsIntegration::QWindowsIntegration(const QStringList &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);
}
@@ -303,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
@@ -333,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);
}
@@ -343,7 +298,7 @@ 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;
}
@@ -353,15 +308,17 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
requested.geometry = window->isTopLevel()
? QHighDpi::toNativePixels(window->geometry(), window)
: QHighDpi::toNativeLocalPosition(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);
+ 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)
@@ -398,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;
}
@@ -466,9 +423,9 @@ 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;
}
@@ -498,12 +455,12 @@ QOpenGLContext *QWindowsIntegration::createOpenGLContext(HGLRC ctx, HWND window,
return nullptr;
if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) {
- QScopedPointer<QWindowsOpenGLContext> result(staticOpenGLContext->createContext(ctx, window));
+ 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.take());
+ contextPrivate->adopt(result.release());
return context;
}
}
@@ -527,17 +484,17 @@ QWindowsStaticOpenGLContext *QWindowsIntegration::staticOpenGLContext()
QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
{
if (!d->m_fontDatabase) {
-#if QT_CONFIG(directwrite3)
- if (d->m_options & QWindowsIntegration::FontDatabaseDirectWrite)
- d->m_fontDatabase = new QWindowsDirectWriteFontDatabase;
- else
-#endif
#ifndef QT_NO_FREETYPE
if (d->m_options & QWindowsIntegration::FontDatabaseFreeType)
d->m_fontDatabase = new QWindowsFontDatabaseFT;
else
#endif // QT_NO_FREETYPE
- d->m_fontDatabase = new QWindowsFontDatabase();
+#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;
}
@@ -585,14 +542,9 @@ QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) co
return QPlatformIntegration::styleHint(hint);
}
-Qt::KeyboardModifiers QWindowsIntegration::queryKeyboardModifiers() const
-{
- return QWindowsKeyMapper::queryKeyboardModifiers();
-}
-
-QList<int> QWindowsIntegration::possibleKeys(const QKeyEvent *e) const
+QPlatformKeyMapper *QWindowsIntegration::keyMapper() const
{
- return d->m_context.possibleKeys(e);
+ return d->m_context.keyMapper();
}
#if QT_CONFIG(clipboard)
@@ -639,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);
}
@@ -659,6 +611,157 @@ 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.
+ 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;
+ }
+#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 e0af1e6512..c271207741 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.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 QWINDOWSINTEGRATION_H
#define QWINDOWSINTEGRATION_H
@@ -46,7 +10,9 @@
#include <qpa/qplatformintegration.h>
#include <QtCore/qscopedpointer.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
@@ -58,7 +24,7 @@ class QWindowsStaticOpenGLContext;
class QWindowsIntegration : public QPlatformIntegration
#ifndef QT_NO_OPENGL
- , public QPlatformInterface::Private::QWindowsGLIntegration
+ , public QNativeInterface::Private::QWindowsGLIntegration
#endif
, public QWindowsApplication
{
@@ -79,7 +45,7 @@ public:
DontUseWMPointer = 0x400,
DetectAltGrModifier = 0x800,
RtlEnabled = 0x1000,
- FontDatabaseDirectWrite = 0x2000
+ FontDatabaseGDI = 0x2000
};
explicit QWindowsIntegration(const QStringList &paramList);
@@ -116,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; }
@@ -125,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
@@ -140,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 5f63adba52..0542473a4b 100644
--- a/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp
+++ b/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp
@@ -1,45 +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 "qwindowsinternalmimedata.h"
#include "qwindowscontext.h"
-#include "qwindowsmime.h"
+#include "qwindowsmimeregistry.h"
#include <QtCore/qdebug.h>
#include <QtCore/qvariant.h>
@@ -58,9 +22,9 @@
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
*/
@@ -70,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;
@@ -83,7 +47,7 @@ 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;
@@ -97,14 +61,14 @@ QVariant QWindowsInternalMimeData::retrieveData_sys(const QString &mimeType, QMe
return QVariant();
QVariant result;
- const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter();
+ 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.name()
<< " returns " << result.metaType().name()
- << (result.userType() != QVariant::ByteArray ? result.toString() : QStringLiteral("<data>"));
+ << (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 998b8c871e..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
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 229e485e22..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"
@@ -51,6 +15,7 @@
#include <QtGui/qevent.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
@@ -123,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 {
@@ -389,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
@@ -566,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
/**
@@ -634,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.._
@@ -691,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));
}
@@ -784,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);
@@ -792,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,
@@ -835,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);
}
/*!
@@ -903,7 +878,7 @@ 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)
@@ -948,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;
@@ -983,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;
}
@@ -1018,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;
@@ -1219,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:
@@ -1239,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;
}
@@ -1267,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;
@@ -1309,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;
@@ -1324,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);
@@ -1346,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)
@@ -1360,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();
@@ -1376,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) + int(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) + int(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 31d9d3e09b..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
@@ -265,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();
diff --git a/src/plugins/platforms/windows/qwindowsmenu.h b/src/plugins/platforms/windows/qwindowsmenu.h
index b94efbe713..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
@@ -45,7 +9,6 @@
#include <qpa/qplatformmenu.h>
#include <QtCore/qlist.h>
-#include <QtCore/qpair.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h
deleted file mode 100644
index 891ec44ecd..0000000000
--- a/src/plugins/platforms/windows/qwindowsmime.h
+++ /dev/null
@@ -1,94 +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 <QtGui/private/qwindowsmime_p.h>
-
-#include <QtCore/qt_windows.h>
-
-#include <QtCore/qlist.h>
-#include <QtCore/qvariant.h>
-
-QT_BEGIN_NAMESPACE
-
-class QDebug;
-class QMimeData;
-
-class QWindowsMimeConverter
-{
- Q_DISABLE_COPY_MOVE(QWindowsMimeConverter)
-public:
- using QWindowsMime = QPlatformInterface::Private::QWindowsMime;
-
- QWindowsMimeConverter();
- ~QWindowsMimeConverter();
-
- QWindowsMime *converterToMime(const QString &mimeType, IDataObject *pDataObj) const;
- QStringList allMimesForFormats(IDataObject *pDataObj) const;
- QWindowsMime *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(QWindowsMime *mime);
- void unregisterMime(QWindowsMime *mime) { m_mimes.removeOne(mime); }
-
- static int registerMimeType(const QString &mime);
-
- static QString clipboardFormatName(int cf);
-
-private:
- void ensureInitialized() const;
-
- mutable QList<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 9c43045d6a..8d147e8fa0 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmimeregistry.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 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>
@@ -55,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
@@ -96,7 +62,6 @@ struct BMP_BITMAPV5HEADER {
DWORD bV5ProfileSize;
DWORD bV5Reserved;
};
-static const int BMP_BITFIELDS = 3;
static const char dibFormatC[] = "dib";
@@ -114,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)
@@ -177,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];
@@ -213,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 qsizetype bpl = image.bytesPerLine();
- uchar *data = image.bits();
-
- auto *buf24 = new uchar[bpl];
- const qsizetype bpl24 = ((qsizetype(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)
@@ -412,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
@@ -445,106 +333,7 @@ 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
-
- 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
-*/
-
-
-/*!
-\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 QList<FORMATETC> QWindowsMime::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
-
- Returns a QList 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,
- QMetaType 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 QPlatformInterface::Private::QWindowsMime
+class QWindowsMimeText : public QWindowsMimeConverter
{
public:
bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const override;
@@ -558,7 +347,7 @@ public:
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();
}
/*
@@ -649,7 +438,7 @@ 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();
}
@@ -659,7 +448,8 @@ QList<FORMATETC> QWindowsMimeText::formatsForMime(const QString &mimeType, const
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;
}
@@ -673,7 +463,7 @@ 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()) {
@@ -700,7 +490,7 @@ QVariant QWindowsMimeText::convertToMime(const QString &mime, LPDATAOBJECT pData
return ret;
}
-class QWindowsMimeURI : public QPlatformInterface::Private::QWindowsMime
+class QWindowsMimeURI : public QWindowsMimeConverter
{
public:
QWindowsMimeURI();
@@ -717,8 +507,8 @@ private:
QWindowsMimeURI::QWindowsMimeURI()
{
- CF_INETURL_W = QWindowsMimeConverter::registerMimeType(QStringLiteral("UniformResourceLocatorW"));
- CF_INETURL = QWindowsMimeConverter::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
@@ -759,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;
}
@@ -771,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');
@@ -801,7 +591,7 @@ 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;
}
@@ -866,7 +656,7 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD
return QVariant();
}
-class QWindowsMimeHtml : public QPlatformInterface::Private::QWindowsMime
+class QWindowsMimeHtml : public QWindowsMimeConverter
{
public:
QWindowsMimeHtml();
@@ -887,7 +677,7 @@ private:
QWindowsMimeHtml::QWindowsMimeHtml()
{
- CF_HTML = QWindowsMimeConverter::registerMimeType(QStringLiteral("HTML Format"));
+ CF_HTML = registerMimeType(u"HTML Format"_s);
}
QList<FORMATETC> QWindowsMimeHtml::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
@@ -901,7 +691,7 @@ QList<FORMATETC> QWindowsMimeHtml::formatsForMime(const QString &mimeType, const
QString QWindowsMimeHtml::mimeForFormat(const FORMATETC &formatetc) const
{
if (getCf(formatetc) == CF_HTML)
- return QStringLiteral("text/html");
+ return u"text/html"_s;
return QString();
}
@@ -1004,7 +794,7 @@ bool QWindowsMimeHtml::convertFromMime(const FORMATETC &formatetc, const QMimeDa
#ifndef QT_NO_IMAGEFORMAT_BMP
-class QWindowsMimeImage : public QPlatformInterface::Private::QWindowsMime
+class QWindowsMimeImage : public QWindowsMimeConverter
{
public:
QWindowsMimeImage();
@@ -1046,7 +836,7 @@ 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();
}
@@ -1080,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);
@@ -1093,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);
}
}
@@ -1113,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;
}
}
@@ -1128,19 +918,22 @@ QVariant QWindowsMimeImage::convertToMime(const QString &mimeType, IDataObject *
QVariant result;
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")) {
@@ -1149,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
@@ -1158,7 +954,7 @@ QVariant QWindowsMimeImage::convertToMime(const QString &mimeType, IDataObject *
}
#endif
-class QBuiltInMimes : public QPlatformInterface::Private::QWindowsMime
+class QBuiltInMimes : public QWindowsMimeConverter
{
public:
QBuiltInMimes();
@@ -1179,10 +975,10 @@ private:
};
QBuiltInMimes::QBuiltInMimes()
-: QWindowsMime()
+: QWindowsMimeConverter()
{
- outFormats.insert(QWindowsMimeConverter::registerMimeType(QStringLiteral("application/x-color")), QStringLiteral("application/x-color"));
- inFormats.insert(QWindowsMimeConverter::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
@@ -1279,7 +1075,7 @@ QString QBuiltInMimes::mimeForFormat(const FORMATETC &formatetc) const
}
-class QLastResortMimes : public QPlatformInterface::Private::QWindowsMime
+class QLastResortMimes : public QWindowsMimeConverter
{
public:
@@ -1307,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);
}
}
@@ -1363,7 +1159,7 @@ QList<FORMATETC> QLastResortMimes::formatsForMime(const QString &mimeType, const
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(QWindowsMimeConverter::registerMimeType(mimeType), mimeType);
+ mit = formats.insert(registerMimeType(mimeType), mimeType);
if (mit != formats.end())
formatetcs += setCf(mit.key());
@@ -1375,7 +1171,7 @@ 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)
@@ -1407,7 +1203,7 @@ 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() : QWindowsMimeConverter::registerMimeType(mimeType);
+ const int cf = mit != formats.cend() ? mit.key() : registerMimeType(mimeType);
return canGetData(cf, pDataObj);
}
@@ -1424,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() : QWindowsMimeConverter::registerMimeType(mimeType);
+ const int cf = mit != formats.cend() ? mit.key() : registerMimeType(mimeType);
data = getData(cf, pDataObj);
}
if (!data.isEmpty())
@@ -1439,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
@@ -1457,7 +1253,7 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const
}
}
if (!ianaType)
- format = QLatin1String(x_qt_windows_mime) + clipFormat + u'"';
+ format = QLatin1StringView(x_qt_windows_mime) + clipFormat + u'"';
else
format = clipFormat;
}
@@ -1469,20 +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
- \sa QWindowsMime
+ \sa QWindowsMimeConverter
*/
-QWindowsMimeConverter::QWindowsMimeConverter() = default;
+QWindowsMimeRegistry::QWindowsMimeRegistry() = default;
-QWindowsMimeConverter::~QWindowsMimeConverter()
+QWindowsMimeRegistry::~QWindowsMimeRegistry()
{
qDeleteAll(m_mimes.begin(), m_mimes.begin() + m_internalMimeCount);
}
-QWindowsMimeConverter::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) {
@@ -1492,9 +1288,9 @@ QWindowsMimeConverter::QWindowsMime *QWindowsMimeConverter::converterToMime(cons
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;
@@ -1521,7 +1317,7 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con
return formats;
}
-QWindowsMimeConverter::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;
@@ -1532,7 +1328,7 @@ QWindowsMimeConverter::QWindowsMime *QWindowsMimeConverter::converterFromMime(co
return nullptr;
}
-QList<FORMATETC> QWindowsMimeConverter::allFormatsForMime(const QMimeData *mimeData) const
+QList<FORMATETC> QWindowsMimeRegistry::allFormatsForMime(const QMimeData *mimeData) const
{
ensureInitialized();
QList<FORMATETC> formatics;
@@ -1549,34 +1345,37 @@ QList<FORMATETC> QWindowsMimeConverter::allFormatsForMime(const QMimeData *mimeD
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,
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()) {
@@ -1593,7 +1392,7 @@ QVariant QWindowsMimeConverter::convertToMime(const QStringList &mimeTypes,
return QVariant();
}
-void QWindowsMimeConverter::registerMime(QWindowsMime *mime)
+void QWindowsMimeRegistry::registerMime(QWindowsMimeConverter *mime)
{
ensureInitialized();
m_mimes.append(mime);
@@ -1602,12 +1401,18 @@ void QWindowsMimeConverter::registerMime(QWindowsMime *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 QWindowsMimeConverter::registerMimeType(const QString &mime)
+int QWindowsMimeRegistry::registerMimeType(const QString &mime)
{
- const UINT f = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (mime.utf16()));
- if (!f)
- qErrnoWarning("QWindowsApplication::registerMimeType: Failed to register clipboard format");
+ 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);
}
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 02c59d4d27..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"
@@ -52,7 +16,8 @@
#include <QtGui/qcursor.h>
#include <QtCore/qdebug.h>
-#include <QtCore/qscopedpointer.h>
+
+#include <memory>
#include <windowsx.h>
@@ -128,6 +93,14 @@ static inline void compressMouseMove(MSG *msg)
QWindowsMouseHandler::QWindowsMouseHandler() = default;
+const QPointingDevice *QWindowsMouseHandler::primaryMouse()
+{
+ static QPointer<const QPointingDevice> result;
+ if (!result)
+ result = QPointingDevice::primaryPointingDevice();
+ return result;
+}
+
void QWindowsMouseHandler::clearEvents()
{
m_lastEventType = QEvent::None;
@@ -151,7 +124,7 @@ Qt::MouseButtons QWindowsMouseHandler::queryMouseButtons()
return result;
}
-static QPoint lastMouseMovePos;
+Q_CONSTINIT static QPoint lastMouseMovePos;
namespace {
struct MouseEvent {
@@ -252,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"
@@ -270,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);
@@ -281,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;
@@ -304,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);
@@ -343,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.
@@ -466,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);
}
@@ -490,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:
@@ -511,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);
}
@@ -539,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;
}
@@ -570,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;
}
@@ -596,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);
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);
@@ -651,10 +631,12 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
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;
}
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h
index 0b7f26f6c6..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,6 +9,7 @@
#include <QtCore/qpointer.h>
#include <QtCore/qhash.h>
+#include <QtCore/qsharedpointer.h>
#include <QtGui/qevent.h>
QT_BEGIN_NAMESPACE
@@ -56,10 +21,12 @@ class QWindowsMouseHandler
{
Q_DISABLE_COPY_MOVE(QWindowsMouseHandler)
public:
+ using QPointingDevicePtr = QSharedPointer<QPointingDevice>;
+
QWindowsMouseHandler();
- QPointingDevice *touchDevice() const { return m_touchDevice; }
- void setTouchDevice(QPointingDevice *d) { m_touchDevice = d; }
+ 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;
- QPointingDevice *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 a971cdae0b..e709123097 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.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 "qwindowsnativeinterface.h"
#include "qwindowswindow.h"
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h
index 8ef14e8603..a123c2b242 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.h
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.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 QWINDOWSNATIVEINTERFACE_H
#define QWINDOWSNATIVEINTERFACE_H
diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp
index c040137a6d..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>
@@ -102,7 +66,7 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
HRESULT hr = ResultFromScode(DATA_E_FORMATETC);
if (data) {
- const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter();
+ const QWindowsMimeRegistry &mc = QWindowsContext::instance()->mimeConverter();
if (auto converter = mc.converterFromMime(*pformatetc, data))
if (converter->convertFromMime(*pformatetc, data, pmedium))
hr = ResultFromScode(S_OK);
@@ -129,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);
}
@@ -180,7 +144,7 @@ QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppe
QList<FORMATETC> fmtetcs;
if (dwDirection == DATADIR_GET) {
- QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter();
+ QWindowsMimeRegistry &mc = QWindowsContext::instance()->mimeConverter();
fmtetcs = mc.allFormatsForMime(data);
} else {
FORMATETC formatetc;
diff --git a/src/plugins/platforms/windows/qwindowsole.h b/src/plugins/platforms/windows/qwindowsole.h
index c556a3fb9c..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/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);
@@ -83,7 +47,7 @@ private:
DWORD performedEffect = DROPEFFECT_NONE;
};
-class QWindowsOleEnumFmtEtc : public QWindowsComBase<IEnumFORMATETC>
+class QWindowsOleEnumFmtEtc : public QComObject<IEnumFORMATETC>
{
public:
explicit QWindowsOleEnumFmtEtc(const QList<FORMATETC> &fmtetcs);
diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h
index 78ff23669c..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
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index 0c348a9b71..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
@@ -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()
@@ -224,13 +183,13 @@ 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;
}
@@ -283,7 +242,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c
#if defined(QT_NO_OPENGL)
Q_UNUSED(gpu);
Q_UNUSED(requested);
- return 0;
+ return {};
#else
QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.vendorId, gpu.deviceId, gpu.driverVersion, gpu.description);
SupportedRenderersCache *srCache = supportedRenderersCache();
@@ -358,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 9091949699..abda0c2dc1 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.h
+++ b/src/plugins/platforms/windows/qwindowsopengltester.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 QWINDOWSOPENGLTESTER_H
#define QWINDOWSOPENGLTESTER_H
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index 095aea2b95..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"
@@ -58,7 +21,6 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qloggingcategory.h>
-#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/qqueue.h>
#include <algorithm>
@@ -79,7 +41,6 @@ qint64 QWindowsPointerHandler::m_nextInputDeviceId = 1;
QWindowsPointerHandler::~QWindowsPointerHandler()
{
- delete m_touchDevice;
}
bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
@@ -87,7 +48,7 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
*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;
}
@@ -101,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;
}
@@ -119,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;
}
@@ -140,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;
}
@@ -152,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;
}
@@ -317,7 +276,7 @@ static bool isValidWheelReceiver(QWindow *candidate)
return false;
}
-QPointingDevice *QWindowsPointerHandler::createTouchDevice(bool mouseEmulation)
+QWindowsPointerHandler::QPointingDevicePtr QWindowsPointerHandler::createTouchDevice(bool mouseEmulation)
{
const int digitizers = GetSystemMetrics(SM_DIGITIZER);
if (!(digitizers & (NID_INTEGRATED_TOUCH | NID_EXTERNAL_TOUCH)))
@@ -336,15 +295,19 @@ QPointingDevice *QWindowsPointerHandler::createTouchDevice(bool mouseEmulation)
capabilities.setFlag(QInputDevice::Capability::MouseEmulation);
}
- qCDebug(lcQpaEvents) << "Digitizers:" << Qt::hex << Qt::showbase << (digitizers & ~NID_READY)
+ 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
- return new QPointingDevice(QString(), m_nextInputDeviceId++,
- type, QPointingDevice::PointerType::Finger,
- capabilities, maxTouchPoints, buttonCount);
+ 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()
@@ -456,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.
@@ -463,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;
@@ -479,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;
@@ -492,6 +467,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
<< " count=" << Qt::dec << count;
QEventPoint::States allStates;
+ QSet<int> inputIds;
for (quint32 i = 0; i < count; ++i) {
if (QWindowsContext::verbose > 1)
@@ -504,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);
@@ -527,31 +506,57 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_DOWN) {
touchPoint.state = QEventPoint::State::Pressed;
- m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition);
+ m_lastTouchPoints.insert(touchPoint.id, touchPoint);
} else if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_UP) {
touchPoint.state = QEventPoint::State::Released;
- m_lastTouchPositions.remove(touchPoint.id);
+ m_lastTouchPoints.remove(touchPoint.id);
} else {
touchPoint.state = stationaryTouchPoint ? QEventPoint::State::Stationary : QEventPoint::State::Updated;
- m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition);
+ 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 == 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)
{
@@ -562,31 +567,34 @@ 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 QInputDevice::DeviceType device = QInputDevice::DeviceType::Stylus;
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.
@@ -604,9 +612,34 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
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(int(device), int(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.
@@ -619,12 +652,12 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
m_windowUnderPointer = nullptr;
m_currentWindow = nullptr;
}
- QWindowSystemInterface::handleTabletLeaveProximityEvent(int(device), int(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)
@@ -642,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, int(device), int(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.
}
}
@@ -694,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;
}
@@ -707,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)
@@ -737,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);
@@ -771,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
}
@@ -803,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 3b204c675b..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,8 +9,10 @@
#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
@@ -57,14 +23,16 @@ 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);
- QPointingDevice *touchDevice() const { return m_touchDevice; }
- void setTouchDevice(QPointingDevice *d) { m_touchDevice = d; }
- static QPointingDevice *createTouchDevice(bool mouseEmulation);
+ 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; }
@@ -76,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
- QPointingDevice *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;
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index a15a39c2a4..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,14 +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));
@@ -65,17 +43,223 @@ 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};
}
+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)
{
MONITORINFOEX info;
@@ -87,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 == u"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)) {
@@ -103,20 +293,46 @@ 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;
- if (info.dwFlags & MONITORINFOF_PRIMARY) {
+ if (info.dwFlags & MONITORINFOF_PRIMARY)
data->flags |= QWindowsScreenData::PrimaryScreen;
- if ((data->flags & QWindowsScreenData::LockScreen) == 0)
- QWindowsFontDatabase::setDefaultVerticalDPI(data->dpi.second);
- }
return true;
}
@@ -126,6 +342,16 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM
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
@@ -152,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)
@@ -185,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
{
@@ -245,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;
}
@@ -256,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;
}
@@ -292,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;
@@ -305,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(),
@@ -321,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
@@ -337,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;
@@ -405,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;
@@ -437,52 +662,66 @@ QPlatformScreen::SubpixelAntialiasingType QWindowsScreen::subpixelAntialiasingTy
\internal
*/
-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;
}
@@ -506,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
@@ -548,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)
@@ -558,14 +797,14 @@ 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
@@ -573,7 +812,6 @@ bool QWindowsScreenManager::handleScreenChanges()
if (auto theme = QWindowsTheme::instance()) // QTBUG-85734/Wine
theme->refreshFonts();
}
- QHighDpiScaling::updateHighDpiScaling();
return true;
}
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 1989934ad4..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,9 +7,9 @@
#include "qtwindowsglobal.h"
#include <QtCore/qlist.h>
-#include <QtCore/qpair.h>
#include <QtCore/qscopedpointer.h>
#include <qpa/qplatformscreen.h>
+#include <QtGui/qscreen_platform.h>
QT_BEGIN_NAMESPACE
@@ -66,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
@@ -86,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;
@@ -103,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(); }
@@ -115,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;
@@ -125,15 +99,17 @@ private:
class QWindowsScreenManager
{
+ Q_DISABLE_COPY_MOVE(QWindowsScreenManager)
public:
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;
@@ -144,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 fe2d8a36c0..89f93fd161 100644
--- a/src/plugins/platforms/windows/qwindowsservices.cpp
+++ b/src/plugins/platforms/windows/qwindowsservices.cpp
@@ -1,43 +1,6 @@
-/****************************************************************************
-**
-** 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>
@@ -48,34 +11,88 @@
#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 *path) : m_path(path) { }
+ 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
{
- if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) {
- m_result = ShellExecute(nullptr, nullptr, m_path, nullptr, nullptr, SW_SHOWNORMAL);
- CoUninitialize();
- }
+ 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_path;
+ 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()
@@ -85,7 +102,9 @@ static inline bool shellExecute(const QUrl &url)
// 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(reinterpret_cast<const wchar_t *>(nativeFilePath.utf16()));
+ QWindowsShellExecuteThread thread(nullptr,
+ reinterpret_cast<const wchar_t *>(nativeFilePath.utf16()),
+ nullptr);
thread.start();
thread.wait();
@@ -93,7 +112,7 @@ static inline bool shellExecute(const QUrl &url)
// ShellExecute returns a value greater than 32 if successful
if (result <= 32) {
- qWarning("ShellExecute '%ls' failed (error %zu).", qUtf16Printable(url.toString()), result);
+ qWarning("%s", qPrintable(msgShellExecuteFailed(url, result)));
return false;
}
return true;
@@ -111,15 +130,15 @@ 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.
+ // 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};
@@ -135,10 +154,15 @@ static inline bool launchMail(const QUrl &url)
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 = 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);
@@ -146,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
@@ -170,7 +194,8 @@ bool QWindowsServices::openUrl(const QUrl &url)
const QString scheme = url.scheme();
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 7c473e66b6..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"
@@ -65,7 +17,6 @@
#include <QtCore/qsettings.h>
#include <qpa/qwindowsysteminterface.h>
-#include <qt_windows.h>
#include <commctrl.h>
#include <shellapi.h>
#include <shlobj.h>
@@ -73,6 +24,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::Literals::StringLiterals;
+
static const UINT q_uNOTIFYICONID = 0;
static uint MYWM_TASKBARCREATED = 0;
@@ -136,9 +89,6 @@ static int indexOfHwnd(HWND hwnd)
extern "C" LRESULT QT_WIN_CALLBACK qWindowsTrayIconWndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
- // QTBUG-79248: Trigger screen update if there are no other windows.
- if (message == WM_DPICHANGED && QGuiApplication::topLevelWindows().isEmpty())
- QWindowsContext::instance()->screenManager().handleScreenChanges();
if (message == MYWM_TASKBARCREATED || message == MYWM_NOTIFYICON
|| message == WM_INITMENU || message == WM_INITMENUPOPUP
|| message == WM_CLOSE || message == WM_COMMAND) {
@@ -168,7 +118,7 @@ static inline HWND createTrayIconMessageWindow()
return nullptr;
// Register window class in the platform plugin.
const QString className =
- ctx->registerWindowClass(QWindowsContext::classNamePrefix() + QStringLiteral("TrayIconMessageWindowClass"),
+ ctx->registerWindowClass(QWindowsContext::classNamePrefix() + "TrayIconMessageWindowClass"_L1,
qWindowsTrayIconWndProc);
const wchar_t windowName[] = L"QTrayIconMessageWindow";
return CreateWindowEx(0, reinterpret_cast<const wchar_t *>(className.utf16()),
@@ -214,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);
@@ -235,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);
@@ -268,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
@@ -344,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();
}
@@ -361,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;
@@ -454,8 +426,15 @@ bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result)
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 f86dbb0c5f..ceebb483d2 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 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;
/*!
@@ -320,14 +325,6 @@ void QWindowsTabletSupport::notifyActivate()
qCDebug(lcQpaTablet) << __FUNCTION__ << result;
}
-static inline int indexOfDevice(const QList<QWindowsTabletDeviceData> &devices, qint64 uniqueId)
-{
- for (int i = 0; i < devices.size(); ++i)
- if (devices.at(i).uniqueId == uniqueId)
- return i;
- return -1;
-}
-
static inline QInputDevice::DeviceType deviceType(const UINT cursorType)
{
if (((cursorType & 0x0006) == 0x0002) && ((cursorType & CursorTypeBitMask) != 0x0902))
@@ -366,10 +363,65 @@ static inline QPointingDevice::PointerType pointerType(unsigned currentCursor)
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,22 +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);
- result.zCapability = (cursorType == 0x0004);
- 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)
@@ -401,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,
- int(m_devices.at(m_currentDevice).currentDevice),
- int(m_devices.at(m_currentDevice).currentPointerType),
- m_devices.at(m_currentDevice).uniqueId);
- } else {
- QWindowSystemInterface::handleTabletLeaveProximityEvent(int(m_devices.at(m_currentDevice).currentDevice),
- int(m_devices.at(m_currentDevice).currentPointerType),
- m_devices.at(m_currentDevice).uniqueId);
-
- }
+ leaveProximity(totalPacks > 0 ? proximityBuffer[0].pkTime : 0u);
return true;
}
@@ -425,48 +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);
- // TODO use the version taking a QPointingDevice, and own those instances; replace QWindowsTabletDeviceData
- // TODO QWindowSystemInterface::registerInputDevice() as early as possible, and before sending any events from it
- QWindowSystemInterface::handleTabletEnterProximityEvent(proximityBuffer[0].pkTime,
- int(m_devices.at(m_currentDevice).currentDevice),
- int(m_devices.at(m_currentDevice).currentPointerType),
- m_devices.at(m_currentDevice).uniqueId);
+ << m_currentDevice.data();
+ enterProximity(proximityBuffer[0].pkTime);
return true;
}
@@ -520,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 auto currentDevice = m_devices.at(m_currentDevice).currentDevice;
- const auto 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:
@@ -545,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 = m_devices.at(m_currentDevice).zCapability ? 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();
@@ -583,12 +649,12 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
Q_ASSERT(platformWindow);
const QPoint localPos = platformWindow->mapFromGlobal(globalPos);
- const qreal pressureNew = packet.pkButtons && (currentPointer == QPointingDevice::PointerType::Pen || currentPointer == QPointingDevice::PointerType::Eraser) ?
- m_devices.at(m_currentDevice).scalePressure(packet.pkNormalPressure) :
- qreal(0);
- const qreal tangentialPressure = currentDevice == QInputDevice::DeviceType::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;
@@ -617,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,
- int(currentDevice), int(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 229677dae4..fb639294d3 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.h
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.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 QWINDOWSTABLETSUPPORT_H
#define QWINDOWSTABLETSUPPORT_H
@@ -47,6 +11,7 @@
#include <QtCore/qhash.h>
#include <QtCore/qlist.h>
#include <QtCore/qpoint.h>
+#include <QtCore/qsharedpointer.h>
#include <wintab.h>
@@ -83,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;
@@ -99,13 +66,31 @@ struct QWindowsTabletDeviceData
int maxY = 0;
int minZ = 0;
int maxZ = 0;
- qint64 uniqueId = 0;
- QInputDevice::DeviceType currentDevice = QInputDevice::DeviceType::Unknown;
- QPointingDevice::PointerType currentPointerType = QPointingDevice::PointerType::Unknown;
+ 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
@@ -117,6 +102,9 @@ class QWindowsTabletSupport
explicit QWindowsTabletSupport(HWND window, HCTX context);
public:
+ using DevicePtr = QSharedPointer<QWinTabPointingDevice>;
+ using Devices = QList<DevicePtr>;
+
enum Mode
{
PenMode,
@@ -146,16 +134,29 @@ public:
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;
static int m_absoluteRange;
bool m_tiltSupport = false;
- QList<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 0c778ecd24..488935e02d 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -1,75 +1,35 @@
-/****************************************************************************
-**
-** 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 "qwindowsscreen.h"
-#include "qt_windows.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/qoperatingsystemversion.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>
@@ -81,30 +41,19 @@
#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>
-QT_BEGIN_NAMESPACE
+# include <winrt/Windows.UI.ViewManagement.h>
+#endif // QT_CONFIG(cpp_winrt)
-static inline QColor COLORREFToQColor(COLORREF cr)
-{
- return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr));
-}
+QT_BEGIN_NAMESPACE
-static inline QTextStream& operator<<(QTextStream &str, const QColor &c)
-{
- str.setIntegerBase(16);
- str.setFieldWidth(2);
- str.setPadChar(u'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)
{
@@ -129,128 +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;
-}
-
-// Dark Mode constants
-enum DarkModeColors : QRgb {
- darkModeBtnHighlightRgb = 0xc0c0c0,
- darkModeBtnShadowRgb = 0x808080,
- darkModeHighlightRgb = 0x0055ff, // deviating from 0x800080
- darkModeMenuHighlightRgb = darkModeHighlightRgb
-};
+Q_APPLICATION_STATIC(QShGetFileInfoThread, s_shGetFileInfoThread)
// from QStyle::standardPalette
static inline QPalette standardPalette()
@@ -269,57 +249,47 @@ static inline QPalette standardPalette()
return palette;
}
+static QColor placeHolderColor(QColor textColor)
+{
+ 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.
+*/
static void 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));
- const QColor btnFace = getSysColor(COLOR_BTNFACE);
result.setColor(QPalette::Button, btnFace);
- const QColor btnHighlight = getSysColor(COLOR_BTNHIGHLIGHT);
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::Text, textColor);
+ result.setColor(QPalette::PlaceholderText, placeHolderColor(textColor));
result.setColor(QPalette::BrightText, btnHighlight);
result.setColor(QPalette::Base, getSysColor(COLOR_WINDOW));
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));
-}
-
-static void populateDarkSystemBasePalette(QPalette &result)
-{
- const QColor darkModeWindowText = Qt::white;
- result.setColor(QPalette::WindowText, darkModeWindowText);
- const QColor darkModebtnFace = Qt::black;
- result.setColor(QPalette::Button, darkModebtnFace);
- const QColor btnHighlight = QColor(darkModeBtnHighlightRgb);
- result.setColor(QPalette::Light, btnHighlight);
- result.setColor(QPalette::Dark, QColor(darkModeBtnShadowRgb));
- result.setColor(QPalette::Mid, result.button().color().darker(150));
- result.setColor(QPalette::Text, darkModeWindowText);
- result.setColor(QPalette::BrightText, btnHighlight);
- result.setColor(QPalette::Base, darkModebtnFace);
- result.setColor(QPalette::Window, darkModebtnFace);
- result.setColor(QPalette::ButtonText, darkModeWindowText);
- result.setColor(QPalette::Midlight, darkModeWindowText);
- result.setColor(QPalette::Shadow, darkModeWindowText);
- result.setColor(QPalette::Highlight, QColor(darkModeHighlightRgb));
- result.setColor(QPalette::HighlightedText, darkModeWindowText);
-}
+ result.setColor(QPalette::Accent, accent);
-static QPalette systemPalette(bool light)
-{
- QPalette result = standardPalette();
- if (light)
- populateLightSystemBasePalette(result);
- else
- populateDarkSystemBasePalette(result);
-
- result.setColor(QPalette::Link, Qt::blue);
- result.setColor(QPalette::LinkVisited, Qt::magenta);
+ 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());
@@ -327,35 +297,79 @@ static QPalette systemPalette(bool light)
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,
- light ? getSysColor(COLOR_HIGHLIGHT) : QColor(darkModeHighlightRgb));
- result.setColor(QPalette::Disabled, QPalette::HighlightedText,
- light ? getSysColor(COLOR_HIGHLIGHTTEXT) : QColor(Qt::white));
- result.setColor(QPalette::Disabled, QPalette::Base,
- result.window().color());
- return result;
+static void 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, bool light)
{
QPalette result(systemPalette);
- const QColor tipBgColor = light ? getSysColor(COLOR_INFOBK) : QColor(Qt::black);
- const QColor tipTextColor = light ? getSysColor(COLOR_INFOTEXT) : QColor(Qt::white);
+ 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);
@@ -369,8 +383,7 @@ static inline QPalette toolTipPalette(const QPalette &systemPalette, bool light)
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);
@@ -382,11 +395,13 @@ static inline QPalette toolTipPalette(const QPalette &systemPalette, bool light)
static inline QPalette menuPalette(const QPalette &systemPalette, bool light)
{
+ if (!light)
+ return systemPalette;
+
QPalette result(systemPalette);
- const QColor menuColor = light ? getSysColor(COLOR_MENU) : QColor(Qt::black);
- const QColor menuTextColor = light ? getSysColor(COLOR_MENUTEXT) : QColor(Qt::white);
- const QColor disabled = light
- ? getSysColor(COLOR_GRAYTEXT) : QColor(darkModeBtnHighlightRgb);
+ 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);
@@ -395,9 +410,7 @@ static inline QPalette menuPalette(const QPalette &systemPalette, bool light)
result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
result.setColor(QPalette::Disabled, QPalette::Text, disabled);
const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false);
- const QColor highlightColor = light
- ? (getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT))
- : QColor(darkModeMenuHighlightRgb);
+ 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,
@@ -422,13 +435,14 @@ static inline QPalette menuPalette(const QPalette &systemPalette, bool light)
static inline QPalette *menuBarPalette(const QPalette &menuPalette, bool light)
{
QPalette *result = nullptr;
- if (booleanSystemParametersInfo(SPI_GETFLATMENU, false)) {
- result = new QPalette(menuPalette);
- const QColor menubar(light ? getSysColor(COLOR_MENUBAR) : QColor(Qt::black));
- 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;
}
@@ -438,6 +452,7 @@ QWindowsTheme *QWindowsTheme::m_instance = nullptr;
QWindowsTheme::QWindowsTheme()
{
m_instance = this;
+ s_darkMode = QWindowsTheme::queryDarkMode();
std::fill(m_fonts, m_fonts + NFonts, nullptr);
std::fill(m_palettes, m_palettes + NPalettes, nullptr);
refresh();
@@ -453,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()
@@ -514,12 +532,40 @@ 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
+{
+ if (queryHighContrast())
+ return Qt::ColorScheme::Unknown;
+ return s_darkMode ? Qt::ColorScheme::Dark : Qt::ColorScheme::Light;
+}
+
+void QWindowsTheme::handleSettingsChanged()
+{
+ const bool darkMode = QWindowsTheme::queryDarkMode();
+ const bool darkModeChanged = darkMode != QWindowsTheme::s_darkMode;
+ s_darkMode = darkMode;
+ auto integration = QWindowsIntegration::instance();
+ integration->updateApplicationBadge();
+ if (integration->darkModeHandling().testFlag(QWindowsApplication::DarkModeStyle)) {
+ QWindowsTheme::instance()->refresh();
+ QWindowSystemInterface::handleThemeChange();
+ }
+ if (darkModeChanged) {
+ if (integration->darkModeHandling().testFlag(QWindowsApplication::DarkModeWindowFrames)) {
+ for (QWindowsWindow *w : std::as_const(QWindowsContext::instance()->windows()))
+ w->setDarkBorder(s_darkMode);
+ }
+ }
+}
+
void QWindowsTheme::clearPalettes()
{
qDeleteAll(m_palettes, m_palettes + NPalettes);
@@ -528,29 +574,64 @@ void QWindowsTheme::clearPalettes()
void QWindowsTheme::refreshPalettes()
{
-
if (!QGuiApplication::desktopSettingsAware())
return;
const bool light =
- !QWindowsContext::isDarkMode()
+ !s_darkMode
|| !QWindowsIntegration::instance()->darkModeHandling().testFlag(QWindowsApplication::DarkModeStyle);
- m_palettes[SystemPalette] = new QPalette(systemPalette(light));
+ clearPalettes();
+ m_palettes[SystemPalette] = new QPalette(QWindowsTheme::systemPalette(light ? Qt::ColorScheme::Light : Qt::ColorScheme::Dark));
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[ButtonPalette] = new QPalette(*m_palettes[SystemPalette]);
- m_palettes[ButtonPalette]->setColor(QPalette::Button, QColor(0x666666u));
- const QColor checkBoxBlue(0x0078d7u);
- const QColor white(Qt::white);
m_palettes[CheckBoxPalette] = new QPalette(*m_palettes[SystemPalette]);
- m_palettes[CheckBoxPalette]->setColor(QPalette::Window, checkBoxBlue);
- m_palettes[CheckBoxPalette]->setColor(QPalette::Base, checkBoxBlue);
- m_palettes[CheckBoxPalette]->setColor(QPalette::Button, checkBoxBlue);
- m_palettes[CheckBoxPalette]->setColor(QPalette::ButtonText, white);
+ 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::Light:
+ populateLightSystemBasePalette(result);
+ break;
+ case Qt::ColorScheme::Dark:
+ populateDarkSystemBasePalette(result);
+ break;
+ default:
+ qFatal("Unknown color scheme");
+ 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()
@@ -592,20 +673,22 @@ void QWindowsTheme::refreshFonts()
clearFonts();
if (!QGuiApplication::desktopSettingsAware())
return;
+
+ const int dpi = 96;
NONCLIENTMETRICS ncm;
- auto screenManager = QWindowsContext::instance()->screenManager();
- QWindowsContext::nonClientMetricsForScreen(&ncm, screenManager.screens().value(0));
- qCDebug(lcQpaWindows) << __FUNCTION__ << 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);
@@ -662,13 +745,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
@@ -779,15 +858,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;
+ }
}
}
@@ -821,7 +903,7 @@ 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 += u'l';
switch (imageListSize) {
@@ -857,10 +939,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}};
@@ -869,16 +950,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;
}
@@ -912,19 +989,16 @@ QString QWindowsFileIconEngine::cacheKey() const
|| !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;
@@ -933,13 +1007,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);
@@ -955,7 +1025,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;
@@ -967,43 +1036,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;
@@ -1014,6 +1083,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();
@@ -1040,9 +1114,7 @@ bool QWindowsTheme::useNativeMenus()
bool QWindowsTheme::queryDarkMode()
{
- if (QOperatingSystemVersion::current()
- < QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 17763)
- || queryHighContrast()) {
+ if (queryHighContrast()) {
return false;
}
const auto setting = QWinRegistryKey(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)")
@@ -1052,7 +1124,11 @@ bool QWindowsTheme::queryDarkMode()
bool QWindowsTheme::queryHighContrast()
{
- return booleanSystemParametersInfo(SPI_GETHIGHCONTRAST, false);
+ 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
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index af28f2878c..6f444d8408 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(); }
@@ -92,6 +64,8 @@ public:
static const char *name;
+ static QPalette systemPalette(Qt::ColorScheme);
+
private:
void clearPalettes();
void refreshPalettes();
@@ -99,6 +73,7 @@ private:
void refreshIconPixmapSizes();
static QWindowsTheme *m_instance;
+ static inline bool s_darkMode = false;
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 a31e00c0ac..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
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 4b9293cc64..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
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 5987324ac1..03c5d149a6 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;
}
@@ -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.
@@ -552,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;
}
}
@@ -569,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
@@ -702,55 +798,68 @@ 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)
{
- return w->isTopLevel() && !w->flags().testFlag(Qt::FramelessWindowHint);
+ 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
@@ -781,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
@@ -811,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;
@@ -820,11 +930,8 @@ QWindowsWindowData
return result;
}
- if (QWindowsContext::isDarkMode()
- && QWindowsIntegration::instance()->darkModeHandling().testFlag(QWindowsApplication::DarkModeWindowFrames)
- && shouldApplyDarkFrame(w)) {
+ if (QWindowsTheme::instance()->colorScheme() == Qt::ColorScheme::Dark && shouldApplyDarkFrame(w))
QWindowsWindow::setDarkBorderToWindow(result.hwnd, true);
- }
if (mirrorParentWidth != 0) {
context->obtainedPos.setX(mirrorParentWidth - context->obtainedSize.width()
@@ -834,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;
@@ -854,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 "
@@ -908,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.
@@ -918,76 +1041,84 @@ static QSize toNativeSizeConstrained(QSize dip, const QScreen *s)
\internal
*/
-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)
@@ -1003,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;
@@ -1039,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
@@ -1054,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,
@@ -1089,7 +1220,7 @@ bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w)
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)
@@ -1125,7 +1256,7 @@ 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>
@@ -1150,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
@@ -1161,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()));
}
@@ -1227,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)
@@ -1235,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.
@@ -1253,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
@@ -1290,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();
@@ -1315,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 << '+'
@@ -1335,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).
@@ -1352,6 +1488,7 @@ void QWindowCreationContext::applyToMinMaxInfo(MINMAXINFO *mmi) const
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),
@@ -1365,14 +1502,12 @@ 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);
@@ -1400,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();
@@ -1420,14 +1556,15 @@ 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
@@ -1451,7 +1588,7 @@ void QWindowsWindow::fireFullExpose(bool 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)
@@ -1558,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.
@@ -1600,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();
@@ -1780,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);
@@ -1831,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;
@@ -1855,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;
}
@@ -1907,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).
@@ -1914,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),
@@ -1926,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 {
@@ -1941,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:
@@ -1978,21 +2252,23 @@ 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
// Check on currentScreen as it can be 0 when resuming a session (QTBUG-80436).
- if (mode == FromGeometryChange && currentScreen != nullptr
- && !equalDpi(currentScreen->logicalDpi(), newScreen->logicalDpi())) {
+ const bool changingDpi = !equalDpi(QDpi(savedDpi(), savedDpi()), newScreen->logicalDpi());
+ if (mode == FromGeometryChange && currentScreen != nullptr && changingDpi)
return;
- }
- qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
+
+ qCDebug(lcQpaWindow).noquote().nospace() << __FUNCTION__
<< ' ' << window() << " \"" << (currentScreen ? currentScreen->name() : QString())
<< "\"->\"" << newScreen->name() << '"';
updateFullFrameMargins();
@@ -2003,14 +2279,12 @@ 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())) {
@@ -2023,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;
@@ -2033,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;
@@ -2064,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();
}
@@ -2086,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()
@@ -2100,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)
@@ -2117,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);
@@ -2162,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) {
@@ -2180,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;
}
@@ -2195,13 +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));
+ 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);
@@ -2209,6 +2475,14 @@ 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();
@@ -2232,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) {
@@ -2268,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();
@@ -2276,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.
@@ -2303,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 {
@@ -2394,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);
@@ -2407,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);
@@ -2434,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();
@@ -2452,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;
@@ -2478,8 +2764,10 @@ 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;
}
}
@@ -2495,35 +2783,71 @@ void QWindowsWindow::updateFullFrameMargins()
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);
}
}
@@ -2578,41 +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.
- const auto activationBehavior = QWindowsIntegration::instance()->windowActivationBehavior();
- if (QGuiApplication::applicationState() != Qt::ApplicationActive
- && activationBehavior == QWindowsApplication::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)
@@ -2621,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) {
@@ -2635,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;
@@ -2707,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
@@ -2781,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;
@@ -2860,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)
@@ -2931,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);
}
@@ -2973,7 +3293,7 @@ static bool queryDarkBorder(HWND hwnd)
SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &result, sizeof(result)))
|| SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &result, sizeof(result)));
if (!ok)
- qWarning("%s: Unable to retrieve dark window border setting.", __FUNCTION__);
+ qCWarning(lcQpaWindow, "%s: Unable to retrieve dark window border setting.", __FUNCTION__);
return result == TRUE;
}
@@ -2984,14 +3304,18 @@ bool QWindowsWindow::setDarkBorderToWindow(HWND hwnd, bool d)
SUCCEEDED(DwmSetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &darkBorder, sizeof(darkBorder)))
|| SUCCEEDED(DwmSetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &darkBorder, sizeof(darkBorder)));
if (!ok)
- qWarning("%s: Unable to set dark window border.", __FUNCTION__);
+ qCWarning(lcQpaWindow, "%s: Unable to set %s window border.", __FUNCTION__, d ? "dark" : "light");
return ok;
}
void QWindowsWindow::setDarkBorder(bool d)
{
- if (shouldApplyDarkFrame(window()) && queryDarkBorder(m_data.hwnd) != d)
- setDarkBorderToWindow(m_data.hwnd, d);
+ // respect explicit opt-out and incompatible palettes or styles
+ d = d && shouldApplyDarkFrame(window());
+ if (queryDarkBorder(m_data.hwnd) == d)
+ return;
+
+ setDarkBorderToWindow(m_data.hwnd, d);
}
QWindowsMenuBar *QWindowsWindow::menuBar() const
@@ -3004,6 +3328,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.
@@ -3016,6 +3347,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;
@@ -3024,7 +3359,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);
}
@@ -3050,7 +3385,7 @@ void *QWindowsWindow::surface(void *nativeConfig, int *err)
#elif defined(QT_NO_OPENGL)
Q_UNUSED(err);
Q_UNUSED(nativeConfig);
- return 0;
+ return nullptr;
#endif
#ifndef QT_NO_OPENGL
if (!m_surface) {
@@ -3107,24 +3442,6 @@ void QWindowsWindow::registerTouchWindow()
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
-}
-
void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border)
{
if (QPlatformWindow *handle = window->handle())
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 827e4cc288..024711e7f3 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.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 QWINDOWSWINDOW_H
#define QWINDOWSWINDOW_H
@@ -62,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);
@@ -113,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;
@@ -125,12 +91,12 @@ struct QWindowsWindowData
};
class QWindowsBaseWindow : public QPlatformWindow,
- public QPlatformInterface::Private::QWindowsWindow
+ public QNativeInterface::Private::QWindowsWindow
{
Q_DISABLE_COPY_MOVE(QWindowsBaseWindow)
public:
- using TouchWindowTouchType = QPlatformInterface::Private::QWindowsApplication::TouchWindowTouchType;
- using TouchWindowTouchTypes = QPlatformInterface::Private::QWindowsApplication::TouchWindowTouchTypes;
+ using TouchWindowTouchType = QNativeInterface::Private::QWindowsApplication::TouchWindowTouchType;
+ using TouchWindowTouchTypes = QNativeInterface::Private::QWindowsApplication::TouchWindowTouchTypes;
explicit QWindowsBaseWindow(QWindow *window) : QPlatformWindow(window) {}
@@ -219,7 +185,6 @@ public:
WithinSetParent = 0x2,
WithinSetGeometry = 0x8,
OpenGLSurface = 0x10,
- OpenGL_ES2 = 0x20,
OpenGLDoubleBuffered = 0x40,
OpenGlPixelFormatInitialized = 0x80,
BlockedByModal = 0x100,
@@ -236,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);
@@ -253,6 +219,8 @@ public:
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;
@@ -307,18 +275,21 @@ public:
QWindowsMenuBar *menuBar() const;
void setMenuBar(QWindowsMenuBar *mb);
- QMargins customMargins() const override { return m_data.customMargins; }
+ 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();
@@ -328,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;
@@ -352,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); }
@@ -372,6 +343,10 @@ public:
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;
@@ -405,6 +380,7 @@ private:
HICON m_iconSmall = nullptr;
HICON m_iconBig = nullptr;
void *m_surface = nullptr;
+ int m_savedDpi = 96;
static bool m_screenForGLInitialized;
@@ -413,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 0903f5a618..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,14 +15,15 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtCore/qt_windows.h>
#include <qpa/qplatformintegration.h>
-#include <QtGui/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()
{
@@ -72,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())
@@ -80,7 +47,7 @@ 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;
}
}
@@ -112,8 +79,8 @@ static QString alertSound(const QObject *object)
static QString soundFileName(const QString &soundName)
{
- const QString key = QStringLiteral("AppEvents\\Schemes\\Apps\\.Default\\")
- + soundName + QStringLiteral("\\.Current");
+ const QString key = "AppEvents\\Schemes\\Apps\\.Default\\"_L1
+ + soundName + "\\.Current"_L1;
return QWinRegistryKey(HKEY_CURRENT_USER, key).stringValue(L"");
}
@@ -131,6 +98,7 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
if (!event)
return;
+ // Always handle system sound events
switch (event->type()) {
case QAccessible::PopupMenuStart:
playSystemSound(QStringLiteral("MenuPopup"));
@@ -145,16 +113,17 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
break;
}
- QAccessibleInterface *accessible = event->accessibleInterface();
- if (!isActive() || !accessible || !accessible->isValid())
+ // 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()) {
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 a14eb8ca65..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 <QtGui/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
index 6ac8de23fa..8eb9baa8ef 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 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 <QtGui/qtguiglobal.h>
#if QT_CONFIG(accessibility)
@@ -52,6 +16,14 @@ 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)
@@ -72,7 +44,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaExpandCollapseProvider::Expand()
if (!actionInterface)
return UIA_E_ELEMENTNOTAVAILABLE;
- if (accessible->childCount() > 0 && accessible->child(0)->state().invisible)
+ if (!isExpanded(accessible))
actionInterface->doAction(QAccessibleActionInterface::showMenuAction());
return S_OK;
@@ -90,7 +62,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaExpandCollapseProvider::Collapse()
if (!actionInterface)
return UIA_E_ELEMENTNOTAVAILABLE;
- if (accessible->childCount() > 0 && !accessible->child(0)->state().invisible)
+ if (isExpanded(accessible))
actionInterface->doAction(QAccessibleActionInterface::showMenuAction());
return S_OK;
@@ -108,9 +80,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaExpandCollapseProvider::get_ExpandCollapseS
if (!accessible)
return UIA_E_ELEMENTNOTAVAILABLE;
- if (accessible->childCount() > 0)
- *pRetVal = accessible->child(0)->state().invisible ?
- ExpandCollapseState_Collapsed : ExpandCollapseState_Expanded;
+ *pRetVal = isExpanded(accessible) ? ExpandCollapseState_Expanded : ExpandCollapseState_Collapsed;
return S_OK;
}
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.h
index f5b4c2e78b..b384eb521c 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 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
#ifndef QWINDOWSUIAEXPANDCOLLAPSEPROVIDER_H
#define QWINDOWSUIAEXPANDCOLLAPSEPROVIDER_H
@@ -49,7 +13,7 @@ QT_BEGIN_NAMESPACE
// Implements the Expand/Collapse control pattern provider. Used for menu items with submenus.
class QWindowsUiaExpandCollapseProvider : public QWindowsUiaBaseProvider,
- public QWindowsComBase<IExpandCollapseProvider>
+ public QComObject<IExpandCollapseProvider>
{
Q_DISABLE_COPY_MOVE(QWindowsUiaExpandCollapseProvider)
public:
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 9808d5481c..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)
@@ -54,7 +18,6 @@
#include "qwindowsuiagriditemprovider.h"
#include "qwindowsuiawindowprovider.h"
#include "qwindowsuiaexpandcollapseprovider.h"
-#include "qwindowscombase.h"
#include "qwindowscontext.h"
#include "qwindowsuiautils.h"
#include "qwindowsuiaprovidercache.h"
@@ -63,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>
@@ -74,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;
@@ -94,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))
{
}
@@ -107,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);
}
}
@@ -126,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);
}
}
}
@@ -135,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);
}
}
}
@@ -164,29 +138,13 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
}
}
}
- if (event->value().type() == QVariant::String) {
+ if (event->value().typeId() == QMetaType::QString) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
-
- // Tries to notify the change using UiaRaiseNotificationEvent(), which is only available on
- // Windows 10 version 1709 or newer. Otherwise uses UiaRaiseAutomationPropertyChangedEvent().
-
- BSTR displayString = bStrFromQString(event->value().toString());
- BSTR activityId = bStrFromQString(QString());
-
- HRESULT hr = QWindowsUiaWrapper::instance()->raiseNotificationEvent(provider, NotificationKind_Other,
- NotificationProcessing_ImportantMostRecent,
- displayString, activityId);
-
- ::SysFreeString(displayString);
- ::SysFreeString(activityId);
-
- if (hr == static_cast<HRESULT>(UIA_E_NOTSUPPORTED)) {
- VARIANT oldVal, newVal;
- clearVariant(&oldVal);
- setVariantString(event->value().toString(), &newVal);
- QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
- ::SysFreeString(newVal.bstrVal);
- }
+ // Notifies changes in string values.
+ VARIANT oldVal, newVal;
+ clearVariant(&oldVal);
+ setVariantString(event->value().toString(), &newVal);
+ UiaRaiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
}
} else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
@@ -194,7 +152,7 @@ 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);
}
}
}
@@ -203,12 +161,16 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
void QWindowsUiaMainProvider::notifyNameChange(QAccessibleEvent *event)
{
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
- if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
- VARIANT oldVal, newVal;
- clearVariant(&oldVal);
- setVariantString(accessible->text(QAccessible::Name), &newVal);
- QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_NamePropertyId, oldVal, newVal);
- ::SysFreeString(newVal.bstrVal);
+ // 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);
+ }
}
}
}
@@ -217,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);
}
}
}
@@ -229,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);
}
}
}
@@ -244,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)
@@ -323,15 +280,20 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow
*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;
@@ -371,9 +333,11 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow
break;
case UIA_ExpandCollapsePatternId:
// Menu items with submenus.
- if (accessible->role() == QAccessible::MenuItem
+ if ((accessible->role() == QAccessible::MenuItem
&& accessible->childCount() > 0
- && accessible->child(0)->role() == QAccessible::PopupMenu) {
+ && accessible->child(0)->role() == QAccessible::PopupMenu)
+ || accessible->role() == QAccessible::ComboBox
+ || (accessible->role() == QAccessible::TreeItem && accessible->state().expandable)) {
*pRetVal = new QWindowsUiaExpandCollapseProvider(id());
}
break;
@@ -384,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;
@@ -414,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;
@@ -429,9 +424,9 @@ 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,
+ // The native OSK should be disabled if the Qt OSK is in use,
// or if disabled via application attribute.
- static bool imModuleEmpty = qEnvironmentVariableIsEmpty("QT_IM_MODULE");
+ static bool imModuleEmpty = QPlatformInputContextFactory::requested().isEmpty();
bool nativeVKDisabled = QCoreApplication::testAttribute(Qt::AA_DisableNativeVirtualKeyboard);
// If we want to disable the native OSK auto-showing
@@ -513,7 +508,7 @@ QString QWindowsUiaMainProvider::automationIdForAccessible(const QAccessibleInte
while (obj) {
QString name = obj->objectName();
if (name.isEmpty())
- return QString();
+ return result;
if (!result.isEmpty())
result.prepend(u'.');
result.prepend(name);
@@ -534,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;
@@ -724,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 f7320388f7..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,15 +20,13 @@ 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);
@@ -74,7 +37,6 @@ public:
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) override;
- ULONG STDMETHODCALLTYPE AddRef() override;
ULONG STDMETHODCALLTYPE Release() override;
// IRawElementProviderSimple methods
@@ -97,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 3305e9c5c4..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)
@@ -77,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.
+ // First get/create list of selected items, then build a safe array with the right size.
QList<QAccessibleInterface *> selectedList;
- for (int i = 0; i < accessible->childCount(); ++i) {
- if (QAccessibleInterface *child = accessible->child(i)) {
- if (child->state().selected) {
- selectedList.append(child);
+ 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);
+ }
+ }
}
}
}
@@ -126,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 682b8c19c0..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.
@@ -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 0daef2ea63..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 <QtGui/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 9b41162d45..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)
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 fd3ed1c6df..0000000000
--- a/src/plugins/platforms/windows/uiautomation/uiautomation.pri
+++ /dev/null
@@ -1,43 +0,0 @@
-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/qwindowsuiaexpandcollapseprovider.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/qwindowsuiaexpandcollapseprovider.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 1cfcf314f3..0000000000
--- a/src/plugins/platforms/windows/windows.pri
+++ /dev/null
@@ -1,116 +0,0 @@
-# Note: OpenGL32 must precede Gdi32 as it overwrites some functions.
-LIBS += -lwinspool -limm32 -loleaut32
-
-QT_FOR_CONFIG += gui
-
-qtConfig(opengl):!qtConfig(dynamicgl): LIBS *= -lopengl32
-
-mingw: QMAKE_USE *= uuid
-
-LIBS += -lshlwapi -lwtsapi32
-
-QMAKE_USE_PRIVATE += \
- advapi32 \
- ole32 \
- shell32 \
- user32 \
- winmm
-
-DEFINES *= QT_NO_CAST_FROM_ASCII QT_NO_FOREACH
-
-SOURCES += \
- $$PWD/qwindowsapplication.cpp \
- $$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/qwindowsapplication.h \
- $$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
-
-# Only WGL is supported in Qt 6, ANGLE is removed
-qtConfig(opengl) {
- SOURCES += $$PWD/qwindowsglcontext.cpp
- HEADERS += $$PWD/qwindowsglcontext.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)
-
diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro
deleted file mode 100644
index ea211beaef..0000000000
--- a/src/plugins/platforms/windows/windows.pro
+++ /dev/null
@@ -1,28 +0,0 @@
-TARGET = qwindows
-
-QT += core-private gui-private
-
-qtConfig(opengl): QT += opengl-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)