summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/CMakeLists.txt3
-rw-r--r--src/plugins/generic/CMakeLists.txt3
-rw-r--r--src/plugins/generic/evdevkeyboard/CMakeLists.txt3
-rw-r--r--src/plugins/generic/evdevmouse/CMakeLists.txt3
-rw-r--r--src/plugins/generic/evdevtablet/CMakeLists.txt3
-rw-r--r--src/plugins/generic/evdevtouch/CMakeLists.txt3
-rw-r--r--src/plugins/generic/libinput/CMakeLists.txt3
-rw-r--r--src/plugins/generic/tslib/CMakeLists.txt3
-rw-r--r--src/plugins/generic/tuiotouch/CMakeLists.txt3
-rw-r--r--src/plugins/generic/tuiotouch/qoscbundle.cpp2
-rw-r--r--src/plugins/imageformats/CMakeLists.txt3
-rw-r--r--src/plugins/imageformats/gif/CMakeLists.txt3
-rw-r--r--src/plugins/imageformats/ico/CMakeLists.txt3
-rw-r--r--src/plugins/imageformats/jpeg/CMakeLists.txt3
-rw-r--r--src/plugins/networkinformation/CMakeLists.txt3
-rw-r--r--src/plugins/networkinformation/android/CMakeLists.txt3
-rw-r--r--src/plugins/networkinformation/android/jar/src/org/qtproject/qt/android/networkinformation/QtAndroidNetworkInformation.java8
-rw-r--r--src/plugins/networkinformation/android/wrapper/androidconnectivitymanager.cpp65
-rw-r--r--src/plugins/networkinformation/android/wrapper/androidconnectivitymanager.h5
-rw-r--r--src/plugins/networkinformation/glib/CMakeLists.txt3
-rw-r--r--src/plugins/networkinformation/networklistmanager/CMakeLists.txt3
-rw-r--r--src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp4
-rw-r--r--src/plugins/networkinformation/networkmanager/CMakeLists.txt3
-rw-r--r--src/plugins/networkinformation/scnetworkreachability/CMakeLists.txt3
-rw-r--r--src/plugins/platforminputcontexts/CMakeLists.txt3
-rw-r--r--src/plugins/platforminputcontexts/compose/CMakeLists.txt3
-rw-r--r--src/plugins/platforminputcontexts/ibus/CMakeLists.txt3
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibustypes.cpp2
-rw-r--r--src/plugins/platforms/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/android/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp8
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp7
-rw-r--r--src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp67
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp17
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp12
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.h4
-rw-r--r--src/plugins/platforms/cocoa/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm7
-rw-r--r--src/plugins/platforms/cocoa/qcocoaclipboard.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoansmenu.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.mm26
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm61
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm4
-rw-r--r--src/plugins/platforms/cocoa/qmultitouch_mac.mm2
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm2
-rw-r--r--src/plugins/platforms/cocoa/qnsview_complextext.mm11
-rw-r--r--src/plugins/platforms/cocoa/qnsview_keys.mm2
-rw-r--r--src/plugins/platforms/cocoa/qnsview_tablet.mm16
-rw-r--r--src/plugins/platforms/direct2d/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/directfb/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/eglfs/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfscursor.cpp10
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsscreen.cpp18
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsscreen_p.h2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp11
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration_p.h2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/ios/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/ios/optional/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/ios/optional/nsphotolibrarysupport/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm2
-rw-r--r--src/plugins/platforms/ios/qioscontext.mm4
-rw-r--r--src/plugins/platforms/ios/qiosdocumentpickercontroller.mm5
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm9
-rw-r--r--src/plugins/platforms/ios/qiosintegration.h2
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm6
-rw-r--r--src/plugins/platforms/ios/qiosplatformaccessibility.h2
-rw-r--r--src/plugins/platforms/ios/qiosplatformaccessibility.mm2
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm14
-rw-r--r--src/plugins/platforms/ios/qiostextinputoverlay.mm8
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm2
-rw-r--r--src/plugins/platforms/ios/qiostheme.mm41
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm4
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm8
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.h2
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.mm2
-rw-r--r--src/plugins/platforms/ios/quiview.mm103
-rw-r--r--src/plugins/platforms/linuxfb/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/minimal/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/minimalegl/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/offscreen/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/qnx/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp4
-rw-r--r--src/plugins/platforms/vkkhrdisplay/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.cpp15
-rw-r--r--src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.h1
-rw-r--r--src/plugins/platforms/vnc/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/wasm/CMakeLists.txt6
-rw-r--r--src/plugins/platforms/wasm/qtloader.js39
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.cpp250
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.h44
-rw-r--r--src/plugins/platforms/wasm/qwasmclipboard.cpp111
-rw-r--r--src/plugins/platforms/wasm/qwasmclipboard.h4
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.cpp713
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.h156
-rw-r--r--src/plugins/platforms/wasm/qwasmcursor.cpp7
-rw-r--r--src/plugins/platforms/wasm/qwasmcursor.h5
-rw-r--r--src/plugins/platforms/wasm/qwasmdrag.cpp3
-rw-r--r--src/plugins/platforms/wasm/qwasmevent.cpp53
-rw-r--r--src/plugins/platforms/wasm/qwasmevent.h168
-rw-r--r--src/plugins/platforms/wasm/qwasmeventdispatcher.cpp4
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.cpp309
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.h32
-rw-r--r--src/plugins/platforms/wasm/qwasminputcontext.cpp19
-rw-r--r--src/plugins/platforms/wasm/qwasminputcontext.h4
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.cpp35
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.h16
-rw-r--r--src/plugins/platforms/wasm/qwasmoffscreensurface.cpp4
-rw-r--r--src/plugins/platforms/wasm/qwasmplatform.cpp31
-rw-r--r--src/plugins/platforms/wasm/qwasmplatform.h29
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.cpp81
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.h5
-rw-r--r--src/plugins/platforms/wasm/qwasmstylepixmaps_p.h4
-rw-r--r--src/plugins/platforms/wasm/qwasmtheme.cpp2
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp26
-rw-r--r--src/plugins/platforms/wasm/wasm_shell.html3
-rw-r--r--src/plugins/platforms/windows/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h8
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp57
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h5
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp14
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp82
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp33
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp47
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h8
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp235
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp233
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h1
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp16
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp12
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp21
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp33
-rw-r--r--src/plugins/platforms/xcb/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp156
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h3
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp19
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h3
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp22
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp31
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp30
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp6
-rw-r--r--src/plugins/platformthemes/CMakeLists.txt3
-rw-r--r--src/plugins/platformthemes/gtk3/CMakeLists.txt12
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp9
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3menu.cpp1
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3theme.cpp17
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3theme.h1
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/CMakeLists.txt3
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp95
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h10
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp7
-rw-r--r--src/plugins/printsupport/CMakeLists.txt3
-rw-r--r--src/plugins/printsupport/cups/CMakeLists.txt3
-rw-r--r--src/plugins/printsupport/cups/qcupsprintersupport.cpp7
-rw-r--r--src/plugins/sqldrivers/.cmake.conf2
-rw-r--r--src/plugins/sqldrivers/CMakeLists.txt3
-rw-r--r--src/plugins/sqldrivers/configure.cmake3
-rw-r--r--src/plugins/sqldrivers/db2/CMakeLists.txt3
-rw-r--r--src/plugins/sqldrivers/ibase/CMakeLists.txt3
-rw-r--r--src/plugins/sqldrivers/mysql/CMakeLists.txt3
-rw-r--r--src/plugins/sqldrivers/mysql/qsql_mysql.cpp4
-rw-r--r--src/plugins/sqldrivers/oci/CMakeLists.txt3
-rw-r--r--src/plugins/sqldrivers/oci/qsql_oci.cpp2
-rw-r--r--src/plugins/sqldrivers/odbc/CMakeLists.txt3
-rw-r--r--src/plugins/sqldrivers/psql/CMakeLists.txt3
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql.cpp2
-rw-r--r--src/plugins/sqldrivers/qt_cmdline.cmake3
-rw-r--r--src/plugins/sqldrivers/sqlite/CMakeLists.txt8
-rw-r--r--src/plugins/styles/CMakeLists.txt3
-rw-r--r--src/plugins/styles/android/CMakeLists.txt3
-rw-r--r--src/plugins/styles/mac/CMakeLists.txt3
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm30
-rw-r--r--src/plugins/styles/windowsvista/CMakeLists.txt3
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle.cpp9
-rw-r--r--src/plugins/tls/CMakeLists.txt3
-rw-r--r--src/plugins/tls/certonly/CMakeLists.txt3
-rw-r--r--src/plugins/tls/openssl/CMakeLists.txt18
-rw-r--r--src/plugins/tls/openssl/qsslcontext_openssl.cpp6
-rw-r--r--src/plugins/tls/openssl/qsslcontext_openssl_p.h3
-rw-r--r--src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp2
-rw-r--r--src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h8
-rw-r--r--src/plugins/tls/schannel/CMakeLists.txt3
-rw-r--r--src/plugins/tls/schannel/qtls_schannel.cpp242
-rw-r--r--src/plugins/tls/securetransport/CMakeLists.txt3
-rw-r--r--src/plugins/tls/securetransport/qtls_st.cpp94
217 files changed, 2999 insertions, 1759 deletions
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt
index 4c3b3a39b4..cce7569eab 100644
--- a/src/plugins/CMakeLists.txt
+++ b/src/plugins/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from plugins.pro.
if(TARGET Qt::Sql)
diff --git a/src/plugins/generic/CMakeLists.txt b/src/plugins/generic/CMakeLists.txt
index f5890d0961..84bccb04a6 100644
--- a/src/plugins/generic/CMakeLists.txt
+++ b/src/plugins/generic/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from generic.pro.
if(QT_FEATURE_evdev)
diff --git a/src/plugins/generic/evdevkeyboard/CMakeLists.txt b/src/plugins/generic/evdevkeyboard/CMakeLists.txt
index 1568ac82cb..56118e020f 100644
--- a/src/plugins/generic/evdevkeyboard/CMakeLists.txt
+++ b/src/plugins/generic/evdevkeyboard/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from evdevkeyboard.pro.
#####################################################################
diff --git a/src/plugins/generic/evdevmouse/CMakeLists.txt b/src/plugins/generic/evdevmouse/CMakeLists.txt
index f467f631f5..0071ce2641 100644
--- a/src/plugins/generic/evdevmouse/CMakeLists.txt
+++ b/src/plugins/generic/evdevmouse/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from evdevmouse.pro.
#####################################################################
diff --git a/src/plugins/generic/evdevtablet/CMakeLists.txt b/src/plugins/generic/evdevtablet/CMakeLists.txt
index 4f39c1be87..867fb069f2 100644
--- a/src/plugins/generic/evdevtablet/CMakeLists.txt
+++ b/src/plugins/generic/evdevtablet/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from evdevtablet.pro.
#####################################################################
diff --git a/src/plugins/generic/evdevtouch/CMakeLists.txt b/src/plugins/generic/evdevtouch/CMakeLists.txt
index 4b90efbd69..6477de192e 100644
--- a/src/plugins/generic/evdevtouch/CMakeLists.txt
+++ b/src/plugins/generic/evdevtouch/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from evdevtouch.pro.
#####################################################################
diff --git a/src/plugins/generic/libinput/CMakeLists.txt b/src/plugins/generic/libinput/CMakeLists.txt
index bf423c601d..3bac413c38 100644
--- a/src/plugins/generic/libinput/CMakeLists.txt
+++ b/src/plugins/generic/libinput/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from libinput.pro.
#####################################################################
diff --git a/src/plugins/generic/tslib/CMakeLists.txt b/src/plugins/generic/tslib/CMakeLists.txt
index 42d6f59b13..fe3e8afff5 100644
--- a/src/plugins/generic/tslib/CMakeLists.txt
+++ b/src/plugins/generic/tslib/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from tslib.pro.
qt_find_package(Tslib) # special case
diff --git a/src/plugins/generic/tuiotouch/CMakeLists.txt b/src/plugins/generic/tuiotouch/CMakeLists.txt
index 8271216182..379c4fc7b5 100644
--- a/src/plugins/generic/tuiotouch/CMakeLists.txt
+++ b/src/plugins/generic/tuiotouch/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from tuiotouch.pro.
#####################################################################
diff --git a/src/plugins/generic/tuiotouch/qoscbundle.cpp b/src/plugins/generic/tuiotouch/qoscbundle.cpp
index 8b70b3c55b..195762d62c 100644
--- a/src/plugins/generic/tuiotouch/qoscbundle.cpp
+++ b/src/plugins/generic/tuiotouch/qoscbundle.cpp
@@ -65,7 +65,7 @@ QOscBundle::QOscBundle(const QByteArray &data)
if (oscTimeEpoch == 0 && oscTimePico == 1) {
// "The time tag value consisting of 63 zero bits followed by a
- // one in the least signifigant bit is a special case meaning
+ // one in the least significant bit is a special case meaning
// "immediately.""
isImmediate = true;
}
diff --git a/src/plugins/imageformats/CMakeLists.txt b/src/plugins/imageformats/CMakeLists.txt
index 00fefbdc0d..17f70c861d 100644
--- a/src/plugins/imageformats/CMakeLists.txt
+++ b/src/plugins/imageformats/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from imageformats.pro.
if(QT_FEATURE_ico)
diff --git a/src/plugins/imageformats/gif/CMakeLists.txt b/src/plugins/imageformats/gif/CMakeLists.txt
index 1241fa2f0f..05cb8b45ec 100644
--- a/src/plugins/imageformats/gif/CMakeLists.txt
+++ b/src/plugins/imageformats/gif/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from gif.pro.
#####################################################################
diff --git a/src/plugins/imageformats/ico/CMakeLists.txt b/src/plugins/imageformats/ico/CMakeLists.txt
index 8cdedb2cfe..c13aee0838 100644
--- a/src/plugins/imageformats/ico/CMakeLists.txt
+++ b/src/plugins/imageformats/ico/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from ico.pro.
#####################################################################
diff --git a/src/plugins/imageformats/jpeg/CMakeLists.txt b/src/plugins/imageformats/jpeg/CMakeLists.txt
index bb5a78fa40..94499f2f8d 100644
--- a/src/plugins/imageformats/jpeg/CMakeLists.txt
+++ b/src/plugins/imageformats/jpeg/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from jpeg.pro.
qt_find_package(WrapJpeg PROVIDED_TARGETS WrapJpeg::WrapJpeg)
diff --git a/src/plugins/networkinformation/CMakeLists.txt b/src/plugins/networkinformation/CMakeLists.txt
index 06bbe89121..43aeb3d22a 100644
--- a/src/plugins/networkinformation/CMakeLists.txt
+++ b/src/plugins/networkinformation/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
if(WIN32 AND QT_FEATURE_networklistmanager)
add_subdirectory(networklistmanager)
endif()
diff --git a/src/plugins/networkinformation/android/CMakeLists.txt b/src/plugins/networkinformation/android/CMakeLists.txt
index 0883ec74e2..7f1087aabd 100644
--- a/src/plugins/networkinformation/android/CMakeLists.txt
+++ b/src/plugins/networkinformation/android/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
set(java_sources
jar/src/org/qtproject/qt/android/networkinformation/QtAndroidNetworkInformation.java
diff --git a/src/plugins/networkinformation/android/jar/src/org/qtproject/qt/android/networkinformation/QtAndroidNetworkInformation.java b/src/plugins/networkinformation/android/jar/src/org/qtproject/qt/android/networkinformation/QtAndroidNetworkInformation.java
index 6a259e5ea6..6a56c506b0 100644
--- a/src/plugins/networkinformation/android/jar/src/org/qtproject/qt/android/networkinformation/QtAndroidNetworkInformation.java
+++ b/src/plugins/networkinformation/android/jar/src/org/qtproject/qt/android/networkinformation/QtAndroidNetworkInformation.java
@@ -15,9 +15,9 @@ import android.os.Build;
public class QtAndroidNetworkInformation {
private static final String LOG_TAG = "QtAndroidNetworkInformation";
- private static native void connectivityChanged(AndroidConnectivity connectivity);
+ private static native void networkConnectivityChanged(int connectivity);
private static native void genericInfoChanged(boolean captivePortal, boolean metered);
- private static native void transportMediumChanged(Transport transportMedium);
+ private static native void transportMediumChanged(int transportMedium);
private static QtNetworkInformationCallback m_callback = null;
private static final Object m_lock = new Object();
@@ -96,14 +96,14 @@ public class QtAndroidNetworkInformation {
private void setState(AndroidConnectivity s) {
if (previousState != s) {
previousState = s;
- connectivityChanged(s);
+ networkConnectivityChanged(s.ordinal());
}
}
private void setTransportMedium(Transport t) {
if (previousTransport != t) {
previousTransport = t;
- transportMediumChanged(t);
+ transportMediumChanged(t.ordinal());
}
}
diff --git a/src/plugins/networkinformation/android/wrapper/androidconnectivitymanager.cpp b/src/plugins/networkinformation/android/wrapper/androidconnectivitymanager.cpp
index b3035db2fa..203772971b 100644
--- a/src/plugins/networkinformation/android/wrapper/androidconnectivitymanager.cpp
+++ b/src/plugins/networkinformation/android/wrapper/androidconnectivitymanager.cpp
@@ -20,14 +20,15 @@ Q_GLOBAL_STATIC(AndroidConnectivityManagerInstance, androidConnManagerInstance)
static const char networkInformationClass[] =
"org/qtproject/qt/android/networkinformation/QtAndroidNetworkInformation";
-static void networkConnectivityChanged(JNIEnv *env, jobject obj, jobject enumValue)
+static void networkConnectivityChanged(JNIEnv *env, jobject obj, jint enumValue)
{
Q_UNUSED(env);
Q_UNUSED(obj);
- const jint value = QJniObject(enumValue).callMethod<jint>("ordinal");
- const auto connectivity = static_cast<AndroidConnectivityManager::AndroidConnectivity>(value);
+ const auto connectivity =
+ static_cast<AndroidConnectivityManager::AndroidConnectivity>(enumValue);
Q_EMIT androidConnManagerInstance->connManager->connectivityChanged(connectivity);
}
+Q_DECLARE_JNI_NATIVE_METHOD(networkConnectivityChanged)
static void genericInfoChanged(JNIEnv *env, jobject obj, jboolean captivePortal, jboolean metered)
{
@@ -36,30 +37,26 @@ static void genericInfoChanged(JNIEnv *env, jobject obj, jboolean captivePortal,
Q_EMIT androidConnManagerInstance->connManager->captivePortalChanged(captivePortal);
Q_EMIT androidConnManagerInstance->connManager->meteredChanged(metered);
}
+Q_DECLARE_JNI_NATIVE_METHOD(genericInfoChanged)
-static void transportMediumChangedCallback(JNIEnv *env, jobject obj, jobject enumValue)
+static void transportMediumChanged(JNIEnv *env, jobject obj, jint enumValue)
{
Q_UNUSED(env);
Q_UNUSED(obj);
- const jint value = QJniObject(enumValue).callMethod<jint>("ordinal");
- const auto transport = static_cast<AndroidConnectivityManager::AndroidTransport>(value);
+ const auto transport = static_cast<AndroidConnectivityManager::AndroidTransport>(enumValue);
emit androidConnManagerInstance->connManager->transportMediumChanged(transport);
}
+Q_DECLARE_JNI_NATIVE_METHOD(transportMediumChanged)
+
+Q_DECLARE_JNI_TYPE(ConnectivityManager, "Landroid/net/ConnectivityManager;")
AndroidConnectivityManager::AndroidConnectivityManager()
{
if (!registerNatives())
return;
- m_connectivityManager = QJniObject::callStaticObjectMethod(
- networkInformationClass, "getConnectivityManager",
- "(Landroid/content/Context;)Landroid/net/ConnectivityManager;",
- QAndroidApplication::context());
- if (!m_connectivityManager.isValid())
- return;
-
QJniObject::callStaticMethod<void>(networkInformationClass, "registerReceiver",
- "(Landroid/content/Context;)V", QAndroidApplication::context());
+ QAndroidApplication::context());
}
AndroidConnectivityManager *AndroidConnectivityManager::getInstance()
@@ -71,36 +68,28 @@ AndroidConnectivityManager *AndroidConnectivityManager::getInstance()
: nullptr;
}
+bool AndroidConnectivityManager::isValid() const
+{
+ return registerNatives();
+}
+
AndroidConnectivityManager::~AndroidConnectivityManager()
{
QJniObject::callStaticMethod<void>(networkInformationClass, "unregisterReceiver",
- "(Landroid/content/Context;)V", QAndroidApplication::context());
+ QAndroidApplication::context());
}
-bool AndroidConnectivityManager::registerNatives()
+bool AndroidConnectivityManager::registerNatives() const
{
- QJniEnvironment env;
- QJniObject networkReceiver(networkInformationClass);
- if (!networkReceiver.isValid())
- return false;
-
- const QByteArray connectivityEnumSig =
- QByteArray("(L") + networkInformationClass + "$AndroidConnectivity;)V";
- const QByteArray transportEnumSig =
- QByteArray("(L") + networkInformationClass + "$Transport;)V";
-
- jclass clazz = env->GetObjectClass(networkReceiver.object());
- static JNINativeMethod methods[] = {
- { "connectivityChanged", connectivityEnumSig.data(),
- reinterpret_cast<void *>(networkConnectivityChanged) },
- { "genericInfoChanged", "(ZZ)V",
- reinterpret_cast<void *>(genericInfoChanged) },
- { "transportMediumChanged", transportEnumSig.data(),
- reinterpret_cast<void *>(transportMediumChangedCallback) },
- };
- const bool ret = (env->RegisterNatives(clazz, methods, std::size(methods)) == JNI_OK);
- env->DeleteLocalRef(clazz);
- return ret;
+ static const bool registered = []() {
+ QJniEnvironment env;
+ return env.registerNativeMethods(networkInformationClass, {
+ Q_JNI_NATIVE_METHOD(networkConnectivityChanged),
+ Q_JNI_NATIVE_METHOD(genericInfoChanged),
+ Q_JNI_NATIVE_METHOD(transportMediumChanged),
+ });
+ }();
+ return registered;
}
QT_END_NAMESPACE
diff --git a/src/plugins/networkinformation/android/wrapper/androidconnectivitymanager.h b/src/plugins/networkinformation/android/wrapper/androidconnectivitymanager.h
index 9b51bbfc19..d15faf0e8e 100644
--- a/src/plugins/networkinformation/android/wrapper/androidconnectivitymanager.h
+++ b/src/plugins/networkinformation/android/wrapper/androidconnectivitymanager.h
@@ -33,7 +33,7 @@ public:
static AndroidConnectivityManager *getInstance();
~AndroidConnectivityManager();
- inline bool isValid() const { return m_connectivityManager.isValid(); }
+ inline bool isValid() const;
Q_SIGNALS:
void connectivityChanged(AndroidConnectivity connectivity);
@@ -44,8 +44,7 @@ Q_SIGNALS:
private:
friend struct AndroidConnectivityManagerInstance;
AndroidConnectivityManager();
- bool registerNatives();
- QJniObject m_connectivityManager;
+ bool registerNatives() const;
Q_DISABLE_COPY_MOVE(AndroidConnectivityManager);
};
diff --git a/src/plugins/networkinformation/glib/CMakeLists.txt b/src/plugins/networkinformation/glib/CMakeLists.txt
index 17a16a15c0..f2e5260b7f 100644
--- a/src/plugins/networkinformation/glib/CMakeLists.txt
+++ b/src/plugins/networkinformation/glib/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
qt_internal_add_plugin(QGlibNetworkInformationPlugin
OUTPUT_NAME qglib
CLASS_NAME QGlibNetworkInformationBackendFactory
diff --git a/src/plugins/networkinformation/networklistmanager/CMakeLists.txt b/src/plugins/networkinformation/networklistmanager/CMakeLists.txt
index d927d4af60..c4b65bb805 100644
--- a/src/plugins/networkinformation/networklistmanager/CMakeLists.txt
+++ b/src/plugins/networkinformation/networklistmanager/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
qt_internal_add_plugin(QNLMNIPlugin
OUTPUT_NAME qnetworklistmanager
CLASS_NAME QNetworkListManagerNetworkInformationBackendFactory
diff --git a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp
index eb42abc48e..9673d2cf69 100644
--- a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp
+++ b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp
@@ -121,7 +121,7 @@ public:
QNetworkListManagerNetworkInformationBackend::QNetworkListManagerNetworkInformationBackend()
{
- auto hr = CoInitialize(nullptr);
+ auto hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (FAILED(hr)) {
qCWarning(lcNetInfoNLM) << "Failed to initialize COM:" << errorStringFromHResult(hr);
comInitFailed = true;
@@ -178,7 +178,7 @@ bool QNetworkListManagerNetworkInformationBackend::start()
Q_ASSERT(!monitoring);
if (comInitFailed) {
- auto hr = CoInitialize(nullptr);
+ auto hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (FAILED(hr)) {
qCWarning(lcNetInfoNLM) << "Failed to initialize COM:" << errorStringFromHResult(hr);
comInitFailed = true;
diff --git a/src/plugins/networkinformation/networkmanager/CMakeLists.txt b/src/plugins/networkinformation/networkmanager/CMakeLists.txt
index 5fc69f2d55..e1407040e8 100644
--- a/src/plugins/networkinformation/networkmanager/CMakeLists.txt
+++ b/src/plugins/networkinformation/networkmanager/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
qt_internal_add_plugin(QNetworkManagerNetworkInformationPlugin
OUTPUT_NAME qnetworkmanager
CLASS_NAME QNetworkManagerNetworkInformationBackendFactory
diff --git a/src/plugins/networkinformation/scnetworkreachability/CMakeLists.txt b/src/plugins/networkinformation/scnetworkreachability/CMakeLists.txt
index c9ee7d9a42..1c16d53587 100644
--- a/src/plugins/networkinformation/scnetworkreachability/CMakeLists.txt
+++ b/src/plugins/networkinformation/scnetworkreachability/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
qt_internal_add_plugin(QSCNetworkReachabilityNetworkInformationPlugin
OUTPUT_NAME qscnetworkreachability
CLASS_NAME QSCNetworkReachabilityNetworkInformationBackendFactory
diff --git a/src/plugins/platforminputcontexts/CMakeLists.txt b/src/plugins/platforminputcontexts/CMakeLists.txt
index b5150df4f3..219ced16b9 100644
--- a/src/plugins/platforminputcontexts/CMakeLists.txt
+++ b/src/plugins/platforminputcontexts/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from platforminputcontexts.pro.
if(QT_FEATURE_xkbcommon)
diff --git a/src/plugins/platforminputcontexts/compose/CMakeLists.txt b/src/plugins/platforminputcontexts/compose/CMakeLists.txt
index e3fbf913b9..9d7e142577 100644
--- a/src/plugins/platforminputcontexts/compose/CMakeLists.txt
+++ b/src/plugins/platforminputcontexts/compose/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from compose.pro.
#####################################################################
diff --git a/src/plugins/platforminputcontexts/ibus/CMakeLists.txt b/src/plugins/platforminputcontexts/ibus/CMakeLists.txt
index 7ccc627eb1..4df2833470 100644
--- a/src/plugins/platforminputcontexts/ibus/CMakeLists.txt
+++ b/src/plugins/platforminputcontexts/ibus/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from ibus.pro.
#####################################################################
diff --git a/src/plugins/platforminputcontexts/ibus/qibustypes.cpp b/src/plugins/platforminputcontexts/ibus/qibustypes.cpp
index 49eb501c06..9d61d61eb3 100644
--- a/src/plugins/platforminputcontexts/ibus/qibustypes.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibustypes.cpp
@@ -178,7 +178,7 @@ QList<QInputMethodEvent::Attribute> QIBusAttributeList::imAttributes() const
QHash<QPair<int, int>, QTextCharFormat> rangeAttrs;
const int numAttributes = attributes.size();
- // Merge text fomats for identical ranges into a single QTextFormat.
+ // Merge text formats for identical ranges into a single QTextFormat.
for (int i = 0; i < numAttributes; ++i) {
const QIBusAttribute &attr = attributes.at(i);
const QTextCharFormat &format = attr.format();
diff --git a/src/plugins/platforms/CMakeLists.txt b/src/plugins/platforms/CMakeLists.txt
index ba64b6b0f5..654fb6d1f2 100644
--- a/src/plugins/platforms/CMakeLists.txt
+++ b/src/plugins/platforms/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from platforms.pro.
if(ANDROID)
diff --git a/src/plugins/platforms/android/CMakeLists.txt b/src/plugins/platforms/android/CMakeLists.txt
index 7db5556d7e..d12e36e206 100644
--- a/src/plugins/platforms/android/CMakeLists.txt
+++ b/src/plugins/platforms/android/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from android.pro.
#####################################################################
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index 0523211196..38b1ed0952 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -61,7 +61,13 @@ namespace QtAndroidAccessibility
template <typename Func, typename Ret>
void runInObjectContext(QObject *context, Func &&func, Ret *retVal)
{
- QMetaObject::invokeMethod(context, func, Qt::BlockingQueuedConnection, retVal);
+ if (!QtAndroid::blockEventLoopsWhenSuspended()
+ || QGuiApplication::applicationState() != Qt::ApplicationSuspended) {
+ QMetaObject::invokeMethod(context, func, Qt::BlockingQueuedConnection, retVal);
+ } else {
+ __android_log_print(ANDROID_LOG_WARN, m_qtTag,
+ "Could not run accessibility call in object context, event loop suspended.");
+ }
}
void initialize()
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 3b5e656630..fee7c438e5 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -27,6 +27,7 @@
#include <QtCore/qbasicatomic.h>
#include <QtCore/qjnienvironment.h>
#include <QtCore/qjniobject.h>
+#include <QtCore/qprocess.h>
#include <QtCore/qresource.h>
#include <QtCore/qthread.h>
#include <QtGui/private/qguiapplication_p.h>
@@ -445,11 +446,11 @@ static jboolean startQtAndroidPlugin(JNIEnv *env, jobject /*object*/, jstring pa
m_mainLibraryHnd = nullptr;
const char *nativeString = env->GetStringUTFChars(paramsString, 0);
- QByteArray string = nativeString;
+ const QStringList argsList = QProcess::splitCommand(QString::fromUtf8(nativeString));
env->ReleaseStringUTFChars(paramsString, nativeString);
- for (auto str : string.split('\t'))
- m_applicationParams.append(str.split(' '));
+ for (const QString &arg : argsList)
+ m_applicationParams.append(arg.toUtf8());
// Go home
QDir::setCurrent(QDir::homePath());
diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
index a25aa673d3..36fa2dd945 100644
--- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
+++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
@@ -54,6 +54,7 @@ struct AssetItem {
}
Type type = Type::File;
QString name;
+ qint64 size = -1;
};
using AssetItemList = QList<AssetItem>;
@@ -231,7 +232,7 @@ public:
{
Q_UNUSED(permissions);
- if (m_isFolder || (openMode & QIODevice::WriteOnly))
+ if (!m_assetInfo || m_assetInfo->type != AssetItem::Type::File || (openMode & QIODevice::WriteOnly))
return false;
close();
m_assetFile = AAssetManager_open(m_assetManager, m_fileName.toUtf8(), AASSET_MODE_BUFFER);
@@ -245,14 +246,13 @@ public:
m_assetFile = 0;
return true;
}
- m_isFolder = false;
return false;
}
qint64 size() const override
{
- if (m_assetFile)
- return AAsset_getLength(m_assetFile);
+ if (m_assetInfo)
+ return m_assetInfo->size;
return -1;
}
@@ -286,10 +286,12 @@ public:
{
FileFlags commonFlags(ReadOwnerPerm|ReadUserPerm|ReadGroupPerm|ReadOtherPerm|ExistsFlag);
FileFlags flags;
- if (m_assetFile)
- flags = FileType | commonFlags;
- else if (m_isFolder)
- flags = DirectoryType | commonFlags;
+ if (m_assetInfo) {
+ if (m_assetInfo->type == AssetItem::Type::File)
+ flags = FileType | commonFlags;
+ else if (m_assetInfo->type == AssetItem::Type::Folder)
+ flags = DirectoryType | commonFlags;
+ }
return type & flags;
}
@@ -324,21 +326,43 @@ public:
return;
close();
m_fileName = cleanedAssetPath(file);
- switch (FolderIterator::fileType(m_fileName)) {
- case AssetItem::Type::File:
- open(QIODevice::ReadOnly, std::nullopt);
- break;
- case AssetItem::Type::Folder:
- m_isFolder = true;
- break;
- case AssetItem::Type::Invalid:
- break;
+
+ {
+ QMutexLocker lock(&m_assetsInfoCacheMutex);
+ QSharedPointer<AssetItem> *assetInfoPtr = m_assetsInfoCache.object(m_fileName);
+ if (assetInfoPtr) {
+ m_assetInfo = *assetInfoPtr;
+ return;
+ }
}
+
+ QSharedPointer<AssetItem> *newAssetInfoPtr = new QSharedPointer<AssetItem>(new AssetItem);
+
+ m_assetInfo = *newAssetInfoPtr;
+ m_assetInfo->name = m_fileName;
+ m_assetInfo->type = AssetItem::Type::Invalid;
+
+ m_assetFile = AAssetManager_open(m_assetManager, m_fileName.toUtf8(), AASSET_MODE_BUFFER);
+
+ if (m_assetFile) {
+ m_assetInfo->type = AssetItem::Type::File;
+ m_assetInfo->size = AAsset_getLength(m_assetFile);
+ } else {
+ auto *assetDir = AAssetManager_openDir(m_assetManager, m_fileName.toUtf8());
+ if (assetDir) {
+ if (AAssetDir_getNextFileName(assetDir))
+ m_assetInfo->type = AssetItem::Type::Folder;
+ AAssetDir_close(assetDir);
+ }
+ }
+
+ QMutexLocker lock(&m_assetsInfoCacheMutex);
+ m_assetsInfoCache.insert(m_fileName, newAssetInfoPtr);
}
Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override
{
- if (m_isFolder)
+ if (m_assetInfo && m_assetInfo->type == AssetItem::Type::Folder)
return new AndroidAbstractFileEngineIterator(filters, filterNames, m_fileName);
return nullptr;
}
@@ -348,9 +372,14 @@ private:
AAssetManager *m_assetManager = nullptr;
// initialize with a name that can't be used as a file name
QString m_fileName = "."_L1;
- bool m_isFolder = false;
+ QSharedPointer<AssetItem> m_assetInfo;
+
+ static QCache<QString, QSharedPointer<AssetItem>> m_assetsInfoCache;
+ static QMutex m_assetsInfoCacheMutex;
};
+QCache<QString, QSharedPointer<AssetItem>> AndroidAbstractFileEngine::m_assetsInfoCache(std::max(200, qEnvironmentVariableIntValue("QT_ANDROID_MAX_FILEINFO_ASSETS_CACHE_SIZE")));
+QMutex AndroidAbstractFileEngine::m_assetsInfoCacheMutex;
AndroidAssetsFileEngineHandler::AndroidAssetsFileEngineHandler()
{
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index 0ae0d7f4de..679c142289 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -593,14 +593,25 @@ void QAndroidInputContext::updateSelectionHandles()
if (cpos == anchor || im->anchorRectangle().isNull()) {
auto curRect = cursorRectangle();
- QPoint cursorPoint = qPlatformWindow->mapToGlobal(QPoint(curRect.x() + (curRect.width() / 2), curRect.y() + curRect.height()));
- QPoint editMenuPoint(cursorPoint.x(), cursorPoint.y());
+ QPoint cursorPointGlobal = qPlatformWindow->mapToGlobal(
+ QPoint(curRect.x() + (curRect.width() / 2), curRect.y() + curRect.height()));
+ QPoint cursorPoint(curRect.center().x(), curRect.bottom());
+ int x = curRect.x();
+ int y = curRect.y();
+
+ // Use x and y for the editMenuPoint from the cursorPointGlobal when the cursor is in the Dialog
+ if (cursorPointGlobal != cursorPoint) {
+ x = cursorPointGlobal.x();
+ y = cursorPointGlobal.y();
+ }
+
+ QPoint editMenuPoint(x, y);
m_handleMode &= ShowEditPopup;
m_handleMode |= ShowCursor;
uint32_t buttons = readOnly ? 0 : EditContext::PasteButton;
if (!query.value(Qt::ImSurroundingText).toString().isEmpty())
buttons |= EditContext::SelectAllButton;
- QtAndroidInput::updateHandles(m_handleMode, editMenuPoint, buttons, cursorPoint);
+ QtAndroidInput::updateHandles(m_handleMode, editMenuPoint, buttons, cursorPointGlobal);
// The VK is hidden, reset the timer
if (m_hideCursorHandleTimer.isActive())
m_hideCursorHandleTimer.start();
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp
index d34f59d2b3..19a7326115 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp
@@ -131,10 +131,10 @@ void QAndroidPlatformNativeInterface::customEvent(QEvent *event)
QAndroidPlatformIntegration *api = static_cast<QAndroidPlatformIntegration *>(QGuiApplicationPrivate::platformIntegration());
QtAndroid::setAndroidPlatformIntegration(api);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
// Android accessibility activation event might have been already received
api->accessibility()->setActive(QtAndroidAccessibility::isActive());
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
if (!m_running) {
m_running = true;
@@ -145,7 +145,7 @@ void QAndroidPlatformNativeInterface::customEvent(QEvent *event)
QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &paramList)
: m_touchDevice(nullptr)
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
, m_accessibility(nullptr)
#endif
{
@@ -179,9 +179,9 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &para
m_androidSystemLocale = new QAndroidSystemLocale;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
m_accessibility = new QAndroidPlatformAccessibility();
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
QJniObject javaActivity(QtAndroid::activity());
if (!javaActivity.isValid())
@@ -463,7 +463,7 @@ void QAndroidPlatformIntegration::flushPendingUpdates()
}
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QPlatformAccessibility *QAndroidPlatformIntegration::accessibility() const
{
return m_accessibility;
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h
index 14e529b93e..6e87c9c02b 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.h
+++ b/src/plugins/platforms/android/qandroidplatformintegration.h
@@ -82,7 +82,7 @@ public:
QPlatformNativeInterface *nativeInterface() const override;
QPlatformServices *services() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
virtual QPlatformAccessibility *accessibility() const override;
#endif
@@ -132,7 +132,7 @@ private:
#endif
QAndroidSystemLocale *m_androidSystemLocale;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
mutable QPlatformAccessibility *m_accessibility;
#endif
diff --git a/src/plugins/platforms/cocoa/CMakeLists.txt b/src/plugins/platforms/cocoa/CMakeLists.txt
index 21f87dae83..32baf20c97 100644
--- a/src/plugins/platforms/cocoa/CMakeLists.txt
+++ b/src/plugins/platforms/cocoa/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from cocoa.pro.
# special case:
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.h b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
index 2042dc5fbf..cdd9aafc80 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.h
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
@@ -4,7 +4,9 @@
#ifndef QCOCOAACCESIBILITY_H
#define QCOCOAACCESIBILITY_H
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+
+#if QT_CONFIG(accessibility)
#include <qpa/qplatformaccessibility.h>
@@ -58,6 +60,6 @@ id getValueAttribute(QAccessibleInterface *interface);
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QCOCOAACCESIBILITY_H
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index e366ba4f26..ccd5f7b665 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -13,7 +13,7 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QCocoaAccessibility::QCocoaAccessibility()
{
@@ -366,7 +366,7 @@ id getValueAttribute(QAccessibleInterface *interface)
} // namespace QCocoaAccessible
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
index 54ddfc3a5a..806359888f 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
@@ -4,9 +4,9 @@
#ifndef QCOCOAACCESIBILITYELEMENT_H
#define QCOCOAACCESIBILITYELEMENT_H
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
-#include <QtCore/qglobal.h>
+#if QT_CONFIG(accessibility)
#include <QtCore/private/qcore_mac_p.h>
#include <QtGui/qaccessible.h>
@@ -16,6 +16,6 @@ QT_DECLARE_NAMESPACED_OBJC_INTERFACE(QMacAccessibilityElement, NSObject <NSAcces
+ (instancetype)elementWithId:(QAccessible::Id)anId;
)
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QCOCOAACCESIBILITYELEMENT_H
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index 67e744ea31..f3c3d0bfaa 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -15,7 +15,7 @@
QT_USE_NAMESPACE
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
/**
* Converts between absolute character offsets and line numbers of a
@@ -616,4 +616,4 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
@end
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index ebbf9d1609..6db88f923c 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -40,6 +40,7 @@ public:
void flush(QWindow *, const QRegion &, const QPoint &) override;
FlushResult rhiFlush(QWindow *window,
+ qreal sourceDevicePixelRatio,
const QRegion &region,
const QPoint &offset,
QPlatformTextureList *textures,
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 21e4d88e73..a3a25062c5 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -395,6 +395,7 @@ void QCALayerBackingStore::windowDestroyed(QObject *object)
}
QPlatformBackingStore::FlushResult QCALayerBackingStore::rhiFlush(QWindow *window,
+ qreal sourceDevicePixelRatio,
const QRegion &region,
const QPoint &offset,
QPlatformTextureList *textures,
@@ -407,7 +408,7 @@ QPlatformBackingStore::FlushResult QCALayerBackingStore::rhiFlush(QWindow *windo
finalizeBackBuffer();
- return QPlatformBackingStore::rhiFlush(window, region, offset, textures, translucentBackground);
+ return QPlatformBackingStore::rhiFlush(window, sourceDevicePixelRatio, region, offset, textures, translucentBackground);
}
QImage QCALayerBackingStore::toImage() const
@@ -558,6 +559,6 @@ QImage *QCALayerBackingStore::GraphicsBuffer::asImage()
return &m_image;
}
-#include "moc_qcocoabackingstore.cpp"
-
QT_END_NAMESPACE
+
+#include "moc_qcocoabackingstore.cpp"
diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.mm b/src/plugins/platforms/cocoa/qcocoaclipboard.mm
index 8b91e9d5d1..7363b011bf 100644
--- a/src/plugins/platforms/cocoa/qcocoaclipboard.mm
+++ b/src/plugins/platforms/cocoa/qcocoaclipboard.mm
@@ -68,8 +68,8 @@ void QCocoaClipboard::handleApplicationStateChanged(Qt::ApplicationState state)
emitChanged(QClipboard::FindBuffer);
}
-#include "moc_qcocoaclipboard.cpp"
-
QT_END_NAMESPACE
+#include "moc_qcocoaclipboard.cpp"
+
#endif // QT_NO_CLIPBOARD
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm
index 3c1b67830f..aaa35a91ef 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.mm
+++ b/src/plugins/platforms/cocoa/qcocoacursor.mm
@@ -240,7 +240,7 @@ NSCursor *QCocoaCursor::createCursorData(QCursor *cursor)
switch (cursor->shape()) {
case Qt::BitmapCursor: {
if (cursor->pixmap().isNull())
- return createCursorFromBitmap(cursor->bitmap(Qt::ReturnByValue), cursor->mask(Qt::ReturnByValue), hotspot);
+ return createCursorFromBitmap(cursor->bitmap(), cursor->mask(), hotspot);
else
return createCursorFromPixmap(cursor->pixmap(), hotspot);
break; }
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 906d77236a..c6d73e3c06 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -69,7 +69,7 @@ public:
QCoreTextFontDatabase *fontDatabase() const override;
QCocoaNativeInterface *nativeInterface() const override;
QPlatformInputContext *inputContext() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QCocoaAccessibility *accessibility() const override;
#endif
#ifndef QT_NO_CLIPBOARD
@@ -104,7 +104,7 @@ private:
QScopedPointer<QCoreTextFontDatabase> mFontDb;
QScopedPointer<QPlatformInputContext> mInputContext;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QScopedPointer<QCocoaAccessibility> mAccessibility;
#endif
QScopedPointer<QPlatformTheme> mPlatformTheme;
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index be68f182c5..9911263c51 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -94,7 +94,7 @@ QCocoaIntegration *QCocoaIntegration::mInstance = nullptr;
QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
: mOptions(parseOptions(paramList))
, mFontDb(nullptr)
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
, mAccessibility(new QCocoaAccessibility)
#endif
#ifndef QT_NO_CLIPBOARD
@@ -344,7 +344,7 @@ QPlatformInputContext *QCocoaIntegration::inputContext() const
return mInputContext.data();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QCocoaAccessibility *QCocoaIntegration::accessibility() const
{
return mAccessibility.data();
diff --git a/src/plugins/platforms/cocoa/qcocoansmenu.mm b/src/plugins/platforms/cocoa/qcocoansmenu.mm
index 84a625ed66..4bc9b0b5f9 100644
--- a/src/plugins/platforms/cocoa/qcocoansmenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoansmenu.mm
@@ -13,6 +13,7 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qcoreevent.h>
+#include <QtCore/qvarlengtharray.h>
#include <QtGui/private/qapplekeymapper_p.h>
static NSString *qt_mac_removePrivateUnicode(NSString *string)
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm
index 1d2b93cd48..a8778ebe1d 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.mm
+++ b/src/plugins/platforms/cocoa/qcocoascreen.mm
@@ -72,6 +72,18 @@ void QCocoaScreen::initializeScreens()
*/
void QCocoaScreen::updateScreens()
{
+ // Adding, updating, or removing a screen below might trigger
+ // Qt or the application to move a window to a different screen,
+ // recursing back here via QCocoaWindow::windowDidChangeScreen.
+ // The update code is not re-entrant, so bail out if we end up
+ // in this situation. The screens will stabilize eventually.
+ static bool updatingScreens = false;
+ if (updatingScreens) {
+ qCInfo(lcQpaScreen) << "Skipping screen update, already updating";
+ return;
+ }
+ QBoolBlocker recursionGuard(updatingScreens);
+
uint32_t displayCount = 0;
if (CGGetOnlineDisplayList(0, nullptr, &displayCount) != kCGErrorSuccess)
qFatal("Failed to get number of online displays");
@@ -257,7 +269,10 @@ void QCocoaScreen::update(CGDirectDisplayID displayId)
float refresh = CGDisplayModeGetRefreshRate(displayMode);
m_refreshRate = refresh > 0 ? refresh : 60.0;
- m_name = displayName(m_displayId);
+ if (@available(macOS 10.15, *))
+ m_name = QString::fromNSString(nsScreen.localizedName);
+ else
+ m_name = displayName(m_displayId);
const bool didChangeGeometry = m_geometry != previousGeometry || m_availableGeometry != previousAvailableGeometry;
@@ -275,6 +290,11 @@ void QCocoaScreen::requestUpdate()
{
Q_ASSERT(m_displayId);
+ if (!isOnline()) {
+ qCDebug(lcQpaScreenUpdates) << this << "is not online. Ignoring update request";
+ return;
+ }
+
if (!m_displayLink) {
CVDisplayLinkCreateWithCGDisplay(m_displayId, &m_displayLink);
CVDisplayLinkSetOutputCallback(m_displayLink, [](CVDisplayLinkRef, const CVTimeStamp*,
@@ -771,10 +791,10 @@ QDebug operator<<(QDebug debug, const QCocoaScreen *screen)
}
#endif // !QT_NO_DEBUG_STREAM
-#include "qcocoascreen.moc"
-
QT_END_NAMESPACE
+#include "qcocoascreen.moc"
+
@implementation NSScreen (QtExtras)
- (CGDirectDisplayID)qt_displayId
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index fecb2b8c58..1ea3505061 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -33,18 +33,6 @@
#include <CoreServices/CoreServices.h>
-#if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
-@interface NSColor (MojaveForwardDeclarations)
-@property (class, strong, readonly) NSColor *selectedContentBackgroundColor NS_AVAILABLE_MAC(10_14);
-@property (class, strong, readonly) NSColor *unemphasizedSelectedTextBackgroundColor NS_AVAILABLE_MAC(10_14);
-@property (class, strong, readonly) NSColor *unemphasizedSelectedTextColor NS_AVAILABLE_MAC(10_14);
-@property (class, strong, readonly) NSColor *unemphasizedSelectedContentBackgroundColor NS_AVAILABLE_MAC(10_14);
-@property (class, strong, readonly) NSArray<NSColor *> *alternatingContentBackgroundColors NS_AVAILABLE_MAC(10_14);
-// Missing from non-Mojave SDKs, even if introduced in 10.10
-@property (class, strong, readonly) NSColor *linkColor NS_AVAILABLE_MAC(10_10);
-@end
-#endif
-
QT_BEGIN_NAMESPACE
static QPalette *qt_mac_createSystemPalette()
@@ -74,14 +62,9 @@ static QPalette *qt_mac_createSystemPalette()
// System palette initialization:
QBrush br = qt_mac_toQBrush([NSColor selectedControlColor]);
palette->setBrush(QPalette::Active, QPalette::Highlight, br);
- if (__builtin_available(macOS 10.14, *)) {
- const auto inactiveHighlight = qt_mac_toQBrush([NSColor unemphasizedSelectedContentBackgroundColor]);
- palette->setBrush(QPalette::Inactive, QPalette::Highlight, inactiveHighlight);
- palette->setBrush(QPalette::Disabled, QPalette::Highlight, inactiveHighlight);
- } else {
- palette->setBrush(QPalette::Inactive, QPalette::Highlight, br);
- palette->setBrush(QPalette::Disabled, QPalette::Highlight, br);
- }
+ const auto inactiveHighlight = qt_mac_toQBrush([NSColor unemphasizedSelectedContentBackgroundColor]);
+ palette->setBrush(QPalette::Inactive, QPalette::Highlight, inactiveHighlight);
+ palette->setBrush(QPalette::Disabled, QPalette::Highlight, inactiveHighlight);
palette->setBrush(QPalette::Shadow, qt_mac_toQColor([NSColor shadowColor]));
@@ -166,17 +149,8 @@ static QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes()
}
if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette
|| mac_widget_colors[i].paletteRole == QPlatformTheme::MenuBarPalette) {
- NSColor *selectedMenuItemColor = nil;
- if (__builtin_available(macOS 10.14, *)) {
- // Cheap approximation for NSVisualEffectView (see deprecation note for selectedMenuItemTextColor)
- selectedMenuItemColor = [[NSColor controlAccentColor] highlightWithLevel:0.3];
- } else {
- // selectedMenuItemColor would presumably be the correct color to use as the background
- // for selected menu items. But that color is always blue, and doesn't follow the
- // appearance color in system preferences. So we therefore deliberately choose to use
- // keyboardFocusIndicatorColor instead, which appears to have the same color value.
- selectedMenuItemColor = [NSColor keyboardFocusIndicatorColor];
- }
+ // Cheap approximation for NSVisualEffectView (see deprecation note for selectedMenuItemTextColor)
+ auto selectedMenuItemColor = [[NSColor controlAccentColor] highlightWithLevel:0.3];
pal.setBrush(QPalette::Highlight, qt_mac_toQColor(selectedMenuItemColor));
qc = qt_mac_toQColor([NSColor labelColor]);
pal.setBrush(QPalette::ButtonText, qc);
@@ -197,17 +171,10 @@ static QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes()
} else if (mac_widget_colors[i].paletteRole == QPlatformTheme::ItemViewPalette) {
NSArray<NSColor *> *baseColors = nil;
NSColor *activeHighlightColor = nil;
- if (__builtin_available(macOS 10.14, *)) {
- baseColors = [NSColor alternatingContentBackgroundColors];
- activeHighlightColor = [NSColor selectedContentBackgroundColor];
- pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
- qt_mac_toQBrush([NSColor unemphasizedSelectedTextColor]));
- } else {
- baseColors = [NSColor controlAlternatingRowBackgroundColors];
- activeHighlightColor = [NSColor alternateSelectedControlColor];
- pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
- pal.brush(QPalette::Active, QPalette::Text));
- }
+ baseColors = [NSColor alternatingContentBackgroundColors];
+ activeHighlightColor = [NSColor selectedContentBackgroundColor];
+ pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
+ qt_mac_toQBrush([NSColor unemphasizedSelectedTextColor]));
pal.setBrush(QPalette::Base, qt_mac_toQBrush(baseColors[0]));
pal.setBrush(QPalette::AlternateBase, qt_mac_toQBrush(baseColors[1]));
pal.setBrush(QPalette::Active, QPalette::Highlight,
@@ -241,16 +208,12 @@ const char *QCocoaTheme::name = "cocoa";
QCocoaTheme::QCocoaTheme()
: m_systemPalette(nullptr)
{
-#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) {
m_appearanceObserver = QMacKeyValueObserver(NSApp, @"effectiveAppearance", [this] {
- if (__builtin_available(macOS 10.14, *))
- NSAppearance.currentAppearance = NSApp.effectiveAppearance;
-
+ NSAppearance.currentAppearance = NSApp.effectiveAppearance;
handleSystemThemeChange();
});
}
-#endif
m_systemColorObserver = QMacNotificationObserver(nil,
NSSystemColorsDidChangeNotification, [this] {
@@ -412,11 +375,11 @@ QPixmap QCocoaTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
if (iconType != 0) {
QPixmap pixmap;
IconRef icon = nullptr;
- GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon);
+ QT_IGNORE_DEPRECATIONS(GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon));
if (icon) {
pixmap = qt_mac_convert_iconref(icon, size.width(), size.height());
- ReleaseIconRef(icon);
+ QT_IGNORE_DEPRECATIONS(ReleaseIconRef(icon));
}
return pixmap;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index f20aad6bb9..ef94b49736 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -1953,6 +1953,6 @@ QDebug operator<<(QDebug debug, const QCocoaWindow *window)
}
#endif // !QT_NO_DEBUG_STREAM
-#include "moc_qcocoawindow.cpp"
-
QT_END_NAMESPACE
+
+#include "moc_qcocoawindow.cpp"
diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac.mm b/src/plugins/platforms/cocoa/qmultitouch_mac.mm
index 40683bbaf8..73d103c5e3 100644
--- a/src/plugins/platforms/cocoa/qmultitouch_mac.mm
+++ b/src/plugins/platforms/cocoa/qmultitouch_mac.mm
@@ -145,7 +145,7 @@ QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch)
// Next: sadly, we need to check that our touch hash is in
// sync with cocoa. This is typically not the case after a system
- // gesture happend (like a four-finger-swipe to show expose).
+ // gesture happened (like a four-finger-swipe to show expose).
if (_touchCount != _currentTouches.size()) {
// Remove all instances, and basically start from scratch:
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 3d07760b2d..dd0f1d6511 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -363,7 +363,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSViewMouseMoveHelper);
#include "qnsview_keys.mm"
#include "qnsview_complextext.mm"
#include "qnsview_menus.mm"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qnsview_accessibility.mm"
#endif
diff --git a/src/plugins/platforms/cocoa/qnsview_complextext.mm b/src/plugins/platforms/cocoa/qnsview_complextext.mm
index 4be8126299..ad5f5a0827 100644
--- a/src/plugins/platforms/cocoa/qnsview_complextext.mm
+++ b/src/plugins/platforms/cocoa/qnsview_complextext.mm
@@ -112,9 +112,14 @@
KeyEvent newlineEvent(m_currentlyInterpretedKeyEvent ?
m_currentlyInterpretedKeyEvent : NSApp.currentEvent);
newlineEvent.type = QEvent::KeyPress;
- newlineEvent.key = Qt::Key_Return;
- newlineEvent.text = QLatin1Char(kReturnCharCode);
- newlineEvent.nativeVirtualKey = kVK_Return;
+
+ const bool isEnter = newlineEvent.modifiers & Qt::KeypadModifier;
+ newlineEvent.key = isEnter ? Qt::Key_Enter : Qt::Key_Return;
+ newlineEvent.text = isEnter ? QLatin1Char(kEnterCharCode)
+ : QLatin1Char(kReturnCharCode);
+ newlineEvent.nativeVirtualKey = isEnter ? kVK_ANSI_KeypadEnter
+ : kVK_Return;
+
qCDebug(lcQpaKeys) << "Inserting newline via" << newlineEvent;
newlineEvent.sendWindowSystemEvent(m_platformWindow->window());
}
diff --git a/src/plugins/platforms/cocoa/qnsview_keys.mm b/src/plugins/platforms/cocoa/qnsview_keys.mm
index 88e94f2c1c..dc669d6f3b 100644
--- a/src/plugins/platforms/cocoa/qnsview_keys.mm
+++ b/src/plugins/platforms/cocoa/qnsview_keys.mm
@@ -32,7 +32,7 @@
}
}
- QObject *focusObject = m_platformWindow->window()->focusObject();
+ QObject *focusObject = m_platformWindow ? m_platformWindow->window()->focusObject() : nullptr;
if (m_sendKeyEvent && focusObject) {
if (auto queryResult = queryInputMethod(focusObject, Qt::ImHints)) {
auto hints = static_cast<Qt::InputMethodHints>(queryResult.value(Qt::ImHints).toUInt());
diff --git a/src/plugins/platforms/cocoa/qnsview_tablet.mm b/src/plugins/platforms/cocoa/qnsview_tablet.mm
index 72e1b2d78f..4c6e351b3f 100644
--- a/src/plugins/platforms/cocoa/qnsview_tablet.mm
+++ b/src/plugins/platforms/cocoa/qnsview_tablet.mm
@@ -34,14 +34,18 @@ Q_GLOBAL_STATIC(QCocoaTabletDeviceMap, devicesInProximity)
// We use devicesInProximity because deviceID is typically 0,
// so QInputDevicePrivate::fromId() won't work.
- const auto *device = devicesInProximity->value(theEvent.deviceID);
- if (!device) {
- // Error: Unknown tablet device. Qt also gets into this state
- // when running on a VM. This appears to be harmless; don't
- // print a warning.
- return false;
+ const auto deviceId = theEvent.deviceID;
+ const auto *device = devicesInProximity->value(deviceId);
+ if (!device && deviceId == 0) {
+ // Application started up with stylus in proximity already, so we missed the proximity event?
+ // Create a generic tablet device for now.
+ device = tabletToolInstance(theEvent);
+ devicesInProximity->insert(deviceId, device);
}
+ if (Q_UNLIKELY(!device))
+ return false;
+
bool down = (eventType != NSEventTypeMouseMoved);
qreal pressure;
diff --git a/src/plugins/platforms/direct2d/CMakeLists.txt b/src/plugins/platforms/direct2d/CMakeLists.txt
index b88ac617aa..41fe0bde5b 100644
--- a/src/plugins/platforms/direct2d/CMakeLists.txt
+++ b/src/plugins/platforms/direct2d/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from direct2d.pro.
#####################################################################
diff --git a/src/plugins/platforms/directfb/CMakeLists.txt b/src/plugins/platforms/directfb/CMakeLists.txt
index c634afb4f8..5d123696bf 100644
--- a/src/plugins/platforms/directfb/CMakeLists.txt
+++ b/src/plugins/platforms/directfb/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from directfb.pro.
# begin special case:
diff --git a/src/plugins/platforms/eglfs/CMakeLists.txt b/src/plugins/platforms/eglfs/CMakeLists.txt
index c8b398e7a2..8df6c98c60 100644
--- a/src/plugins/platforms/eglfs/CMakeLists.txt
+++ b/src/plugins/platforms/eglfs/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from eglfs.pro.
# special case begin
qt_find_package(EGL)
diff --git a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp
index 05a86cee64..dadde5905e 100644
--- a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp
@@ -309,8 +309,7 @@ void QEglFSCursor::paintOnScreen()
// screens are siblings of each other. When not enabled, the sibling list
// only contains m_screen itself.
for (QPlatformScreen *screen : m_screen->virtualSiblings()) {
- if (screen->geometry().contains(cr.topLeft().toPoint() + m_cursor.hotSpot)
- && QOpenGLContext::currentContext()->screen() == screen->screen())
+ if (screen->geometry().contains(cr.topLeft().toPoint() + m_cursor.hotSpot))
{
cr.translate(-screen->geometry().topLeft());
const QSize screenSize = screen->geometry().size();
@@ -433,11 +432,12 @@ void QEglFSCursor::draw(const QRectF &r)
{
StateSaver stateSaver;
- QEglFSCursorData &gfx = static_cast<QEglFSContext*>(QOpenGLContext::currentContext()->handle())->cursorData;
- if (!gfx.program) {
- // one time initialization
+ // one time initialization
+ if (!QOpenGLFunctions::d_ptr)
initializeOpenGLFunctions();
+ QEglFSCursorData &gfx = static_cast<QEglFSContext*>(QOpenGLContext::currentContext()->handle())->cursorData;
+ if (!gfx.program) {
createShaderPrograms();
if (!gfx.atlasTexture) {
diff --git a/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp
index b081406258..a6345f693d 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp
@@ -212,4 +212,22 @@ QPixmap QEglFSScreen::grabWindow(WId wid, int x, int y, int width, int height) c
return QPixmap();
}
+QWindow *QEglFSScreen::topLevelAt(const QPoint &point) const
+{
+#ifndef QT_NO_OPENGL
+ QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
+ const QList<QOpenGLCompositorWindow *> windows = compositor->windows();
+ const int windowCount = windows.size();
+
+ // Higher z-order is at the end of the list
+ for (int i = windowCount - 1; i >= 0; i--) {
+ QWindow *window = windows[i]->sourceWindow();
+ if (window->isVisible() && window->geometry().contains(point))
+ return window;
+ }
+#endif
+
+ return QPlatformScreen::topLevelAt(point);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/api/qeglfsscreen_p.h b/src/plugins/platforms/eglfs/api/qeglfsscreen_p.h
index 8f1eb91206..bbfc9a9259 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsscreen_p.h
+++ b/src/plugins/platforms/eglfs/api/qeglfsscreen_p.h
@@ -54,6 +54,8 @@ public:
void handleCursorMove(const QPoint &pos);
+ QWindow *topLevelAt(const QPoint &point) const override;
+
private:
void setPrimarySurface(EGLSurface surface);
diff --git a/src/plugins/platforms/eglfs/deviceintegration/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/CMakeLists.txt
index 9e1c31527e..8c8389c316 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/CMakeLists.txt
+++ b/src/plugins/platforms/eglfs/deviceintegration/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from deviceintegration.pro.
if(QT_FEATURE_eglfs_x11)
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/CMakeLists.txt
index e1de63ea42..57d1533a3f 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/CMakeLists.txt
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from eglfs_emu.pro.
#####################################################################
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/CMakeLists.txt
index a20a4a084d..a04c9bdb0f 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/CMakeLists.txt
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from eglfs_kms.pro.
#####################################################################
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
index 9aa815ba90..c7b0208188 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
@@ -324,20 +324,21 @@ void QEglFSKmsGbmScreen::flip()
if (d.screen != this) {
d.screen->ensureModeSet(fb->fb);
d.cloneFlipPending = true;
+ QKmsOutput &destOutput(d.screen->output());
if (device()->hasAtomicSupport()) {
#if QT_CONFIG(drm_atomic)
drmModeAtomicReq *request = device()->threadLocalAtomicRequest();
if (request) {
- drmModeAtomicAddProperty(request, d.screen->output().eglfs_plane->id,
- d.screen->output().eglfs_plane->framebufferPropertyId, fb->fb);
- drmModeAtomicAddProperty(request, d.screen->output().eglfs_plane->id,
- d.screen->output().eglfs_plane->crtcPropertyId, op.crtc_id);
+ drmModeAtomicAddProperty(request, destOutput.eglfs_plane->id,
+ destOutput.eglfs_plane->framebufferPropertyId, fb->fb);
+ drmModeAtomicAddProperty(request, destOutput.eglfs_plane->id,
+ destOutput.eglfs_plane->crtcPropertyId, destOutput.crtc_id);
}
#endif
} else {
int ret = drmModePageFlip(fd,
- d.screen->output().crtc_id,
+ destOutput.crtc_id,
fb->fb,
DRM_MODE_PAGE_FLIP_EVENT,
d.screen);
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/CMakeLists.txt
index a9be917555..5567b14e77 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/CMakeLists.txt
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from eglfs_kms_egldevice.pro.
#####################################################################
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/CMakeLists.txt
index f9458ae5c6..d342d41121 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/CMakeLists.txt
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from eglfs_kms_support.pro.
#####################################################################
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp
index 77e66ed473..96cdcd8947 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp
@@ -144,7 +144,7 @@ void QEglFSKmsEventReader::create(QEglFSKmsDevice *device)
m_device = device;
- qCDebug(qLcEglfsKmsDebug, "Initalizing event reader for device %p fd %d",
+ qCDebug(qLcEglfsKmsDebug, "Initializing event reader for device %p fd %d",
m_device, m_device->fd());
m_thread = new QEglFSKmsEventReaderThread(m_device->fd());
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration_p.h
index 7000b9d35e..36e65a0bd4 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration_p.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration_p.h
@@ -27,7 +27,7 @@ QT_BEGIN_NAMESPACE
class QKmsDevice;
class QKmsScreenConfig;
-Q_EGLFS_EXPORT Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
+Q_DECLARE_EXPORTED_LOGGING_CATEGORY(qLcEglfsKmsDebug, Q_EGLFS_EXPORT)
class Q_EGLFS_EXPORT QEglFSKmsIntegration : public QEglFSDeviceIntegration
{
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/CMakeLists.txt
index 7550529f79..c919b655fa 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/CMakeLists.txt
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from eglfs_mali.pro.
#####################################################################
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/CMakeLists.txt
index fb8b79454d..385aaaef25 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/CMakeLists.txt
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from openwfd.pro.
#####################################################################
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/CMakeLists.txt
index 988ab76d79..836461f9a4 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/CMakeLists.txt
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from eglfs_viv.pro.
#####################################################################
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/CMakeLists.txt
index cb07c9aecc..f7e4f7a164 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/CMakeLists.txt
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from eglfs_viv_wl.pro.
#####################################################################
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/CMakeLists.txt
index 18bb02efe0..b4bdf770ff 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/CMakeLists.txt
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from eglfs_x11.pro.
#####################################################################
diff --git a/src/plugins/platforms/ios/CMakeLists.txt b/src/plugins/platforms/ios/CMakeLists.txt
index a55b30440a..d67239fee5 100644
--- a/src/plugins/platforms/ios/CMakeLists.txt
+++ b/src/plugins/platforms/ios/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from ios.pro.
#####################################################################
diff --git a/src/plugins/platforms/ios/optional/CMakeLists.txt b/src/plugins/platforms/ios/optional/CMakeLists.txt
index 6f5d754d4a..72f61c7473 100644
--- a/src/plugins/platforms/ios/optional/CMakeLists.txt
+++ b/src/plugins/platforms/ios/optional/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from optional.pro.
if(IOS)
diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/CMakeLists.txt b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/CMakeLists.txt
index 2fceac77ab..45f6e588d5 100644
--- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/CMakeLists.txt
+++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from nsphotolibrarysupport.pro.
#####################################################################
diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm
index 3f29c26cc4..0ca911f68b 100644
--- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm
+++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm
@@ -188,7 +188,7 @@ public:
// We can only load images from the asset library async. And this might take time, since it
// involves showing the authorization dialog. But the QFile API is synchronuous, so we need to
- // wait until we have access to the data. [ALAssetLibrary assetForUrl:] will shedule a block on
+ // wait until we have access to the data. [ALAssetLibrary assetForUrl:] will schedule a block on
// the current thread. But instead of spinning the event loop to force the block to execute, we
// wrap the call inside a synchronuous dispatch queue so that it executes on another thread.
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm
index 9defb01bfa..1649089841 100644
--- a/src/plugins/platforms/ios/qioscontext.mm
+++ b/src/plugins/platforms/ios/qioscontext.mm
@@ -332,6 +332,6 @@ bool QIOSContext::isSharing() const
return m_sharedContext;
}
-#include "moc_qioscontext.cpp"
-
QT_END_NAMESPACE
+
+#include "moc_qioscontext.cpp"
diff --git a/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm b/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm
index 544d9b9b88..09934dda0e 100644
--- a/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm
+++ b/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm
@@ -41,8 +41,7 @@
if (m_fileDialog->options()->fileMode() == QFileDialogOptions::ExistingFiles)
self.allowsMultipleSelection = YES;
- if (@available(ios 13.0, *))
- self.directoryURL = m_fileDialog->options()->initialDirectory().toNSURL();
+ self.directoryURL = m_fileDialog->options()->initialDirectory().toNSURL();
}
return self;
}
@@ -71,7 +70,7 @@
// "Called on the delegate when the user has taken action to dismiss the
// presentation successfully, after all animations are finished.
- // This is not called if the presentation is dismissed programatically."
+ // This is not called if the presentation is dismissed programmatically."
// So if document picker's view was dismissed, for example by swiping it away,
// we got this method called. But not if the dialog was cancelled or a file
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index e30ccc2c84..4c4b213ba2 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -712,11 +712,20 @@ void QIOSInputContext::reset()
// Instead, we choose to recreate the text responder as a brute-force solution
// until we have better knowledge of what is going on (or implement the new
// UITextInteraction protocol).
+ const auto oldResponder = m_textResponder;
[m_textResponder reset];
[m_textResponder autorelease];
m_textResponder = nullptr;
update(Qt::ImQueryAll);
+
+ // If update() didn't end up creating a new text responder, oldResponder will still be
+ // the first responder. In that case we need to resign it, so that the input panel hides.
+ // (the input panel will apparently not hide if the first responder is only released).
+ if ([oldResponder isFirstResponder]) {
+ qImDebug("IM not enabled, resigning autoreleased text responder as first responder");
+ [oldResponder resignFirstResponder];
+ }
}
/*!
diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h
index 8720534da8..6830a5b455 100644
--- a/src/plugins/platforms/ios/qiosintegration.h
+++ b/src/plugins/platforms/ios/qiosintegration.h
@@ -52,7 +52,7 @@ public:
QPlatformNativeInterface *nativeInterface() const override;
QPointingDevice *touchDevice();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QPlatformAccessibility *accessibility() const override;
#endif
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index df559a5f33..84caccc267 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -247,7 +247,7 @@ QPointingDevice *QIOSIntegration::touchDevice()
return m_touchDevice;
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QPlatformAccessibility *QIOSIntegration::accessibility() const
{
if (!m_accessibility)
@@ -287,6 +287,6 @@ void *QIOSIntegration::nativeResourceForWindow(const QByteArray &resource, QWind
// ---------------------------------------------------------
-#include "moc_qiosintegration.cpp"
-
QT_END_NAMESPACE
+
+#include "moc_qiosintegration.cpp"
diff --git a/src/plugins/platforms/ios/qiosplatformaccessibility.h b/src/plugins/platforms/ios/qiosplatformaccessibility.h
index 6ddc71c2cb..96efc663ba 100644
--- a/src/plugins/platforms/ios/qiosplatformaccessibility.h
+++ b/src/plugins/platforms/ios/qiosplatformaccessibility.h
@@ -6,7 +6,7 @@
#include <qpa/qplatformaccessibility.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosplatformaccessibility.mm b/src/plugins/platforms/ios/qiosplatformaccessibility.mm
index 30313b4536..d54b7db57a 100644
--- a/src/plugins/platforms/ios/qiosplatformaccessibility.mm
+++ b/src/plugins/platforms/ios/qiosplatformaccessibility.mm
@@ -3,7 +3,7 @@
#include "qiosplatformaccessibility.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <QtGui/QtGui>
#include "qioswindow.h"
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index 7ae28e1783..ce0dedc88d 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -177,12 +177,10 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
{
[super traitCollectionDidChange:previousTraitCollection];
- if (@available(iOS 12, *)) {
- if (self.screen == UIScreen.mainScreen) {
- if (previousTraitCollection.userInterfaceStyle != self.traitCollection.userInterfaceStyle) {
- QIOSTheme::initializeSystemPalette();
- QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>();
- }
+ if (self.screen == UIScreen.mainScreen) {
+ if (previousTraitCollection.userInterfaceStyle != self.traitCollection.userInterfaceStyle) {
+ QIOSTheme::initializeSystemPalette();
+ QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>();
}
}
}
@@ -530,6 +528,6 @@ UIWindow *QIOSScreen::uiWindow() const
return m_uiWindow;
}
-#include "moc_qiosscreen.cpp"
-
QT_END_NAMESPACE
+
+#include "moc_qiosscreen.cpp"
diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm
index f0e88d417a..512ab77bd2 100644
--- a/src/plugins/platforms/ios/qiostextinputoverlay.mm
+++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm
@@ -51,7 +51,7 @@ static void executeBlockWithoutAnimation(Block block)
// -------------------------------------------------------------------------
/**
QIOSEditMenu is just a wrapper class around UIMenuController to
- ease showing and hiding it correcly.
+ ease showing and hiding it correctly.
*/
@interface QIOSEditMenu : NSObject
@property (nonatomic, assign) BOOL visible;
@@ -792,7 +792,7 @@ static void executeBlockWithoutAnimation(Block block)
SelectionPair selection = querySelection();
int touchTextPos = QPlatformInputContext::queryFocusObject(Qt::ImCursorPosition, touchPoint).toInt();
- // Ensure that the handels cannot be dragged past each other
+ // Ensure that the handles cannot be dragged past each other
if (_dragOnCursor)
selection.second = (touchTextPos > selection.first) ? touchTextPos : selection.first + 1;
else
@@ -920,7 +920,7 @@ static void executeBlockWithoutAnimation(Block block)
// But note, we only want to hide the menu, and not clear the selection.
// Only when the user taps inside the input area do we want to clear the
// selection as well. This is different from native behavior, but done so
- // deliberatly for cross-platform consistency. This will let the user click on
+ // deliberately for cross-platform consistency. This will let the user click on
// e.g "Bold" and "Italic" buttons elsewhere in the UI to modify the selected text.
return;
}
@@ -933,7 +933,7 @@ static void executeBlockWithoutAnimation(Block block)
}
// When no menu is showing, and the touch is inside the input
- // area, we check if we should show it. We wan't to do so if
+ // area, we check if we should show it. We want to do so if
// the tap doesn't result in the cursor changing position.
_cursorPosOnPress = QInputMethod::queryFocusObject(Qt::ImCursorPosition, QVariant()).toInt();
}
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index 8e2043af86..8069ddb601 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -111,7 +111,7 @@
// By keeping the responder (QIOSTextInputResponder in this case)
// retained, we ensure that all messages sent to the view during
-// its lifetime in a window hierarcy will be able to traverse the
+// its lifetime in a window hierarchy will be able to traverse the
// responder chain.
- (void)willMoveToWindow:(UIWindow *)window
{
diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm
index e9525a0275..390ca2e351 100644
--- a/src/plugins/platforms/ios/qiostheme.mm
+++ b/src/plugins/platforms/ios/qiostheme.mm
@@ -49,28 +49,23 @@ void QIOSTheme::initializeSystemPalette()
Q_DECL_IMPORT QPalette qt_fusionPalette(void);
s_systemPalette = qt_fusionPalette();
- if (@available(ios 13.0, *)) {
- s_systemPalette.setBrush(QPalette::Window, qt_mac_toQBrush(UIColor.systemGroupedBackgroundColor.CGColor));
- s_systemPalette.setBrush(QPalette::Active, QPalette::WindowText, qt_mac_toQBrush(UIColor.labelColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Window, qt_mac_toQBrush(UIColor.systemGroupedBackgroundColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Active, QPalette::WindowText, qt_mac_toQBrush(UIColor.labelColor.CGColor));
- s_systemPalette.setBrush(QPalette::Base, qt_mac_toQBrush(UIColor.secondarySystemGroupedBackgroundColor.CGColor));
- s_systemPalette.setBrush(QPalette::Active, QPalette::Text, qt_mac_toQBrush(UIColor.labelColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Base, qt_mac_toQBrush(UIColor.secondarySystemGroupedBackgroundColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Active, QPalette::Text, qt_mac_toQBrush(UIColor.labelColor.CGColor));
- s_systemPalette.setBrush(QPalette::Button, qt_mac_toQBrush(UIColor.secondarySystemBackgroundColor.CGColor));
- s_systemPalette.setBrush(QPalette::Active, QPalette::ButtonText, qt_mac_toQBrush(UIColor.labelColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Button, qt_mac_toQBrush(UIColor.secondarySystemBackgroundColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Active, QPalette::ButtonText, qt_mac_toQBrush(UIColor.labelColor.CGColor));
- s_systemPalette.setBrush(QPalette::Active, QPalette::BrightText, qt_mac_toQBrush(UIColor.lightTextColor.CGColor));
- s_systemPalette.setBrush(QPalette::Active, QPalette::PlaceholderText, qt_mac_toQBrush(UIColor.placeholderTextColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Active, QPalette::BrightText, qt_mac_toQBrush(UIColor.lightTextColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Active, QPalette::PlaceholderText, qt_mac_toQBrush(UIColor.placeholderTextColor.CGColor));
- s_systemPalette.setBrush(QPalette::Active, QPalette::Link, qt_mac_toQBrush(UIColor.linkColor.CGColor));
- s_systemPalette.setBrush(QPalette::Active, QPalette::LinkVisited, qt_mac_toQBrush(UIColor.linkColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Active, QPalette::Link, qt_mac_toQBrush(UIColor.linkColor.CGColor));
+ s_systemPalette.setBrush(QPalette::Active, QPalette::LinkVisited, qt_mac_toQBrush(UIColor.linkColor.CGColor));
- s_systemPalette.setBrush(QPalette::Highlight, QColor(11, 70, 150, 60));
- s_systemPalette.setBrush(QPalette::HighlightedText, qt_mac_toQBrush(UIColor.labelColor.CGColor));
- } else {
- s_systemPalette.setBrush(QPalette::Highlight, QColor(204, 221, 237));
- s_systemPalette.setBrush(QPalette::HighlightedText, Qt::black);
- }
+ s_systemPalette.setBrush(QPalette::Highlight, QColor(11, 70, 150, 60));
+ s_systemPalette.setBrush(QPalette::HighlightedText, qt_mac_toQBrush(UIColor.labelColor.CGColor));
}
const QPalette *QIOSTheme::palette(QPlatformTheme::Palette type) const
@@ -139,13 +134,11 @@ QVariant QIOSTheme::themeHint(ThemeHint hint) const
QPlatformTheme::Appearance QIOSTheme::appearance() const
{
- if (@available(ios 12, *)) {
- if (UIWindow *window = qt_apple_sharedApplication().keyWindow) {
- return window.rootViewController.traitCollection.userInterfaceStyle
- == UIUserInterfaceStyleDark
- ? QPlatformTheme::Appearance::Dark
- : QPlatformTheme::Appearance::Light;
- }
+ if (UIWindow *window = qt_apple_sharedApplication().windows.lastObject) {
+ return window.rootViewController.traitCollection.userInterfaceStyle
+ == UIUserInterfaceStyleDark
+ ? QPlatformTheme::Appearance::Dark
+ : QPlatformTheme::Appearance::Light;
}
return QPlatformTheme::Appearance::Unknown;
}
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index 668e077803..c4e8968232 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -205,7 +205,7 @@
{
// The initial frame computed during startup may happen before the view has
// a window, meaning our calculations above will be wrong. We ensure that the
- // frame is set correctly once we have a window to base our calulations on.
+ // frame is set correctly once we have a window to base our calculations on.
[self setFrame:self.window.bounds];
}
@@ -405,7 +405,7 @@
// Prevent recursion caused by updating the status bar appearance (position
// or visibility), which in turn may cause a layout of our subviews, and
// a reset of window-states, which themselves affect the view controller
- // properties such as the statusbar visibilty.
+ // properties such as the statusbar visibility.
if (m_updatingProperties)
return;
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 7d904d7642..e88f5ab3d0 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -68,7 +68,7 @@ QIOSWindow::~QIOSWindow()
// According to the UIResponder documentation, Cocoa Touch should react to system interruptions
// that "might cause the view to be removed from the window" by sending touchesCancelled, but in
// practice this doesn't seem to happen when removing the view from its superview. To ensure that
- // Qt's internal state for touch and mouse handling is kept consistent, we therefor have to force
+ // Qt's internal state for touch and mouse handling is kept consistent, we therefore have to force
// cancellation of all touch events.
[m_view touchesCancelled:[NSSet set] withEvent:0];
@@ -259,7 +259,7 @@ void QIOSWindow::requestActivateWindow()
{
// Note that several windows can be active at the same time if they exist in the same
// hierarchy (transient children). But only one window can be QGuiApplication::focusWindow().
- // Dispite the name, 'requestActivateWindow' means raise and transfer focus to the window:
+ // Despite the name, 'requestActivateWindow' means raise and transfer focus to the window:
if (blockedByModal())
return;
@@ -371,6 +371,6 @@ QDebug operator<<(QDebug debug, const QIOSWindow *window)
}
#endif // !QT_NO_DEBUG_STREAM
-#include "moc_qioswindow.cpp"
-
QT_END_NAMESPACE
+
+#include "moc_qioswindow.cpp"
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.h b/src/plugins/platforms/ios/quiaccessibilityelement.h
index bf67db2246..e78fef6d30 100644
--- a/src/plugins/platforms/ios/quiaccessibilityelement.h
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.h
@@ -7,7 +7,7 @@
#import <UIKit/UIKit.h>
#import <QtGui/QtGui>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
@interface QT_MANGLE_NAMESPACE(QMacAccessibilityElement) : UIAccessibilityElement
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm
index c1415163a6..08e366f32b 100644
--- a/src/plugins/platforms/ios/quiaccessibilityelement.mm
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm
@@ -3,7 +3,7 @@
#include "quiaccessibilityelement.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "private/qaccessiblecache_p.h"
#include "private/qcore_mac_p.h"
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 5e1992ee9c..85f27f8450 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -22,12 +22,16 @@
#include <qpa/qwindowsysteminterface_p.h>
Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
+Q_LOGGING_CATEGORY(lcQpaInputEvents, "qt.qpa.input.events")
@implementation QUIView {
QHash<NSUInteger, QWindowSystemInterface::TouchPoint> m_activeTouches;
UITouch *m_activePencilTouch;
int m_nextTouchId;
NSMutableArray<UIAccessibilityElement *> *m_accessibleElements;
+ UIPanGestureRecognizer *m_scrollGestureRecognizer;
+ CGPoint m_lastScrollCursorPos;
+ CGPoint m_lastScrollDelta;
}
+ (void)load
@@ -60,6 +64,21 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
if (self = [self initWithFrame:window->geometry().toCGRect()]) {
self.platformWindow = window;
m_accessibleElements = [[NSMutableArray<UIAccessibilityElement *> alloc] init];
+ m_scrollGestureRecognizer = [[UIPanGestureRecognizer alloc]
+ initWithTarget:self
+ action:@selector(handleScroll:)];
+ // The gesture recognizer should only care about scroll gestures (for now)
+ // Set allowedTouchTypes to empty array here to not interfere with touch events
+ // handled by the UIView. Scroll gestures, even those coming from touch devices,
+ // such as trackpads will still be received as they are not touch events
+ m_scrollGestureRecognizer.allowedTouchTypes = [NSArray array];
+ if (@available(ios 13.4, *)) {
+ m_scrollGestureRecognizer.allowedScrollTypesMask = UIScrollTypeMaskAll;
+ }
+ m_scrollGestureRecognizer.maximumNumberOfTouches = 0;
+ m_lastScrollDelta = CGPointZero;
+ m_lastScrollCursorPos = CGPointZero;
+ [self addGestureRecognizer:m_scrollGestureRecognizer];
}
return self;
@@ -117,6 +136,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
- (void)dealloc
{
[m_accessibleElements release];
+ [m_scrollGestureRecognizer release];
[super dealloc];
}
@@ -430,7 +450,10 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::AsynchronousDelivery>(
self.platformWindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
} else {
- QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(
+ // Send the touch event asynchronously, as the application might spin a recursive
+ // event loop in response to the touch event (a dialog e.g.), which will deadlock
+ // the UIKit event delivery system (QTBUG-98651).
+ QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::AsynchronousDelivery>(
self.platformWindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
}
}
@@ -536,7 +559,12 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
NSTimeInterval timestamp = event ? event.timestamp : [[NSProcessInfo processInfo] systemUptime];
QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
- QWindowSystemInterface::handleTouchCancelEvent(self.platformWindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice());
+
+ // Send the touch event asynchronously, as the application might spin a recursive
+ // event loop in response to the touch event (a dialog e.g.), which will deadlock
+ // the UIKit event delivery system (QTBUG-98651).
+ QWindowSystemInterface::handleTouchCancelEvent<QWindowSystemInterface::AsynchronousDelivery>(
+ self.platformWindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice());
}
- (int)mapPressTypeToKey:(UIPress*)press withModifiers:(Qt::KeyboardModifiers)qtModifiers text:(QString &)text
@@ -550,7 +578,6 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
case UIPressTypeMenu: return Qt::Key_Menu;
case UIPressTypePlayPause: return Qt::Key_MediaTogglePlayPause;
}
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_13_4)
if (@available(ios 13.4, *)) {
NSString *charactersIgnoringModifiers = press.key.charactersIgnoringModifiers;
Qt::Key key = QAppleKeyMapper::fromUIKitKey(charactersIgnoringModifiers);
@@ -559,7 +586,6 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
return QAppleKeyMapper::fromNSString(qtModifiers, press.key.characters,
charactersIgnoringModifiers, text);
}
-#endif
return Qt::Key_unknown;
}
@@ -572,10 +598,8 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
bool handled = false;
for (UIPress* press in presses) {
Qt::KeyboardModifiers qtModifiers = Qt::NoModifier;
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_13_4)
if (@available(ios 13.4, *))
qtModifiers = QAppleKeyMapper::fromUIKitModifiers(press.key.modifierFlags);
-#endif
QString text;
int key = [self mapPressTypeToKey:press withModifiers:qtModifiers text:text];
if (key == Qt::Key_unknown)
@@ -664,6 +688,63 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
UIEditingInteractionConfigurationDefault : UIEditingInteractionConfigurationNone;
}
+#if QT_CONFIG(wheelevent)
+- (void)handleScroll:(UIPanGestureRecognizer *)recognizer
+{
+ if (!self.platformWindow->window())
+ return;
+
+ if (!self.canBecomeFirstResponder)
+ return;
+
+ CGPoint translation = [recognizer translationInView:self];
+ CGFloat deltaX = translation.x - m_lastScrollDelta.x;
+ CGFloat deltaY = translation.y - m_lastScrollDelta.y;
+
+ QPoint angleDelta;
+ // From QNSView implementation:
+ // "Since deviceDelta is delivered as pixels rather than degrees, we need to
+ // convert from pixels to degrees in a sensible manner.
+ // It looks like 1/4 degrees per pixel behaves most native.
+ // (NB: Qt expects the unit for delta to be 8 per degree):"
+ const int pixelsToDegrees = 2; // 8 * 1/4
+ angleDelta.setX(deltaX * pixelsToDegrees);
+ angleDelta.setY(deltaY * pixelsToDegrees);
+
+ QPoint pixelDelta;
+ pixelDelta.setX(deltaX);
+ pixelDelta.setY(deltaY);
+
+ NSTimeInterval time_stamp = [[NSProcessInfo processInfo] systemUptime];
+ ulong qt_timestamp = time_stamp * 1000;
+
+ Qt::KeyboardModifiers qt_modifierFlags = Qt::NoModifier;
+ if (@available(ios 13.4, *))
+ qt_modifierFlags = QAppleKeyMapper::fromUIKitModifiers(recognizer.modifierFlags);
+
+ if (recognizer.state == UIGestureRecognizerStateBegan)
+ // locationInView: doesn't return the cursor position at the time of the wheel event,
+ // but rather gives us the position with the deltas applied, so we need to save the
+ // cursor position at the beginning of the gesture
+ m_lastScrollCursorPos = [recognizer locationInView:self];
+
+ if (recognizer.state != UIGestureRecognizerStateEnded) {
+ m_lastScrollDelta.x = translation.x;
+ m_lastScrollDelta.y = translation.y;
+ } else {
+ m_lastScrollDelta = CGPointZero;
+ }
+
+ QPoint qt_local = QPointF::fromCGPoint(m_lastScrollCursorPos).toPoint();
+ QPoint qt_global = self.platformWindow->mapToGlobal(qt_local);
+
+ qCInfo(lcQpaInputEvents).nospace() << "wheel event" << " at " << qt_local
+ << " pixelDelta=" << pixelDelta << " angleDelta=" << angleDelta;
+
+ QWindowSystemInterface::handleWheelEvent(self.platformWindow->window(), qt_timestamp, qt_local, qt_global, pixelDelta, angleDelta, qt_modifierFlags);
+}
+#endif // QT_CONFIG(wheelevent)
+
@end
@implementation UIView (QtHelpers)
@@ -708,21 +789,13 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
+ (Class)layerClass
{
-#ifdef TARGET_IPHONE_SIMULATOR
- if (@available(ios 13.0, *))
-#endif
-
return [CAMetalLayer class];
-
-#ifdef TARGET_IPHONE_SIMULATOR
- return nil;
-#endif
}
@end
#endif
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
// Include category as an alternative to using -ObjC (Apple QA1490)
#include "quiview_accessibility.mm"
#endif
diff --git a/src/plugins/platforms/linuxfb/CMakeLists.txt b/src/plugins/platforms/linuxfb/CMakeLists.txt
index a671dcfc1e..9162997fc8 100644
--- a/src/plugins/platforms/linuxfb/CMakeLists.txt
+++ b/src/plugins/platforms/linuxfb/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from linuxfb.pro.
#####################################################################
diff --git a/src/plugins/platforms/minimal/CMakeLists.txt b/src/plugins/platforms/minimal/CMakeLists.txt
index a763dbac9a..3ce3ce2b79 100644
--- a/src/plugins/platforms/minimal/CMakeLists.txt
+++ b/src/plugins/platforms/minimal/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from minimal.pro.
#####################################################################
diff --git a/src/plugins/platforms/minimalegl/CMakeLists.txt b/src/plugins/platforms/minimalegl/CMakeLists.txt
index f285d8ece6..286e8aa5af 100644
--- a/src/plugins/platforms/minimalegl/CMakeLists.txt
+++ b/src/plugins/platforms/minimalegl/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from minimalegl.pro.
qt_find_package(EGL) # special case
diff --git a/src/plugins/platforms/offscreen/CMakeLists.txt b/src/plugins/platforms/offscreen/CMakeLists.txt
index 424da0a980..0a6d923f0c 100644
--- a/src/plugins/platforms/offscreen/CMakeLists.txt
+++ b/src/plugins/platforms/offscreen/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from offscreen.pro.
#####################################################################
diff --git a/src/plugins/platforms/qnx/CMakeLists.txt b/src/plugins/platforms/qnx/CMakeLists.txt
index 3e952e6ddf..ad7719a09e 100644
--- a/src/plugins/platforms/qnx/CMakeLists.txt
+++ b/src/plugins/platforms/qnx/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from qnx.pro.
#####################################################################
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
index 2a2422f5cc..525b22242c 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
@@ -746,6 +746,6 @@ void QQnxScreenEventHandler::timerEvent(QTimerEvent *event)
}
}
-#include "moc_qqnxscreeneventhandler.cpp"
-
QT_END_NAMESPACE
+
+#include "moc_qqnxscreeneventhandler.cpp"
diff --git a/src/plugins/platforms/vkkhrdisplay/CMakeLists.txt b/src/plugins/platforms/vkkhrdisplay/CMakeLists.txt
index 98fb6d39b7..1d32b3b808 100644
--- a/src/plugins/platforms/vkkhrdisplay/CMakeLists.txt
+++ b/src/plugins/platforms/vkkhrdisplay/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
qt_find_package(WrapFreetype PROVIDED_TARGETS WrapFreetype::WrapFreetype)
qt_internal_add_plugin(QVkKhrDisplayIntegrationPlugin
diff --git a/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.cpp b/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.cpp
index 96c7fbfbdd..4d58e4154e 100644
--- a/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.cpp
+++ b/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.cpp
@@ -46,6 +46,9 @@ void QVkKhrDisplayVulkanInstance::createOrAdoptInstance()
m_enumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)
m_vkGetInstanceProcAddr(m_vkInst, "vkEnumeratePhysicalDevices");
+ m_getPhysicalDeviceSurfaceSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceSurfaceSupportKHR"));
+
// Use for first physical device, unless overridden by QT_VK_PHYSICAL_DEVICE_INDEX.
// This behavior matches what the Vulkan backend of QRhi would do.
@@ -81,10 +84,14 @@ bool QVkKhrDisplayVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevic
uint32_t queueFamilyIndex,
QWindow *window)
{
- Q_UNUSED(physicalDevice);
- Q_UNUSED(queueFamilyIndex);
- Q_UNUSED(window);
- return true;
+ if (!m_getPhysicalDeviceSurfaceSupportKHR)
+ return true;
+
+ VkSurfaceKHR surface = QVulkanInstance::surfaceForWindow(window);
+ VkBool32 supported = false;
+ m_getPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, &supported);
+
+ return supported;
}
bool QVkKhrDisplayVulkanInstance::chooseDisplay()
diff --git a/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.h b/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.h
index a47878e344..bf99dc037f 100644
--- a/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.h
+++ b/src/plugins/platforms/vkkhrdisplay/qvkkhrdisplayvulkaninstance.h
@@ -45,6 +45,7 @@ private:
QVulkanInstance *m_instance;
VkPhysicalDevice m_physDev = VK_NULL_HANDLE;
PFN_vkEnumeratePhysicalDevices m_enumeratePhysicalDevices = nullptr;
+ PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_getPhysicalDeviceSurfaceSupportKHR = nullptr;
#if VK_KHR_display
PFN_vkGetPhysicalDeviceDisplayPropertiesKHR m_getPhysicalDeviceDisplayPropertiesKHR = nullptr;
PFN_vkGetDisplayModePropertiesKHR m_getDisplayModePropertiesKHR = nullptr;
diff --git a/src/plugins/platforms/vnc/CMakeLists.txt b/src/plugins/platforms/vnc/CMakeLists.txt
index ca9445207b..a9086bdf48 100644
--- a/src/plugins/platforms/vnc/CMakeLists.txt
+++ b/src/plugins/platforms/vnc/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from vnc.pro.
#####################################################################
diff --git a/src/plugins/platforms/wasm/CMakeLists.txt b/src/plugins/platforms/wasm/CMakeLists.txt
index efd468c9be..94a26da371 100644
--- a/src/plugins/platforms/wasm/CMakeLists.txt
+++ b/src/plugins/platforms/wasm/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from wasm.pro.
#####################################################################
@@ -11,15 +14,18 @@ qt_internal_add_plugin(QWasmIntegrationPlugin
STATIC
SOURCES
main.cpp
+ qwasmaccessibility.cpp qwasmaccessibility.h
qwasmclipboard.cpp qwasmclipboard.h
qwasmcompositor.cpp qwasmcompositor.h
qwasmcursor.cpp qwasmcursor.h
+ qwasmevent.cpp qwasmevent.h
qwasmeventdispatcher.cpp qwasmeventdispatcher.h
qwasmeventtranslator.cpp qwasmeventtranslator.h
qwasmfontdatabase.cpp qwasmfontdatabase.h
qwasmintegration.cpp qwasmintegration.h
qwasmoffscreensurface.cpp qwasmoffscreensurface.h
qwasmopenglcontext.cpp qwasmopenglcontext.h
+ qwasmplatform.cpp qwasmplatform.h
qwasmscreen.cpp qwasmscreen.h
qwasmservices.cpp qwasmservices.h
qwasmstring.cpp qwasmstring.h
diff --git a/src/plugins/platforms/wasm/qtloader.js b/src/plugins/platforms/wasm/qtloader.js
index 33280237ab..2de0ac95e8 100644
--- a/src/plugins/platforms/wasm/qtloader.js
+++ b/src/plugins/platforms/wasm/qtloader.js
@@ -61,6 +61,8 @@
// Optional exited element constructor function.
// showError : function(crashed, exitCode, containerElement)
// Optional error element constructor function.
+// statusChanged : function(newStatus)
+// Optional callback called when the status of the app has changed
//
// path : <string>
// Prefix path for wasm file, realative to the loading HMTL file.
@@ -232,13 +234,19 @@ function QtLoader(config)
self.restartCount = 0;
+ function handleError(error) {
+ self.error = error;
+ setStatus("Error");
+ console.error(error);
+ }
+
function fetchResource(filePath) {
var fullPath = config.path + filePath;
return fetch(fullPath).then(function(response) {
if (!response.ok) {
- self.error = response.status + " " + response.statusText + " " + response.url;
- setStatus("Error");
- return Promise.reject(self.error)
+ let err = response.status + " " + response.statusText + " " + response.url;
+ handleError(err);
+ return Promise.reject(err)
} else {
return response;
}
@@ -287,13 +295,11 @@ function QtLoader(config)
// Check for Wasm & WebGL support; set error and return before downloading resources if missing
if (!webAssemblySupported()) {
- self.error = "Error: WebAssembly is not supported"
- setStatus("Error");
+ handleError("Error: WebAssembly is not supported");
return;
}
if (!webGLSupported()) {
- self.error = "Error: WebGL is not supported"
- setStatus("Error");
+ handleError("Error: WebGL is not supported");
return;
}
@@ -319,8 +325,9 @@ function QtLoader(config)
Promise.all([emscriptenModuleSourcePromise, wasmModulePromise]).then(function(){
completeLoadEmscriptenModule(applicationName, emscriptenModuleSource, wasmModule);
}).catch(function(error) {
- self.error = error;
- setStatus("Error");
+ handleError(error);
+ // An error here is fatal, abort
+ self.moduleConfig.onAbort(error)
});
}
@@ -333,8 +340,7 @@ function QtLoader(config)
WebAssembly.instantiate(wasmModule, imports).then(function(instance) {
successCallback(instance, wasmModule);
}, function(error) {
- self.error = error;
- setStatus("Error");
+ handleError(error)
});
return {};
};
@@ -418,8 +424,7 @@ function QtLoader(config)
// Restart by readling the emscripten app module.
++self.restartCount;
if (self.restartCount > config.restartLimit) {
- self.error = "Error: This application has crashed too many times and has been disabled. Reload the page to try again."
- setStatus("Error");
+ handleError("Error: This application has crashed too many times and has been disabled. Reload the page to try again.");
return;
}
loadEmscriptenModule(applicationName);
@@ -539,27 +544,27 @@ function QtLoader(config)
function addCanvasElement(element) {
if (publicAPI.status == "Running")
- self.module.qtAddCanvasElement(element);
+ self.module.qtAddContainerElement(element);
else
console.log("Error: addCanvasElement can only be called in the Running state");
}
function removeCanvasElement(element) {
if (publicAPI.status == "Running")
- self.module.qtRemoveCanvasElement(element);
+ self.module.qtRemoveContainerElement(element);
else
console.log("Error: removeCanvasElement can only be called in the Running state");
}
function resizeCanvasElement(element) {
if (publicAPI.status == "Running")
- self.module.qtResizeCanvasElement(element);
+ self.module.qtResizeContainerElement(element);
}
function setFontDpi(dpi) {
self.qtFontDpi = dpi;
if (publicAPI.status == "Running")
- self.qtSetFontDpi(dpi);
+ self.qtUpdateDpi();
}
function fontDpi() {
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.cpp b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
new file mode 100644
index 0000000000..b96a3799e6
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
@@ -0,0 +1,250 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "qwasmaccessibility.h"
+#include "qwasmscreen.h"
+
+// Qt WebAssembly a11y backend
+//
+// This backend implements accessibility support by creating "shadowing" html
+// elements for each Qt UI element. We access the DOM by using Emscripten's
+// val.h API.
+//
+// Currently, html elements are created in response to notifyAccessibilityUpdate
+// events. In addition or alternatively, we could also walk the accessibility tree
+// from setRootObject().
+
+
+QWasmAccessibility::QWasmAccessibility()
+{
+
+}
+
+QWasmAccessibility::~QWasmAccessibility()
+{
+
+}
+
+emscripten::val QWasmAccessibility::getContainer(QAccessibleInterface *iface)
+{
+ // Get to QWasmScreen::container(), return undefined element if unable to
+ QWindow *window = iface->window();
+ if (!window)
+ return emscripten::val::undefined();
+ QWasmScreen *screen = QWasmScreen::get(window->screen());
+ if (!screen)
+ return emscripten::val::undefined();
+ return screen->container();
+}
+
+emscripten::val QWasmAccessibility::getDocument(const emscripten::val &container)
+{
+ if (container.isUndefined())
+ return emscripten::val::undefined();
+ return container["ownerDocument"];
+}
+
+emscripten::val QWasmAccessibility::getDocument(QAccessibleInterface *iface)
+{
+ return getDocument(getContainer(iface));
+}
+
+emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *iface)
+{
+ // Get the html container element for the interface; this depends on which
+ // QScreen it is on. If the interface is not on a screen yet we get an undefined
+ // container, and the code below handles that case as well.
+ emscripten::val container = getContainer(iface);
+
+ // Get the correct html document for the container, or fall back
+ // to the global document. TODO: Does using the correct document actually matter?
+ emscripten::val document = container.isUndefined() ? emscripten::val::global("document") : getDocument(container);
+
+ // Translate the Qt a11y elemen role into html element type + ARIA role.
+ // Here we can either create <div> elements with a spesific ARIA role,
+ // or create e.g. <button> elements which should have built-in accessibility.
+ emscripten::val element = [iface, document] {
+
+ emscripten::val element = emscripten::val::undefined();
+
+ switch (iface->role()) {
+
+ case QAccessible::Button: {
+ element = document.call<emscripten::val>("createElement", std::string("button"));
+ } break;
+
+ case QAccessible::CheckBox: {
+ element = document.call<emscripten::val>("createElement", std::string("input"));
+ element.call<void>("setAttribute", std::string("type"), std::string("checkbox"));
+ } break;
+
+ default:
+ qDebug() << "TODO: createHtmlElement() handle" << iface->role();
+ element = document.call<emscripten::val>("createElement", std::string("div"));
+ //element.set("AriaRole", "foo");
+ }
+
+ return element;
+
+ }();
+
+ // Add the html element to the container if we have one. If not there
+ // is a second chance when handling the ObjectShow event.
+ if (!container.isUndefined())
+ container.call<void>("appendChild", element);
+
+ return element;
+}
+
+void QWasmAccessibility::destroyHtmlElement(QAccessibleInterface *iface)
+{
+ Q_UNUSED(iface);
+ qDebug() << "TODO destroyHtmlElement";
+}
+
+emscripten::val QWasmAccessibility::ensureHtmlElement(QAccessibleInterface *iface)
+{
+ auto it = m_elements.find(iface);
+ if (it != m_elements.end())
+ return it.value();
+
+ emscripten::val element = createHtmlElement(iface);
+ m_elements.insert(iface, element);
+
+ return element;
+}
+
+void QWasmAccessibility::setHtmlElementVisibility(QAccessibleInterface *iface, bool visible)
+{
+ emscripten::val element = ensureHtmlElement(iface);
+ emscripten::val container = getContainer(iface);
+
+ if (container.isUndefined()) {
+ qDebug() << "TODO: setHtmlElementVisibility: unable to find html container for element" << iface;
+ return;
+ }
+
+ container.call<void>("appendChild", element);
+
+ element.set("ariaHidden", !visible); // ariaHidden mean completely hidden; maybe some sort of soft-hidden should be used.
+}
+
+void QWasmAccessibility::setHtmlElementGeometry(QAccessibleInterface *iface)
+{
+ emscripten::val element = ensureHtmlElement(iface);
+ setHtmlElementGeometry(iface, element);
+}
+
+void QWasmAccessibility::setHtmlElementGeometry(QAccessibleInterface *iface, emscripten::val element)
+{
+ // Position the element using "position: absolute" in order to place
+ // it under the corresponding Qt element on the canvas.
+ QRect geometry = iface->rect();
+ emscripten::val style = element["style"];
+ style.set("position", std::string("absolute"));
+ style.set("z-index", std::string("-1")); // FIXME: "0" should be sufficient to order beheind the canvas, but isn't
+ style.set("left", std::to_string(geometry.x()) + "px");
+ style.set("top", std::to_string(geometry.y()) + "px");
+ style.set("width", std::to_string(geometry.width()) + "px");
+ style.set("height", std::to_string(geometry.height()) + "px");
+}
+
+void QWasmAccessibility::setHtmlElementTextName(QAccessibleInterface *iface)
+{
+ emscripten::val element = ensureHtmlElement(iface);
+ QString text = iface->text(QAccessible::Name);
+ element.set("innerHTML", text.toStdString()); // FIXME: use something else than innerHTML
+}
+
+void QWasmAccessibility::handleStaticTextUpdate(QAccessibleEvent *event)
+{
+ switch (event->type()) {
+ case QAccessible::NameChanged: {
+ setHtmlElementTextName(event->accessibleInterface());
+ } break;
+ default:
+ qDebug() << "TODO: implement handleStaticTextUpdate for event" << event->type();
+ break;
+ }
+}
+
+void QWasmAccessibility::handleButtonUpdate(QAccessibleEvent *event)
+{
+ qDebug() << "TODO: implement handleButtonUpdate for event" << event->type();
+}
+
+void QWasmAccessibility::handleCheckBoxUpdate(QAccessibleEvent *event)
+{
+ switch (event->type()) {
+ case QAccessible::NameChanged: {
+ setHtmlElementTextName(event->accessibleInterface());
+ } break;
+ default:
+ qDebug() << "TODO: implement handleCheckBoxUpdate for event" << event->type();
+ break;
+ }
+}
+
+void QWasmAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
+{
+ QAccessibleInterface *iface = event->accessibleInterface();
+ if (!iface) {
+ qWarning() << "notifyAccessibilityUpdate with null a11y interface" ;
+ return;
+ }
+
+ // Handle some common event types. See
+ // https://doc.qt.io/qt-5/qaccessible.html#Event-enum
+ switch (event->type()) {
+ case QAccessible::ObjectShow:
+
+ setHtmlElementVisibility(iface, true);
+
+ // Sync up properties on show;
+ setHtmlElementGeometry(iface);
+ setHtmlElementTextName(iface);
+
+ return;
+ break;
+ case QAccessible::ObjectHide:
+ setHtmlElementVisibility(iface, false);
+ return;
+ break;
+ // TODO: maybe handle more types here
+ default:
+ break;
+ };
+
+ // Switch on interface role, see
+ // https://doc.qt.io/qt-5/qaccessibleinterface.html#role
+ switch (iface->role()) {
+ case QAccessible::StaticText:
+ handleStaticTextUpdate(event);
+ break;
+ case QAccessible::Button:
+ handleStaticTextUpdate(event);
+ break;
+ case QAccessible::CheckBox:
+ handleCheckBoxUpdate(event);
+ break;
+ default:
+ qDebug() << "TODO: implement notifyAccessibilityUpdate for role" << iface->role();
+ };
+}
+
+void QWasmAccessibility::setRootObject(QObject *o)
+{
+ qDebug() << "setRootObject" << o;
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(o);
+ Q_UNUSED(iface)
+}
+
+void QWasmAccessibility::initialize()
+{
+
+}
+
+void QWasmAccessibility::cleanup()
+{
+
+}
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.h b/src/plugins/platforms/wasm/qwasmaccessibility.h
new file mode 100644
index 0000000000..4f34b96c2e
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.h
@@ -0,0 +1,44 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QWASMACCESIBILITY_H
+#define QWASMACCESIBILITY_H
+
+#include <QtCore/qhash.h>
+#include <qpa/qplatformaccessibility.h>
+
+#include <emscripten/val.h>
+
+class QWasmAccessibility : public QPlatformAccessibility
+{
+public:
+ QWasmAccessibility();
+ ~QWasmAccessibility();
+
+ static emscripten::val getContainer(QAccessibleInterface *iface);
+ static emscripten::val getDocument(const emscripten::val &container);
+ static emscripten::val getDocument(QAccessibleInterface *iface);
+
+ emscripten::val createHtmlElement(QAccessibleInterface *iface);
+ void destroyHtmlElement(QAccessibleInterface *iface);
+ emscripten::val ensureHtmlElement(QAccessibleInterface *iface);
+ void setHtmlElementVisibility(QAccessibleInterface *iface, bool visible);
+ void setHtmlElementGeometry(QAccessibleInterface *iface);
+ void setHtmlElementGeometry(QAccessibleInterface *iface, emscripten::val element);
+ void setHtmlElementTextName(QAccessibleInterface *iface);
+
+ void handleStaticTextUpdate(QAccessibleEvent *event);
+ void handleButtonUpdate(QAccessibleEvent *event);
+ void handleCheckBoxUpdate(QAccessibleEvent *event);
+
+ void notifyAccessibilityUpdate(QAccessibleEvent *event) override;
+ void setRootObject(QObject *o) override;
+ void initialize() override;
+ void cleanup() override;
+
+private:
+ QHash<QAccessibleInterface *, emscripten::val> m_elements;
+
+};
+
+#endif
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.cpp b/src/plugins/platforms/wasm/qwasmclipboard.cpp
index a10e15f421..99f3e61155 100644
--- a/src/plugins/platforms/wasm/qwasmclipboard.cpp
+++ b/src/plugins/platforms/wasm/qwasmclipboard.cpp
@@ -16,85 +16,9 @@
#include <QBuffer>
#include <QString>
+QT_BEGIN_NAMESPACE
using namespace emscripten;
-static void pasteClipboardData(emscripten::val format, emscripten::val dataPtr)
-{
- QString formatString = QWasmString::toQString(format);
- QByteArray dataArray = QByteArray::fromStdString(dataPtr.as<std::string>());
-
- QMimeData *mMimeData = new QMimeData;
- mMimeData->setData(formatString, dataArray);
-
- QWasmClipboard::qWasmClipboardPaste(mMimeData);
-// QWasmIntegration::get()->getWasmClipboard()->isPaste = false;
-}
-
-static void qClipboardPasteResolve(emscripten::val blob)
-{
- // read Blob here
-
- auto fileReader = std::make_shared<qstdweb::FileReader>();
- auto _blob = qstdweb::Blob(blob);
- QString formatString = QString::fromStdString(_blob.type());
-
- fileReader->readAsArrayBuffer(_blob);
- char *chunkBuffer = nullptr;
- qstdweb::ArrayBuffer result = fileReader->result();
- qstdweb::Uint8Array(result).copyTo(chunkBuffer);
- QMimeData *mMimeData = new QMimeData;
- mMimeData->setData(formatString, chunkBuffer);
- QWasmClipboard::qWasmClipboardPaste(mMimeData);
-}
-
-static void qClipboardPromiseResolve(emscripten::val clipboardItems)
-{
- int itemsCount = clipboardItems["length"].as<int>();
-
- for (int i = 0; i < itemsCount; i++) {
- int typesCount = clipboardItems[i]["types"]["length"].as<int>(); // ClipboardItem
-
- std::string mimeFormat = clipboardItems[i]["types"][0].as<std::string>();
-
- if (mimeFormat.find(std::string("text")) != std::string::npos) {
- // simple val object, no further processing
-
- val navigator = val::global("navigator");
- val textPromise = navigator["clipboard"].call<val>("readText");
- val readTextResolve = val::global("Module")["qtClipboardTextPromiseResolve"];
- textPromise.call<val>("then", readTextResolve);
-
- } else {
- // binary types require additional processing
- for (int j = 0; j < typesCount; j++) {
- val pasteResolve = emscripten::val::module_property("qtClipboardPasteResolve");
- val pasteException = emscripten::val::module_property("qtClipboardPromiseException");
-
- // get the blob
- clipboardItems[i]
- .call<val>("getType", clipboardItems[i]["types"][j])
- .call<val>("then", pasteResolve)
- .call<val>("catch", pasteException);
- }
- }
- }
-}
-
-static void qClipboardCopyPromiseResolve(emscripten::val something)
-{
- Q_UNUSED(something)
- qWarning() << "copy succeeeded";
-}
-
-
-static emscripten::val qClipboardPromiseException(emscripten::val something)
-{
- qWarning() << "clipboard error"
- << QString::fromStdString(something["name"].as<std::string>())
- << QString::fromStdString(something["message"].as<std::string>());
- return something;
-}
-
static void commonCopyEvent(val event)
{
QMimeData *_mimes = QWasmIntegration::get()->getWasmClipboard()->mimeData(QClipboard::Clipboard);
@@ -214,24 +138,10 @@ static void qClipboardPasteTo(val dataTransfer)
QWasmIntegration::get()->getWasmClipboard()->m_isListener = false;
}
-static void qClipboardTextPromiseResolve(emscripten::val clipdata)
-{
- pasteClipboardData(emscripten::val("text/plain"), clipdata);
-}
-
EMSCRIPTEN_BINDINGS(qtClipboardModule) {
- function("qtPasteClipboardData", &pasteClipboardData);
-
- function("qtClipboardTextPromiseResolve", &qClipboardTextPromiseResolve);
- function("qtClipboardPromiseResolve", &qClipboardPromiseResolve);
-
- function("qtClipboardCopyPromiseResolve", &qClipboardCopyPromiseResolve);
- function("qtClipboardPromiseException", &qClipboardPromiseException);
-
function("qtClipboardCutTo", &qClipboardCutTo);
function("qtClipboardCopyTo", &qClipboardCopyTo);
function("qtClipboardPasteTo", &qClipboardPasteTo);
- function("qtClipboardPasteResolve", &qClipboardPasteResolve);
}
QWasmClipboard::QWasmClipboard() :
@@ -418,14 +328,18 @@ void QWasmClipboard::writeToClipboardApi()
// break;
}
- val copyResolve = emscripten::val::module_property("qtClipboardCopyPromiseResolve");
- val copyException = emscripten::val::module_property("qtClipboardPromiseException");
-
val navigator = val::global("navigator");
- navigator["clipboard"]
- .call<val>("write", clipboardWriteArray)
- .call<val>("then", copyResolve)
- .call<val>("catch", copyException);
+
+ qstdweb::Promise::make(
+ navigator["clipboard"], "write",
+ {
+ .catchFunc = [](emscripten::val error) {
+ qWarning() << "clipboard error"
+ << QString::fromStdString(error["name"].as<std::string>())
+ << QString::fromStdString(error["message"].as<std::string>());
+ }
+ },
+ clipboardWriteArray);
}
void QWasmClipboard::writeToClipboard(const QMimeData *data)
@@ -438,3 +352,4 @@ void QWasmClipboard::writeToClipboard(const QMimeData *data)
val document = val::global("document");
document.call<val>("execCommand", val("copy"));
}
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.h b/src/plugins/platforms/wasm/qwasmclipboard.h
index 4fcb712764..ef11fd2e49 100644
--- a/src/plugins/platforms/wasm/qwasmclipboard.h
+++ b/src/plugins/platforms/wasm/qwasmclipboard.h
@@ -12,6 +12,8 @@
#include <emscripten/bind.h>
#include <emscripten/val.h>
+QT_BEGIN_NAMESPACE
+
class QWasmClipboard : public QObject, public QPlatformClipboard
{
public:
@@ -36,4 +38,6 @@ public:
bool isSafari;
};
+QT_END_NAMESPACE
+
#endif // QWASMCLIPBOARD_H
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp
index 9fc4dedb9b..e93098cf79 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp
@@ -7,6 +7,7 @@
#include "qwasmeventtranslator.h"
#include "qwasmeventdispatcher.h"
#include "qwasmclipboard.h"
+#include "qwasmevent.h"
#include <QtOpenGL/qopengltexture.h>
@@ -25,18 +26,16 @@
#include <emscripten/bind.h>
+namespace {
+QWasmWindow *AsWasmWindow(QWindow *window) {
+ return static_cast<QWasmWindow*>(window->handle());
+}
+} // namespace
+
using namespace emscripten;
Q_GUI_EXPORT int qt_defaultDpiX();
-QWasmCompositedWindow::QWasmCompositedWindow()
- : window(nullptr)
- , parentWindow(nullptr)
- , flushPending(false)
- , visible(false)
-{
-}
-
bool g_scrollingInvertedFromDevice = false;
static void mouseWheelEvent(emscripten::val event)
@@ -51,31 +50,23 @@ EMSCRIPTEN_BINDINGS(qtMouseModule) {
}
QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
- :QObject(screen)
+ : QObject(screen)
+ , m_windowManipulation(screen)
, m_blitter(new QOpenGLTextureBlitter)
- , m_needComposit(false)
- , m_inFlush(false)
- , m_inResize(false)
- , m_isEnabled(true)
- , m_targetDevicePixelRatio(1)
- , draggedWindow(nullptr)
- , lastWindow(nullptr)
- , pressedButtons(Qt::NoButton)
- , resizeMode(QWasmCompositor::ResizeNone)
- , eventTranslator(new QWasmEventTranslator())
- , mouseInCanvas(false)
+ , m_eventTranslator(std::make_unique<QWasmEventTranslator>())
{
- touchDevice = new QPointingDevice(
+ m_touchDevice = std::make_unique<QPointingDevice>(
"touchscreen", 1, QInputDevice::DeviceType::TouchScreen,
QPointingDevice::PointerType::Finger,
- QPointingDevice::Capability::Position | QPointingDevice::Capability::Area | QPointingDevice::Capability::NormalizedPosition,
+ QPointingDevice::Capability::Position | QPointingDevice::Capability::Area
+ | QPointingDevice::Capability::NormalizedPosition,
10, 0);
- QWindowSystemInterface::registerInputDevice(touchDevice);
+ QWindowSystemInterface::registerInputDevice(m_touchDevice.get());
}
QWasmCompositor::~QWasmCompositor()
{
- windowUnderMouse.clear();
+ m_windowUnderMouse.clear();
if (m_requestAnimationFrameId != -1)
emscripten_cancel_animation_frame(m_requestAnimationFrameId);
@@ -90,12 +81,6 @@ void QWasmCompositor::deregisterEventHandlers()
emscripten_set_keydown_callback(canvasSelector.constData(), 0, 0, NULL);
emscripten_set_keyup_callback(canvasSelector.constData(), 0, 0, NULL);
- emscripten_set_mousedown_callback(canvasSelector.constData(), 0, 0, NULL);
- emscripten_set_mouseup_callback(canvasSelector.constData(), 0, 0, NULL);
- emscripten_set_mousemove_callback(canvasSelector.constData(), 0, 0, NULL);
- emscripten_set_mouseenter_callback(canvasSelector.constData(), 0, 0, NULL);
- emscripten_set_mouseleave_callback(canvasSelector.constData(), 0, 0, NULL);
-
emscripten_set_focus_callback(canvasSelector.constData(), 0, 0, NULL);
emscripten_set_wheel_callback(canvasSelector.constData(), 0, 0, NULL);
@@ -136,9 +121,7 @@ void QWasmCompositor::initEventHandlers()
{
QByteArray canvasSelector = screen()->canvasTargetId().toUtf8();
- eventTranslator->g_usePlatformMacSpecifics
- = (QWasmIntegration::get()->platform == QWasmIntegration::MacOSPlatform);
- if (QWasmIntegration::get()->platform == QWasmIntegration::MacOSPlatform) {
+ if (platform() == Platform::MacOS) {
if (!emscripten::val::global("window")["safari"].isUndefined()) {
val canvas = screen()->canvas();
canvas.call<void>("addEventListener",
@@ -147,25 +130,32 @@ void QWasmCompositor::initEventHandlers()
}
}
- emscripten_set_keydown_callback(canvasSelector.constData(), (void *)this, 1, &keyboard_cb);
- emscripten_set_keyup_callback(canvasSelector.constData(), (void *)this, 1, &keyboard_cb);
+ constexpr EM_BOOL UseCapture = 1;
- emscripten_set_mousedown_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
- emscripten_set_mouseup_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
- emscripten_set_mousemove_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
- emscripten_set_mouseenter_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
- emscripten_set_mouseleave_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
+ emscripten_set_keydown_callback(canvasSelector.constData(), (void *)this, UseCapture, &keyboard_cb);
+ emscripten_set_keyup_callback(canvasSelector.constData(), (void *)this, UseCapture, &keyboard_cb);
- emscripten_set_focus_callback(canvasSelector.constData(), (void *)this, 1, &focus_cb);
+ val canvas = screen()->canvas();
+ const auto callback = std::function([this](emscripten::val event) {
+ if (processPointer(*PointerEvent::fromWeb(event)))
+ event.call<void>("preventDefault");
+ });
- emscripten_set_wheel_callback(canvasSelector.constData(), (void *)this, 1, &wheel_cb);
+ m_pointerDownCallback = std::make_unique<qstdweb::EventCallback>(canvas, "pointerdown", callback);
+ m_pointerMoveCallback = std::make_unique<qstdweb::EventCallback>(canvas, "pointermove", callback);
+ m_pointerUpCallback = std::make_unique<qstdweb::EventCallback>(canvas, "pointerup", callback);
+ m_pointerEnterCallback = std::make_unique<qstdweb::EventCallback>(canvas, "pointerenter", callback);
+ m_pointerLeaveCallback = std::make_unique<qstdweb::EventCallback>(canvas, "pointerleave", callback);
- emscripten_set_touchstart_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
- emscripten_set_touchend_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
- emscripten_set_touchmove_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
- emscripten_set_touchcancel_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
+ emscripten_set_focus_callback(canvasSelector.constData(), (void *)this, UseCapture, &focus_cb);
+
+ emscripten_set_wheel_callback(canvasSelector.constData(), (void *)this, UseCapture, &wheel_cb);
+
+ emscripten_set_touchstart_callback(canvasSelector.constData(), (void *)this, UseCapture, &touchCallback);
+ emscripten_set_touchend_callback(canvasSelector.constData(), (void *)this, UseCapture, &touchCallback);
+ emscripten_set_touchmove_callback(canvasSelector.constData(), (void *)this, UseCapture, &touchCallback);
+ emscripten_set_touchcancel_callback(canvasSelector.constData(), (void *)this, UseCapture, &touchCallback);
- val canvas = screen()->canvas();
canvas.call<void>("addEventListener",
std::string("drop"),
val::module_property("qtDrop"), val(true));
@@ -178,64 +168,46 @@ void QWasmCompositor::setEnabled(bool enabled)
m_isEnabled = enabled;
}
-void QWasmCompositor::addWindow(QWasmWindow *window, QWasmWindow *parentWindow)
+void QWasmCompositor::addWindow(QWasmWindow *window)
{
- QWasmCompositedWindow compositedWindow;
- compositedWindow.window = window;
- compositedWindow.parentWindow = parentWindow;
- m_compositedWindows.insert(window, compositedWindow);
+ m_windowVisibility.insert(window, false);
- if (parentWindow == 0)
- m_windowStack.append(window);
- else
- m_compositedWindows[parentWindow].childWindows.append(window);
+ m_windowStack.append(window);
notifyTopWindowChanged(window);
}
void QWasmCompositor::removeWindow(QWasmWindow *window)
{
- QWasmWindow *platformWindow = m_compositedWindows[window].parentWindow;
-
- if (platformWindow) {
- QWasmWindow *parentWindow = window;
- m_compositedWindows[parentWindow].childWindows.removeAll(window);
- }
-
m_windowStack.removeAll(window);
- m_compositedWindows.remove(window);
+ m_windowVisibility.remove(window);
m_requestUpdateWindows.remove(window);
if (!m_windowStack.isEmpty() && !QGuiApplication::focusWindow()) {
- auto lastWindow = m_windowStack.last();
- lastWindow->requestActivateWindow();
- notifyTopWindowChanged(lastWindow);
+ auto m_lastMouseTargetWindow = m_windowStack.last();
+ m_lastMouseTargetWindow->requestActivateWindow();
+ notifyTopWindowChanged(m_lastMouseTargetWindow);
}
}
void QWasmCompositor::setVisible(QWasmWindow *window, bool visible)
{
- QWasmCompositedWindow &compositedWindow = m_compositedWindows[window];
- if (compositedWindow.visible == visible)
+ const bool wasVisible = m_windowVisibility[window];
+ if (wasVisible == visible)
return;
- compositedWindow.visible = visible;
- compositedWindow.flushPending = true;
- if (visible)
- compositedWindow.damage = compositedWindow.window->geometry();
- else
- m_globalDamage = compositedWindow.window->geometry(); // repaint previously covered area.
+ m_windowVisibility[window] = visible;
+ if (!visible)
+ m_globalDamage = window->window()->geometry(); // repaint previously covered area.
requestUpdateWindow(window, QWasmCompositor::ExposeEventDelivery);
}
void QWasmCompositor::raise(QWasmWindow *window)
{
- if (m_compositedWindows.size() <= 1)
+ if (m_windowStack.size() <= 1)
return;
- QWasmCompositedWindow &compositedWindow = m_compositedWindows[window];
- compositedWindow.damage = compositedWindow.window->geometry();
m_windowStack.removeAll(window);
m_windowStack.append(window);
@@ -244,47 +216,31 @@ void QWasmCompositor::raise(QWasmWindow *window)
void QWasmCompositor::lower(QWasmWindow *window)
{
- if (m_compositedWindows.size() <= 1)
+ if (m_windowStack.size() <= 1)
return;
m_windowStack.removeAll(window);
m_windowStack.prepend(window);
- QWasmCompositedWindow &compositedWindow = m_compositedWindows[window];
- m_globalDamage = compositedWindow.window->geometry(); // repaint previously covered area.
+ m_globalDamage = window->window()->geometry(); // repaint previously covered area.
notifyTopWindowChanged(window);
}
-void QWasmCompositor::setParent(QWasmWindow *window, QWasmWindow *parent)
-{
- m_compositedWindows[window].parentWindow = parent;
-
- requestUpdate();
-}
-
int QWasmCompositor::windowCount() const
{
return m_windowStack.count();
}
-QWindow *QWasmCompositor::windowAt(QPoint globalPoint, int padding) const
+QWindow *QWasmCompositor::windowAt(QPoint targetPointInScreenCoords, int padding) const
{
- int index = m_windowStack.count() - 1;
- // qDebug() << "window at" << "point" << p << "window count" << index;
-
- while (index >= 0) {
- const QWasmCompositedWindow &compositedWindow = m_compositedWindows[m_windowStack.at(index)];
- //qDebug() << "windwAt testing" << compositedWindow.window <<
-
- QRect geometry = compositedWindow.window->windowFrameGeometry()
- .adjusted(-padding, -padding, padding, padding);
-
- if (compositedWindow.visible && geometry.contains(globalPoint))
- return m_windowStack.at(index)->window();
- --index;
- }
-
- return 0;
+ const auto found = std::find_if(m_windowStack.rbegin(), m_windowStack.rend(),
+ [this, padding, &targetPointInScreenCoords](const QWasmWindow* window) {
+ const QRect geometry = window->windowFrameGeometry()
+ .adjusted(-padding, -padding, padding, padding);
+
+ return m_windowVisibility[window] && geometry.contains(targetPointInScreenCoords);
+ });
+ return found != m_windowStack.rend() ? (*found)->window() : nullptr;
}
QWindow *QWasmCompositor::keyWindow() const
@@ -422,7 +378,7 @@ void QWasmCompositor::requestUpdateWindow(QWasmWindow *window, UpdateRequestDeli
requestUpdate();
}
-// Requests an upate/new frame using RequestAnimationFrame
+// Requests an update/new frame using RequestAnimationFrame
void QWasmCompositor::requestUpdate()
{
if (m_requestAnimationFrameId != -1)
@@ -655,7 +611,8 @@ void QWasmCompositor::drawItemPixmap(QPainter *painter, const QRect &rect, int a
QRect aligned = QRect(x, y, w, h);
QRect inter = aligned.intersected(rect);
- painter->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), inter.y() - aligned.y(), inter.width() * scale, inter.height() *scale);
+ painter->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(),
+ inter.y() - aligned.y(), inter.width() * scale, inter.height() *scale);
}
@@ -845,12 +802,8 @@ void QWasmCompositor::frame()
m_blitter->setRedBlueSwizzle(true);
for (QWasmWindow *window : qAsConst(m_windowStack)) {
- QWasmCompositedWindow &compositedWindow = m_compositedWindows[window];
-
- if (!compositedWindow.visible)
- continue;
-
- drawWindow(m_blitter.data(), screen(), window);
+ if (m_windowVisibility[window])
+ drawWindow(m_blitter.data(), screen(), window);
}
m_blitter->release();
@@ -859,70 +812,37 @@ void QWasmCompositor::frame()
m_context->swapBuffers(someWindow->window());
}
-void QWasmCompositor::resizeWindow(QWindow *window, QWasmCompositor::ResizeMode mode,
- QRect startRect, QPoint amount)
+void QWasmCompositor::WindowManipulation::resizeWindow(const QPoint& amount)
{
- if (mode == QWasmCompositor::ResizeNone)
- return;
-
- bool top = mode == QWasmCompositor::ResizeTopLeft ||
- mode == QWasmCompositor::ResizeTop ||
- mode == QWasmCompositor::ResizeTopRight;
-
- bool bottom = mode == QWasmCompositor::ResizeBottomLeft ||
- mode == QWasmCompositor::ResizeBottom ||
- mode == QWasmCompositor::ResizeBottomRight;
-
- bool left = mode == QWasmCompositor::ResizeLeft ||
- mode == QWasmCompositor::ResizeTopLeft ||
- mode == QWasmCompositor::ResizeBottomLeft;
-
- bool right = mode == QWasmCompositor::ResizeRight ||
- mode == QWasmCompositor::ResizeTopRight ||
- mode == QWasmCompositor::ResizeBottomRight;
-
- int x1 = startRect.left();
- int y1 = startRect.top();
- int x2 = startRect.right();
- int y2 = startRect.bottom();
-
- if (left)
- x1 += amount.x();
- if (top)
- y1 += amount.y();
- if (right)
- x2 += amount.x();
- if (bottom)
- y2 += amount.y();
-
- int w = x2-x1;
- int h = y2-y1;
-
- if (w < window->minimumWidth()) {
- if (left)
- x1 -= window->minimumWidth() - w;
-
- w = window->minimumWidth();
- }
-
- if (h < window->minimumHeight()) {
- if (top)
- y1 -= window->minimumHeight() - h;
-
- h = window->minimumHeight();
- }
-
- window->setGeometry(x1, y1, w, h);
+ const auto& minShrink = std::get<ResizeState>(m_state->operationSpecific).m_minShrink;
+ const auto& maxGrow = std::get<ResizeState>(m_state->operationSpecific).m_maxGrow;
+ const auto& resizeMode = std::get<ResizeState>(m_state->operationSpecific).m_resizeMode;
+
+ const QPoint cappedGrowVector(
+ std::min(maxGrow.x(), std::max(minShrink.x(),
+ (resizeMode & Left) ? -amount.x() : (resizeMode & Right) ? amount.x() : 0)),
+ std::min(maxGrow.y(), std::max(minShrink.y(),
+ (resizeMode & Top) ? -amount.y() : (resizeMode & Bottom) ? amount.y() : 0)));
+
+ const auto& initialBounds =
+ std::get<ResizeState>(m_state->operationSpecific).m_initialWindowBounds;
+ m_state->window->setGeometry(
+ initialBounds.adjusted(
+ (resizeMode & Left) ? -cappedGrowVector.x() : 0,
+ (resizeMode & Top) ? -cappedGrowVector.y() : 0,
+ (resizeMode & Right) ? cappedGrowVector.x() : 0,
+ (resizeMode & Bottom) ? cappedGrowVector.y() : 0
+ ));
}
void QWasmCompositor::notifyTopWindowChanged(QWasmWindow *window)
{
QWindow *modalWindow;
- bool blocked = QGuiApplicationPrivate::instance()->isWindowBlocked(window->window(), &modalWindow);
+ bool isTargetWindowBlocked = QGuiApplicationPrivate::instance()->isWindowBlocked(window->window(), &modalWindow);
- if (blocked) {
+ if (isTargetWindowBlocked) {
modalWindow->requestActivate();
- raise(static_cast<QWasmWindow*>(modalWindow->handle()));
+ raise(AsWasmWindow(modalWindow));
return;
}
@@ -945,12 +865,6 @@ int QWasmCompositor::keyboard_cb(int eventType, const EmscriptenKeyboardEvent *k
return static_cast<int>(wasmCompositor->processKeyboard(eventType, keyEvent));
}
-int QWasmCompositor::mouse_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
-{
- QWasmCompositor *compositor = (QWasmCompositor*)userData;
- return static_cast<int>(compositor->processMouse(eventType, mouseEvent));
-}
-
int QWasmCompositor::focus_cb(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData)
{
Q_UNUSED(eventType)
@@ -972,226 +886,280 @@ int QWasmCompositor::touchCallback(int eventType, const EmscriptenTouchEvent *to
return static_cast<int>(compositor->handleTouch(eventType, touchEvent));
}
-bool QWasmCompositor::processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent)
+bool QWasmCompositor::processPointer(const PointerEvent& event)
{
- QPoint targetPoint(mouseEvent->targetX, mouseEvent->targetY);
- QPoint globalPoint = screen()->geometry().topLeft() + targetPoint;
+ if (event.pointerType != PointerType::Mouse)
+ return false;
- QEvent::Type buttonEventType = QEvent::None;
- Qt::MouseButton button = Qt::NoButton;
- Qt::KeyboardModifiers modifiers = eventTranslator->translateMouseEventModifier(mouseEvent);
+ const QPoint targetPointInScreenCoords = screen()->geometry().topLeft() + event.point;
- QWindow *window2 = nullptr;
- if (resizeMode == QWasmCompositor::ResizeNone)
- window2 = screen()->compositor()->windowAt(globalPoint, 5);
+ QWindow *const targetWindow = ([this, &targetPointInScreenCoords]() -> QWindow * {
+ auto *targetWindow =
+ m_windowManipulation.operation() == WindowManipulation::Operation::None ?
+ screen()->compositor()->windowAt(targetPointInScreenCoords, 5) : nullptr;
- if (window2 == nullptr) {
- window2 = lastWindow;
- } else {
- lastWindow = window2;
- }
+ return targetWindow ? targetWindow : m_lastMouseTargetWindow.get();
+ })();
+ if (targetWindow)
+ m_lastMouseTargetWindow = targetWindow;
- QPoint localPoint = window2->mapFromGlobal(globalPoint);
- bool interior = window2->geometry().contains(globalPoint);
+ const QPoint pointInTargetWindowCoords = targetWindow->mapFromGlobal(targetPointInScreenCoords);
+ const bool pointerIsWithinTargetWindowBounds = targetWindow->geometry().contains(targetPointInScreenCoords);
+ const bool isTargetWindowBlocked = QGuiApplicationPrivate::instance()->isWindowBlocked(targetWindow);
- if (mouseInCanvas) {
- if (windowUnderMouse != window2 && interior) {
+ if (m_mouseInCanvas && m_windowUnderMouse != targetWindow && pointerIsWithinTargetWindowBounds) {
// delayed mouse enter
- enterWindow(window2, localPoint, globalPoint);
- windowUnderMouse = window2;
- }
+ enterWindow(targetWindow, pointInTargetWindowCoords, targetPointInScreenCoords);
+ m_windowUnderMouse = targetWindow;
}
- QWasmWindow *htmlWindow = static_cast<QWasmWindow*>(window2->handle());
- switch (eventType) {
- case EMSCRIPTEN_EVENT_MOUSEDOWN:
+ QWasmWindow *wasmTargetWindow = AsWasmWindow(targetWindow);
+ Qt::WindowStates windowState = targetWindow->windowState();
+ const bool isTargetWindowResizable = !windowState.testFlag(Qt::WindowMaximized) && !windowState.testFlag(Qt::WindowFullScreen);
+
+ switch (event.type) {
+ case EventType::PointerDown:
{
- button = QWasmEventTranslator::translateMouseButton(mouseEvent->button);
-
- if (window2)
- window2->requestActivate();
-
- pressedButtons.setFlag(button);
-
- pressedWindow = window2;
- buttonEventType = QEvent::MouseButtonPress;
-
- // button overview:
- // 0 = primary mouse button, usually left click
- // 1 = middle mouse button, usually mouse wheel
- // 2 = right mouse button, usually right click
- // from: https://w3c.github.io/uievents/#dom-mouseevent-button
- if (mouseEvent->button == 0) {
- if (!(htmlWindow->m_windowState & Qt::WindowFullScreen) && !(htmlWindow->m_windowState & Qt::WindowMaximized)) {
- if (htmlWindow && window2->flags().testFlag(Qt::WindowTitleHint) && htmlWindow->isPointOnTitle(globalPoint))
- draggedWindow = window2;
- else if (htmlWindow && htmlWindow->isPointOnResizeRegion(globalPoint)) {
- draggedWindow = window2;
- resizeMode = htmlWindow->resizeModeAtPoint(globalPoint);
- resizePoint = globalPoint;
- resizeStartRect = window2->geometry();
- }
- }
- }
+ if (targetWindow)
+ targetWindow->requestActivate();
- htmlWindow->injectMousePressed(localPoint, globalPoint, button, modifiers);
+ m_pressedWindow = targetWindow;
+
+ m_windowManipulation.onPointerDown(event, targetWindow);
+
+ wasmTargetWindow->injectMousePressed(pointInTargetWindowCoords, targetPointInScreenCoords, event.mouseButton, event.modifiers);
break;
}
- case EMSCRIPTEN_EVENT_MOUSEUP:
+ case EventType::PointerUp:
{
- button = QWasmEventTranslator::translateMouseButton(mouseEvent->button);
- pressedButtons.setFlag(button, false);
- buttonEventType = QEvent::MouseButtonRelease;
- QWasmWindow *oldWindow = nullptr;
-
- if (mouseEvent->button == 0 && pressedWindow) {
- oldWindow = static_cast<QWasmWindow*>(pressedWindow->handle());
- pressedWindow = nullptr;
- }
+ m_windowManipulation.onPointerUp(event);
- if (draggedWindow && pressedButtons.testFlag(Qt::NoButton)) {
- draggedWindow = nullptr;
- resizeMode = QWasmCompositor::ResizeNone;
+ if (m_pressedWindow) {
+ // Always deliver the released event to the same window that was pressed
+ AsWasmWindow(m_pressedWindow)->injectMouseReleased(pointInTargetWindowCoords, targetPointInScreenCoords, event.mouseButton, event.modifiers);
+ if (event.mouseButton == Qt::MouseButton::LeftButton)
+ m_pressedWindow = nullptr;
+ } else {
+ wasmTargetWindow->injectMouseReleased(pointInTargetWindowCoords, targetPointInScreenCoords, event.mouseButton, event.modifiers);
}
-
- if (oldWindow)
- oldWindow->injectMouseReleased(localPoint, globalPoint, button, modifiers);
- else
- htmlWindow->injectMouseReleased(localPoint, globalPoint, button, modifiers);
break;
}
- case EMSCRIPTEN_EVENT_MOUSEMOVE: // drag event
+ case EventType::PointerMove:
{
- buttonEventType = QEvent::MouseMove;
-
- if (htmlWindow && pressedButtons.testFlag(Qt::NoButton)) {
-
- Qt::WindowStates windowState = htmlWindow->window()->windowState();
- bool isResizable = !(windowState.testFlag(Qt::WindowMaximized) || windowState.testFlag(Qt::WindowFullScreen));
- bool isOnResizeRegion = htmlWindow->isPointOnResizeRegion(globalPoint);
+ if (wasmTargetWindow && event.mouseButtons.testFlag(Qt::NoButton)) {
+ const bool isOnResizeRegion = wasmTargetWindow->isPointOnResizeRegion(targetPointInScreenCoords);
- if (isResizable && isOnResizeRegion) {
- QCursor resizingCursor = eventTranslator->cursorForMode(htmlWindow->resizeModeAtPoint(globalPoint));
+ if (isTargetWindowResizable && isOnResizeRegion && !isTargetWindowBlocked) {
+ const QCursor resizingCursor = QWasmEventTranslator::cursorForMode(
+ wasmTargetWindow->resizeModeAtPoint(targetPointInScreenCoords));
- if (resizingCursor != window2->cursor()) {
- isCursorOverridden = true;
- QWasmCursor::setOverrideWasmCursor(&resizingCursor, window2->screen());
- }
- } else { // off resizing area
- if (isCursorOverridden) {
- isCursorOverridden = false;
- QWasmCursor::clearOverrideWasmCursor(window2->screen());
+ if (resizingCursor != targetWindow->cursor()) {
+ m_isResizeCursorDisplayed = true;
+ QWasmCursor::setOverrideWasmCursor(resizingCursor, targetWindow->screen());
}
+ } else if (m_isResizeCursorDisplayed) { // off resizing area
+ m_isResizeCursorDisplayed = false;
+ QWasmCursor::clearOverrideWasmCursor(targetWindow->screen());
}
}
- if (!(htmlWindow->m_windowState & Qt::WindowFullScreen) && !(htmlWindow->m_windowState & Qt::WindowMaximized)) {
- if (resizeMode == QWasmCompositor::ResizeNone && draggedWindow) {
- draggedWindow->setX(draggedWindow->x() + mouseEvent->movementX);
- draggedWindow->setY(draggedWindow->y() + mouseEvent->movementY);
- }
-
- if (resizeMode != QWasmCompositor::ResizeNone && !(htmlWindow->m_windowState & Qt::WindowFullScreen)) {
- QPoint delta = QPoint(mouseEvent->targetX, mouseEvent->targetY) - resizePoint;
- resizeWindow(draggedWindow, resizeMode, resizeStartRect, delta);
- }
- }
+ m_windowManipulation.onPointerMove(event);
break;
}
- case EMSCRIPTEN_EVENT_MOUSEENTER:
- processMouseEnter(mouseEvent);
+ case EventType::PointerEnter:
+ processMouseEnter(nullptr);
+ break;
+ case EventType::PointerLeave:
+ processMouseLeave();
break;
- case EMSCRIPTEN_EVENT_MOUSELEAVE:
- processMouseLeave();
+ default:
break;
- default: break;
};
- if (!interior && pressedButtons.testFlag(Qt::NoButton)) {
- leaveWindow(lastWindow);
+ if (!pointerIsWithinTargetWindowBounds && event.mouseButtons.testFlag(Qt::NoButton)) {
+ leaveWindow(m_lastMouseTargetWindow);
}
- if (!window2 && buttonEventType == QEvent::MouseButtonRelease) {
- window2 = lastWindow;
- lastWindow = nullptr;
- interior = true;
+ const bool eventAccepted = deliverEventToTarget(event, targetWindow);
+ if (!eventAccepted && event.type == EventType::PointerDown)
+ QGuiApplicationPrivate::instance()->closeAllPopups();
+ return eventAccepted;
+}
+
+bool QWasmCompositor::deliverEventToTarget(const PointerEvent &event, QWindow *eventTarget)
+{
+ const QPoint pointInScreenCoords = screen()->geometry().topLeft() + event.point;
+ const QPoint targetPointClippedToScreen(
+ std::max(screen()->geometry().left(),
+ std::min(screen()->geometry().right(), pointInScreenCoords.x())),
+ std::max(screen()->geometry().top(),
+ std::min(screen()->geometry().bottom(), pointInScreenCoords.y())));
+
+ bool deliveringToPreviouslyClickedWindow = false;
+
+ if (!eventTarget) {
+ if (event.type != EventType::PointerUp || !m_lastMouseTargetWindow)
+ return false;
+
+ eventTarget = m_lastMouseTargetWindow;
+ m_lastMouseTargetWindow = nullptr;
+ deliveringToPreviouslyClickedWindow = true;
}
- bool accepted = false;
- if (window2 && interior) {
- accepted = QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(
- window2, QWasmIntegration::getTimestamp(), localPoint, globalPoint, pressedButtons, button, buttonEventType, modifiers);
+
+ WindowArea windowArea = WindowArea::Client;
+ if (!eventTarget->geometry().contains(targetPointClippedToScreen)
+ && !deliveringToPreviouslyClickedWindow) {
+ if (!eventTarget->frameGeometry().contains(targetPointClippedToScreen))
+ return false;
+ windowArea = WindowArea::NonClient;
}
- if (eventType == EMSCRIPTEN_EVENT_MOUSEDOWN && !accepted)
- QGuiApplicationPrivate::instance()->closeAllPopups();
- return accepted;
+ const QEvent::Type eventType =
+ MouseEvent::mouseEventTypeFromEventType(event.type, windowArea);
+
+ return eventType != QEvent::None &&
+ QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(
+ eventTarget, QWasmIntegration::getTimestamp(),
+ eventTarget->mapFromGlobal(targetPointClippedToScreen),
+ targetPointClippedToScreen, event.mouseButtons, event.mouseButton,
+ eventType, event.modifiers);
+}
+
+QWasmCompositor::WindowManipulation::WindowManipulation(QWasmScreen *screen)
+ : m_screen(screen)
+{
+ Q_ASSERT(!!screen);
+}
+
+QWasmCompositor::WindowManipulation::Operation QWasmCompositor::WindowManipulation::operation() const
+{
+ if (!m_state)
+ return Operation::None;
+
+ return std::holds_alternative<MoveState>(m_state->operationSpecific)
+ ? Operation::Move : Operation::Resize;
+}
+
+void QWasmCompositor::WindowManipulation::onPointerDown(
+ const PointerEvent& event, QWindow* windowAtPoint)
+{
+ // Only one operation at a time.
+ if (operation() != Operation::None)
+ return;
+
+ if (event.mouseButton != Qt::MouseButton::LeftButton)
+ return;
+
+ const bool isTargetWindowResizable =
+ !windowAtPoint->windowStates().testFlag(Qt::WindowMaximized) &&
+ !windowAtPoint->windowStates().testFlag(Qt::WindowFullScreen);
+ if (!isTargetWindowResizable)
+ return;
+
+ const bool isTargetWindowBlocked =
+ QGuiApplicationPrivate::instance()->isWindowBlocked(windowAtPoint);
+ if (isTargetWindowBlocked)
+ return;
+
+ const auto pointInScreenCoords = m_screen->geometry().topLeft() + event.point;
+
+ std::unique_ptr<std::variant<ResizeState, MoveState>> operationSpecific;
+ if (AsWasmWindow(windowAtPoint)->isPointOnTitle(pointInScreenCoords)) {
+ operationSpecific = std::make_unique<std::variant<ResizeState, MoveState>>(MoveState {
+ .m_lastPointInScreenCoords = pointInScreenCoords
+ });
+ } else if (AsWasmWindow(windowAtPoint)->isPointOnResizeRegion(pointInScreenCoords)) {
+ operationSpecific = std::make_unique<std::variant<ResizeState, MoveState>>(ResizeState {
+ .m_resizeMode = AsWasmWindow(windowAtPoint)->resizeModeAtPoint(pointInScreenCoords),
+ .m_originInScreenCoords = pointInScreenCoords,
+ .m_initialWindowBounds = windowAtPoint->geometry(),
+ .m_minShrink = QPoint(windowAtPoint->minimumWidth() - windowAtPoint->geometry().width(),
+ windowAtPoint->minimumHeight() - windowAtPoint->geometry().height()),
+ .m_maxGrow = QPoint(
+ windowAtPoint->maximumWidth() - windowAtPoint->geometry().width(),
+ windowAtPoint->maximumHeight() - windowAtPoint->geometry().height()),
+ });
+ } else {
+ return;
+ }
+
+ m_state.reset(new OperationState{
+ .pointerId = event.pointerId,
+ .window = windowAtPoint,
+ .operationSpecific = std::move(*operationSpecific),
+ });
+
+ m_screen->canvas().call<void>("setPointerCapture", event.pointerId);
}
-bool QWasmCompositor::processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent)
+void QWasmCompositor::WindowManipulation::onPointerMove(
+ const PointerEvent& event)
{
- Qt::Key qtKey;
- QString keyText;
- QEvent::Type keyType = QEvent::None;
- switch (eventType) {
- case EMSCRIPTEN_EVENT_KEYPRESS:
- case EMSCRIPTEN_EVENT_KEYDOWN: // down
- keyType = QEvent::KeyPress;
- keyText = this->eventTranslator->getKeyText(keyEvent);
- qtKey = this->eventTranslator->getKey(keyEvent);
+ if (operation() == Operation::None || event.pointerId != m_state->pointerId)
+ return;
+
+ switch (operation()) {
+ case Operation::Move: {
+ const QPoint targetPointClippedToScreen =
+ m_screen->translateAndClipGlobalPoint(event.point);
+ const QPoint difference = targetPointClippedToScreen -
+ std::get<MoveState>(m_state->operationSpecific).m_lastPointInScreenCoords;
+
+ std::get<MoveState>(m_state->operationSpecific).m_lastPointInScreenCoords = targetPointClippedToScreen;
+
+ m_state->window->setPosition(m_state->window->position() + difference);
break;
- case EMSCRIPTEN_EVENT_KEYUP: // up
- keyType = QEvent::KeyRelease;
- this->eventTranslator->setStickyDeadKey(keyEvent);
+ }
+ case Operation::Resize: {
+ const auto pointInScreenCoords = m_screen->geometry().topLeft() + event.point;
+ resizeWindow(pointInScreenCoords -
+ std::get<ResizeState>(m_state->operationSpecific).m_originInScreenCoords);
break;
- default:
+ }
+ case Operation::None:
+ Q_ASSERT(0);
break;
- };
+ }
+}
- if (keyType == QEvent::None)
- return 0;
+void QWasmCompositor::WindowManipulation::onPointerUp(const PointerEvent& event)
+{
+ if (operation() == Operation::None || event.mouseButtons != 0 || event.pointerId != m_state->pointerId)
+ return;
- QFlags<Qt::KeyboardModifier> modifiers = eventTranslator->translateKeyboardEventModifier(keyEvent);
+ m_state.reset();
+ m_screen->canvas().call<void>("releasePointerCapture", event.pointerId);
+}
- // Clipboard fallback path: cut/copy/paste are handled by clipboard event
- // handlers if direct clipboard access is not available.
- if (!QWasmIntegration::get()->getWasmClipboard()->hasClipboardApi && modifiers & Qt::ControlModifier &&
- (qtKey == Qt::Key_X || qtKey == Qt::Key_C || qtKey == Qt::Key_V)) {
- if (qtKey == Qt::Key_V) {
- QWasmIntegration::get()->getWasmClipboard()->isPaste = true;
- }
- return false;
- }
+bool QWasmCompositor::processKeyboard(int eventType, const EmscriptenKeyboardEvent *emKeyEvent)
+{
+ Q_ASSERT(eventType == EMSCRIPTEN_EVENT_KEYDOWN || eventType == EMSCRIPTEN_EVENT_KEYUP);
- bool accepted = false;
+ auto translatedEvent = m_eventTranslator->translateKeyEvent(eventType, emKeyEvent);
- if (keyType == QEvent::KeyPress &&
- modifiers.testFlag(Qt::ControlModifier)
- && qtKey == Qt::Key_V) {
- QWasmIntegration::get()->getWasmClipboard()->isPaste = true;
- accepted = false; // continue on to event
- } else {
- if (keyText.isEmpty())
- keyText = QString(keyEvent->key);
- if (keyText.size() > 1)
- keyText.clear();
- accepted = QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(
- 0, keyType, qtKey, modifiers, keyText);
- }
- if (keyType == QEvent::KeyPress &&
- modifiers.testFlag(Qt::ControlModifier)
- && qtKey == Qt::Key_C) {
- QWasmIntegration::get()->getWasmClipboard()->isPaste = false;
- accepted = false; // continue on to event
+ const QFlags<Qt::KeyboardModifier> modifiers = KeyboardModifier::getForEvent(*emKeyEvent);
+
+ // Clipboard path: cut/copy/paste are handled by clipboard event or direct clipboard access.
+ if (translatedEvent.type == QEvent::KeyPress && modifiers.testFlag(Qt::ControlModifier)
+ && (translatedEvent.key == Qt::Key_X || translatedEvent.key == Qt::Key_V
+ || translatedEvent.key == Qt::Key_C)) {
+ QWasmIntegration::get()->getWasmClipboard()->isPaste = translatedEvent.key == Qt::Key_V;
+ return false; // continue on to event
}
- return accepted;
+ if (translatedEvent.text.isEmpty())
+ translatedEvent.text = QString(emKeyEvent->key);
+ if (translatedEvent.text.size() > 1)
+ translatedEvent.text.clear();
+ return QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(
+ 0, translatedEvent.type, translatedEvent.key, modifiers, translatedEvent.text);
}
bool QWasmCompositor::processWheel(int eventType, const EmscriptenWheelEvent *wheelEvent)
{
Q_UNUSED(eventType);
- EmscriptenMouseEvent mouseEvent = wheelEvent->mouse;
+ const EmscriptenMouseEvent* mouseEvent = &wheelEvent->mouse;
int scrollFactor = 0;
switch (wheelEvent->deltaMode) {
@@ -1208,14 +1176,14 @@ bool QWasmCompositor::processWheel(int eventType, const EmscriptenWheelEvent *wh
scrollFactor = -scrollFactor; // Web scroll deltas are inverted from Qt deltas.
- Qt::KeyboardModifiers modifiers = eventTranslator->translateMouseEventModifier(&mouseEvent);
- QPoint targetPoint(mouseEvent.targetX, mouseEvent.targetY);
- QPoint globalPoint = screen()->geometry().topLeft() + targetPoint;
+ Qt::KeyboardModifiers modifiers = KeyboardModifier::getForEvent(*mouseEvent);
+ QPoint targetPointInCanvasCoords(mouseEvent->targetX, mouseEvent->targetY);
+ QPoint targetPointInScreenCoords = screen()->geometry().topLeft() + targetPointInCanvasCoords;
- QWindow *window2 = screen()->compositor()->windowAt(globalPoint, 5);
- if (!window2)
+ QWindow *targetWindow = screen()->compositor()->windowAt(targetPointInScreenCoords, 5);
+ if (!targetWindow)
return 0;
- QPoint localPoint = window2->mapFromGlobal(globalPoint);
+ QPoint pointInTargetWindowCoords = targetWindow->mapFromGlobal(targetPointInScreenCoords);
QPoint pixelDelta;
@@ -1225,8 +1193,8 @@ bool QWasmCompositor::processWheel(int eventType, const EmscriptenWheelEvent *wh
QPoint angleDelta = pixelDelta; // FIXME: convert from pixels?
bool accepted = QWindowSystemInterface::handleWheelEvent(
- window2, QWasmIntegration::getTimestamp(), localPoint,
- globalPoint, pixelDelta, angleDelta, modifiers,
+ targetWindow, QWasmIntegration::getTimestamp(), pointInTargetWindowCoords,
+ targetPointInScreenCoords, pixelDelta, angleDelta, modifiers,
Qt::NoScrollPhase, Qt::MouseEventNotSynthesized,
g_scrollingInvertedFromDevice);
return accepted;
@@ -1236,17 +1204,17 @@ int QWasmCompositor::handleTouch(int eventType, const EmscriptenTouchEvent *touc
{
QList<QWindowSystemInterface::TouchPoint> touchPointList;
touchPointList.reserve(touchEvent->numTouches);
- QWindow *window2;
+ QWindow *targetWindow;
for (int i = 0; i < touchEvent->numTouches; i++) {
const EmscriptenTouchPoint *touches = &touchEvent->touches[i];
- QPoint targetPoint(touches->targetX, touches->targetY);
- QPoint globalPoint = screen()->geometry().topLeft() + targetPoint;
+ QPoint targetPointInCanvasCoords(touches->targetX, touches->targetY);
+ QPoint targetPointInScreenCoords = screen()->geometry().topLeft() + targetPointInCanvasCoords;
- window2 = this->screen()->compositor()->windowAt(globalPoint, 5);
- if (window2 == nullptr)
+ targetWindow = screen()->compositor()->windowAt(targetPointInScreenCoords, 5);
+ if (targetWindow == nullptr)
continue;
QWindowSystemInterface::TouchPoint touchPoint;
@@ -1255,41 +1223,41 @@ int QWasmCompositor::handleTouch(int eventType, const EmscriptenTouchEvent *touc
touchPoint.id = touches->identifier;
touchPoint.pressure = 1.0;
- touchPoint.area.moveCenter(globalPoint);
+ touchPoint.area.moveCenter(targetPointInScreenCoords);
- const auto tp = pressedTouchIds.constFind(touchPoint.id);
- if (tp != pressedTouchIds.constEnd())
+ const auto tp = m_pressedTouchIds.constFind(touchPoint.id);
+ if (tp != m_pressedTouchIds.constEnd())
touchPoint.normalPosition = tp.value();
- QPointF localPoint = QPointF(window2->mapFromGlobal(globalPoint));
- QPointF normalPosition(localPoint.x() / window2->width(),
- localPoint.y() / window2->height());
+ QPointF pointInTargetWindowCoords = QPointF(targetWindow->mapFromGlobal(targetPointInScreenCoords));
+ QPointF normalPosition(pointInTargetWindowCoords.x() / targetWindow->width(),
+ pointInTargetWindowCoords.y() / targetWindow->height());
const bool stationaryTouchPoint = (normalPosition == touchPoint.normalPosition);
touchPoint.normalPosition = normalPosition;
switch (eventType) {
case EMSCRIPTEN_EVENT_TOUCHSTART:
- if (tp != pressedTouchIds.constEnd()) {
+ if (tp != m_pressedTouchIds.constEnd()) {
touchPoint.state = (stationaryTouchPoint
? QEventPoint::State::Stationary
: QEventPoint::State::Updated);
} else {
touchPoint.state = QEventPoint::State::Pressed;
}
- pressedTouchIds.insert(touchPoint.id, touchPoint.normalPosition);
+ m_pressedTouchIds.insert(touchPoint.id, touchPoint.normalPosition);
break;
case EMSCRIPTEN_EVENT_TOUCHEND:
touchPoint.state = QEventPoint::State::Released;
- pressedTouchIds.remove(touchPoint.id);
+ m_pressedTouchIds.remove(touchPoint.id);
break;
case EMSCRIPTEN_EVENT_TOUCHMOVE:
touchPoint.state = (stationaryTouchPoint
? QEventPoint::State::Stationary
: QEventPoint::State::Updated);
- pressedTouchIds.insert(touchPoint.id, touchPoint.normalPosition);
+ m_pressedTouchIds.insert(touchPoint.id, touchPoint.normalPosition);
break;
default:
break;
@@ -1298,37 +1266,40 @@ int QWasmCompositor::handleTouch(int eventType, const EmscriptenTouchEvent *touc
touchPointList.append(touchPoint);
}
- QFlags<Qt::KeyboardModifier> keyModifier = eventTranslator->translateTouchEventModifier(touchEvent);
+ QFlags<Qt::KeyboardModifier> keyModifier = KeyboardModifier::getForEvent(*touchEvent);
bool accepted = false;
if (eventType == EMSCRIPTEN_EVENT_TOUCHCANCEL)
- accepted = QWindowSystemInterface::handleTouchCancelEvent(window2, QWasmIntegration::getTimestamp(), touchDevice, keyModifier);
+ accepted = QWindowSystemInterface::handleTouchCancelEvent(targetWindow, QWasmIntegration::getTimestamp(), m_touchDevice.get(), keyModifier);
else
accepted = QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(
- window2, QWasmIntegration::getTimestamp(), touchDevice, touchPointList, keyModifier);
+ targetWindow, QWasmIntegration::getTimestamp(), m_touchDevice.get(), touchPointList, keyModifier);
return static_cast<int>(accepted);
}
void QWasmCompositor::leaveWindow(QWindow *window)
{
- windowUnderMouse = nullptr;
+ m_windowUnderMouse = nullptr;
QWindowSystemInterface::handleLeaveEvent<QWindowSystemInterface::SynchronousDelivery>(window);
}
-void QWasmCompositor::enterWindow(QWindow *window, const QPoint &localPoint, const QPoint &globalPoint)
+
+void QWasmCompositor::enterWindow(QWindow *window, const QPoint &pointInTargetWindowCoords, const QPoint &targetPointInScreenCoords)
{
- QWindowSystemInterface::handleEnterEvent<QWindowSystemInterface::SynchronousDelivery>(window, localPoint, globalPoint);
+ QWindowSystemInterface::handleEnterEvent<QWindowSystemInterface::SynchronousDelivery>(window, pointInTargetWindowCoords, targetPointInScreenCoords);
}
+
bool QWasmCompositor::processMouseEnter(const EmscriptenMouseEvent *mouseEvent)
{
Q_UNUSED(mouseEvent)
// mouse has entered the canvas area
- mouseInCanvas = true;
+ m_mouseInCanvas = true;
return true;
}
+
bool QWasmCompositor::processMouseLeave()
{
- mouseInCanvas = false;
+ m_mouseInCanvas = false;
return true;
}
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h
index 29a0f02267..c883fc310d 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.h
+++ b/src/plugins/platforms/wasm/qwasmcompositor.h
@@ -11,6 +11,7 @@
#include <QtGui/qpalette.h>
#include <QtGui/qpainter.h>
#include <QtGui/qinputdevice.h>
+#include <QtCore/private/qstdweb_p.h>
#include <QPointer>
#include <QPointingDevice>
@@ -21,25 +22,13 @@
QT_BEGIN_NAMESPACE
+struct PointerEvent;
class QWasmWindow;
class QWasmScreen;
class QOpenGLContext;
class QOpenGLTexture;
class QWasmEventTranslator;
-class QWasmCompositedWindow
-{
-public:
- QWasmCompositedWindow();
-
- QWasmWindow *window;
- QWasmWindow *parentWindow;
- QRegion damage;
- bool flushPending;
- bool visible;
- QList<QWasmWindow *> childWindows;
-};
-
class QWasmCompositor : public QObject
{
Q_OBJECT
@@ -69,16 +58,23 @@ public:
};
Q_DECLARE_FLAGS(StateFlags, QWasmStateFlag)
+ enum ResizeDimension {
+ Left = 1,
+ Right = 1 << 1,
+ Top = 1 << 2,
+ Bottom = 1 << 3
+ };
+
enum ResizeMode {
ResizeNone,
- ResizeTopLeft,
- ResizeTop,
- ResizeTopRight,
- ResizeRight,
- ResizeBottomRight,
- ResizeBottom,
- ResizeBottomLeft,
- ResizeLeft
+ ResizeTopLeft = Top | Left,
+ ResizeTop = Top,
+ ResizeTopRight = Top | Right,
+ ResizeRight = Right,
+ ResizeBottomRight = Bottom | Right,
+ ResizeBottom = Bottom,
+ ResizeBottomLeft = Bottom | Left,
+ ResizeLeft = Left
};
struct QWasmTitleBarOptions {
@@ -99,13 +95,12 @@ public:
void setEnabled(bool enabled);
- void addWindow(QWasmWindow *window, QWasmWindow *parentWindow = nullptr);
+ void addWindow(QWasmWindow *window);
void removeWindow(QWasmWindow *window);
void setVisible(QWasmWindow *window, bool visible);
void raise(QWasmWindow *window);
void lower(QWasmWindow *window);
- void setParent(QWasmWindow *window, QWasmWindow *parent);
int windowCount() const;
@@ -125,11 +120,9 @@ public:
void deliverUpdateRequests();
void deliverUpdateRequest(QWasmWindow *window, UpdateRequestDeliveryType updateType);
void handleBackingStoreFlush();
- bool processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent);
bool processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent);
bool processWheel(int eventType, const EmscriptenWheelEvent *wheelEvent);
int handleTouch(int eventType, const EmscriptenTouchEvent *touchEvent);
- void resizeWindow(QWindow *window, QWasmCompositor::ResizeMode mode, QRect startRect, QPoint amount);
bool processMouseEnter(const EmscriptenMouseEvent *mouseEvent);
bool processMouseLeave();
@@ -140,65 +133,108 @@ private slots:
void frame();
private:
+ class WindowManipulation {
+ public:
+ enum class Operation {
+ None,
+ Move,
+ Resize,
+ };
+
+ WindowManipulation(QWasmScreen* screen);
+
+ void onPointerDown(const PointerEvent& event, QWindow* windowAtPoint);
+ void onPointerMove(const PointerEvent& event);
+ void onPointerUp(const PointerEvent& event);
+
+ Operation operation() const;
+
+ private:
+ struct ResizeState {
+ ResizeMode m_resizeMode;
+ QPoint m_originInScreenCoords;
+ QRect m_initialWindowBounds;
+ const QPoint m_minShrink;
+ const QPoint m_maxGrow;
+ };
+ struct MoveState {
+ QPoint m_lastPointInScreenCoords;
+ };
+ struct OperationState
+ {
+ int pointerId;
+ QPointer<QWindow> window;
+ std::variant<ResizeState, MoveState> operationSpecific;
+ };
+
+ void resizeWindow(const QPoint& amount);
+
+ QWasmScreen *m_screen;
+
+ std::unique_ptr<OperationState> m_state;
+ };
+
void notifyTopWindowChanged(QWasmWindow *window);
void drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
void drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
void blit(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, const QOpenGLTexture *texture, QRect targetGeometry);
void drawWindowDecorations(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
- void drwPanelButton();
+
+ static QPalette makeWindowPalette();
+
+ void drawFrameWindow(QWasmFrameOptions options, QPainter *painter);
+ void drawTitlebarWindow(QWasmTitleBarOptions options, QPainter *painter);
+ void drawShadePanel(QWasmTitleBarOptions options, QPainter *painter);
+ void drawItemPixmap(QPainter *painter, const QRect &rect,
+ int alignment, const QPixmap &pixmap) const;
+
+ static int keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData);
+ static int focus_cb(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData);
+ static int wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData);
+
+ bool processPointer(const PointerEvent& event);
+ bool deliverEventToTarget(const PointerEvent& event, QWindow *eventTarget);
+
+ static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
+
+ WindowManipulation m_windowManipulation;
QScopedPointer<QOpenGLContext> m_context;
QScopedPointer<QOpenGLTextureBlitter> m_blitter;
- QHash<QWasmWindow *, QWasmCompositedWindow> m_compositedWindows;
+ QHash<const QWasmWindow *, bool> m_windowVisibility;
QList<QWasmWindow *> m_windowStack;
QRegion m_globalDamage; // damage caused by expose, window close, etc.
- bool m_needComposit;
- bool m_inFlush;
- bool m_inResize;
- bool m_isEnabled;
+ bool m_needComposit = false;
+ bool m_inFlush = false;
+ bool m_isEnabled = true;
QSize m_targetSize;
- qreal m_targetDevicePixelRatio;
+ qreal m_targetDevicePixelRatio = 1;
QMap<QWasmWindow *, UpdateRequestDeliveryType> m_requestUpdateWindows;
bool m_requestUpdateAllWindows = false;
int m_requestAnimationFrameId = -1;
bool m_inDeliverUpdateRequest = false;
- QPointer<QWindow> draggedWindow;
- QPointer<QWindow> pressedWindow;
- QPointer<QWindow> lastWindow;
- Qt::MouseButtons pressedButtons;
+ QPointer<QWindow> m_pressedWindow;
+ QPointer<QWindow> m_lastMouseTargetWindow;
- QWasmCompositor::ResizeMode resizeMode;
- QPoint resizePoint;
- QRect resizeStartRect;
- QPointingDevice *touchDevice;
-
- QMap <int, QPointF> pressedTouchIds;
-
- QCursor overriddenCursor;
- bool isCursorOverridden = false;
-
- static QPalette makeWindowPalette();
+ std::unique_ptr<qstdweb::EventCallback> m_pointerDownCallback;
+ std::unique_ptr<qstdweb::EventCallback> m_pointerMoveCallback;
+ std::unique_ptr<qstdweb::EventCallback> m_pointerUpCallback;
+ std::unique_ptr<qstdweb::EventCallback> m_pointerLeaveCallback;
+ std::unique_ptr<qstdweb::EventCallback> m_pointerEnterCallback;
- void drawFrameWindow(QWasmFrameOptions options, QPainter *painter);
- void drawTitlebarWindow(QWasmTitleBarOptions options, QPainter *painter);
- void drawShadePanel(QWasmTitleBarOptions options, QPainter *painter);
- void drawItemPixmap(QPainter *painter, const QRect &rect,
- int alignment, const QPixmap &pixmap) const;
+ std::unique_ptr<QPointingDevice> m_touchDevice;
- static int keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData);
- static int mouse_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
- static int focus_cb(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData);
- static int wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData);
+ QMap <int, QPointF> m_pressedTouchIds;
- static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
+ bool m_isResizeCursorDisplayed = false;
- QWasmEventTranslator *eventTranslator;
+ std::unique_ptr<QWasmEventTranslator> m_eventTranslator;
- bool mouseInCanvas;
- QPointer<QWindow> windowUnderMouse;
+ bool m_mouseInCanvas = false;
+ QPointer<QWindow> m_windowUnderMouse;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QWasmCompositor::SubControls)
diff --git a/src/plugins/platforms/wasm/qwasmcursor.cpp b/src/plugins/platforms/wasm/qwasmcursor.cpp
index 199fc1bf00..f954e005ce 100644
--- a/src/plugins/platforms/wasm/qwasmcursor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcursor.cpp
@@ -11,6 +11,7 @@
#include <emscripten/emscripten.h>
#include <emscripten/bind.h>
+QT_BEGIN_NAMESPACE
using namespace emscripten;
void QWasmCursor::changeCursor(QCursor *windowCursor, QWindow *window)
@@ -122,10 +123,10 @@ void QWasmCursor::setWasmCursor(QScreen *screen, const QByteArray &name)
canvasStyle.set("cursor", val(name.constData()));
}
-void QWasmCursor::setOverrideWasmCursor(QCursor *windowCursor, QScreen *screen)
+void QWasmCursor::setOverrideWasmCursor(const QCursor &windowCursor, QScreen *screen)
{
QWasmCursor *wCursor = static_cast<QWasmCursor *>(QWasmScreen::get(screen)->cursor());
- wCursor->setWasmCursor(screen, wCursor->cursorShapeToHtml(windowCursor->shape()));
+ wCursor->setWasmCursor(screen, wCursor->cursorShapeToHtml(windowCursor.shape()));
}
void QWasmCursor::clearOverrideWasmCursor(QScreen *screen)
@@ -133,3 +134,5 @@ void QWasmCursor::clearOverrideWasmCursor(QScreen *screen)
QWasmCursor *wCursor = static_cast<QWasmCursor *>(QWasmScreen::get(screen)->cursor());
wCursor->setWasmCursor(screen, wCursor->htmlCursorName);
}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmcursor.h b/src/plugins/platforms/wasm/qwasmcursor.h
index 1fad7475e0..4a5cb23bf4 100644
--- a/src/plugins/platforms/wasm/qwasmcursor.h
+++ b/src/plugins/platforms/wasm/qwasmcursor.h
@@ -5,6 +5,7 @@
#define QWASMCURSOR_H
#include <qpa/qplatformcursor.h>
+QT_BEGIN_NAMESPACE
class QWasmCursor : public QPlatformCursor
{
@@ -12,11 +13,13 @@ public:
void changeCursor(QCursor *windowCursor, QWindow *window) override;
QByteArray cursorShapeToHtml(Qt::CursorShape shape);
- static void setOverrideWasmCursor(QCursor *windowCursor, QScreen *screen);
+ static void setOverrideWasmCursor(const QCursor &windowCursor, QScreen *screen);
static void clearOverrideWasmCursor(QScreen *screen);
private:
QByteArray htmlCursorName = "default";
void setWasmCursor(QScreen *screen, const QByteArray &name);
};
+QT_END_NAMESPACE
+
#endif
diff --git a/src/plugins/platforms/wasm/qwasmdrag.cpp b/src/plugins/platforms/wasm/qwasmdrag.cpp
index c87e4ce7c2..c2b50e4356 100644
--- a/src/plugins/platforms/wasm/qwasmdrag.cpp
+++ b/src/plugins/platforms/wasm/qwasmdrag.cpp
@@ -64,8 +64,7 @@ static void dropEvent(val event)
if (wasmDrag->m_mimeData)
delete wasmDrag->m_mimeData;
wasmDrag->m_mimeData = new QMimeData;
- int button = event["button"].as<int>();
- wasmDrag->m_qButton = QWasmEventTranslator::translateMouseButton(button);
+ wasmDrag->m_qButton = MouseEvent::buttonFromWeb(event["button"].as<int>());
wasmDrag->m_keyModifiers = Qt::NoModifier;
if (event["altKey"].as<bool>())
diff --git a/src/plugins/platforms/wasm/qwasmevent.cpp b/src/plugins/platforms/wasm/qwasmevent.cpp
new file mode 100644
index 0000000000..b094dbfe14
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmevent.cpp
@@ -0,0 +1,53 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "qwasmevent.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace KeyboardModifier
+{
+template <>
+QFlags<Qt::KeyboardModifier> getForEvent<EmscriptenKeyboardEvent>(
+ const EmscriptenKeyboardEvent& event)
+{
+ return internal::Helper<EmscriptenKeyboardEvent>::getModifierForEvent(event) |
+ (event.location == DOM_KEY_LOCATION_NUMPAD ? Qt::KeypadModifier : Qt::NoModifier);
+}
+} // namespace KeyboardModifier
+
+std::optional<PointerEvent> PointerEvent::fromWeb(emscripten::val event)
+{
+ PointerEvent ret;
+
+ const auto eventType = ([&event]() -> std::optional<EventType> {
+ const auto eventTypeString = event["type"].as<std::string>();
+
+ if (eventTypeString == "pointermove")
+ return EventType::PointerMove;
+ else if (eventTypeString == "pointerup")
+ return EventType::PointerUp;
+ else if (eventTypeString == "pointerdown")
+ return EventType::PointerDown;
+ else if (eventTypeString == "pointerenter")
+ return EventType::PointerEnter;
+ else if (eventTypeString == "pointerleave")
+ return EventType::PointerLeave;
+ return std::nullopt;
+ })();
+ if (!eventType)
+ return std::nullopt;
+
+ ret.type = *eventType;
+ ret.pointerType = event["pointerType"].as<std::string>() == "mouse" ?
+ PointerType::Mouse : PointerType::Other;
+ ret.mouseButton = MouseEvent::buttonFromWeb(event["button"].as<int>());
+ ret.mouseButtons = MouseEvent::buttonsFromWeb(event["buttons"].as<unsigned short>());
+ ret.point = QPoint(event["x"].as<int>(), event["y"].as<int>());
+ ret.pointerId = event["pointerId"].as<int>();
+ ret.modifiers = KeyboardModifier::getForEvent(event);
+
+ return ret;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmevent.h b/src/plugins/platforms/wasm/qwasmevent.h
new file mode 100644
index 0000000000..df9276b746
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmevent.h
@@ -0,0 +1,168 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QWASMEVENT_H
+#define QWASMEVENT_H
+
+#include "qwasmplatform.h"
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qnamespace.h>
+#include <QtGui/qevent.h>
+
+#include <QPoint>
+
+#include <emscripten/html5.h>
+#include <emscripten/val.h>
+
+QT_BEGIN_NAMESPACE
+
+enum class EventType {
+ PointerDown,
+ PointerMove,
+ PointerUp,
+ PointerEnter,
+ PointerLeave,
+};
+
+enum class PointerType {
+ Mouse,
+ Other,
+};
+
+enum class WindowArea {
+ NonClient,
+ Client,
+};
+
+namespace KeyboardModifier {
+namespace internal
+{
+ // Check for the existence of shiftKey, ctrlKey, altKey and metaKey in a type.
+ // Based on that, we can safely assume we are dealing with an emscripten event type.
+ template<typename T>
+ struct IsEmscriptenEvent
+ {
+ template<typename U, EM_BOOL U::*, EM_BOOL U::*, EM_BOOL U::*, EM_BOOL U::*>
+ struct SFINAE {};
+ template<typename U> static char Test(
+ SFINAE<U, &U::shiftKey, &U::ctrlKey, &U::altKey, &U::metaKey>*);
+ template<typename U> static int Test(...);
+ static const bool value = sizeof(Test<T>(0)) == sizeof(char);
+ };
+
+ template<class T, typename Enable = void>
+ struct Helper;
+
+ template<class T>
+ struct Helper<T, std::enable_if_t<IsEmscriptenEvent<T>::value>>
+ {
+ static QFlags<Qt::KeyboardModifier> getModifierForEvent(const T& event) {
+ QFlags<Qt::KeyboardModifier> keyModifier = Qt::NoModifier;
+ if (event.shiftKey)
+ keyModifier |= Qt::ShiftModifier;
+ if (event.ctrlKey)
+ keyModifier |= platform() == Platform::MacOS ? Qt::MetaModifier : Qt::ControlModifier;
+ if (event.altKey)
+ keyModifier |= Qt::AltModifier;
+ if (event.metaKey)
+ keyModifier |= platform() == Platform::MacOS ? Qt::ControlModifier : Qt::MetaModifier;
+
+ return keyModifier;
+ }
+ };
+
+ template<>
+ struct Helper<emscripten::val>
+ {
+ static QFlags<Qt::KeyboardModifier> getModifierForEvent(const emscripten::val& event) {
+ QFlags<Qt::KeyboardModifier> keyModifier = Qt::NoModifier;
+ if (event["shiftKey"].as<bool>())
+ keyModifier |= Qt::ShiftModifier;
+ if (event["ctrlKey"].as<bool>())
+ keyModifier |= platform() == Platform::MacOS ? Qt::MetaModifier : Qt::ControlModifier;
+ if (event["altKey"].as<bool>())
+ keyModifier |= Qt::AltModifier;
+ if (event["metaKey"].as<bool>())
+ keyModifier |= platform() == Platform::MacOS ? Qt::ControlModifier : Qt::MetaModifier;
+ if (event["constructor"]["name"].as<std::string>() == "KeyboardEvent" &&
+ event["location"].as<unsigned int>() == DOM_KEY_LOCATION_NUMPAD) {
+ keyModifier |= Qt::KeypadModifier;
+ }
+
+ return keyModifier;
+ }
+ };
+} // namespace internal
+
+template <typename Event>
+QFlags<Qt::KeyboardModifier> getForEvent(const Event& event)
+{
+ return internal::Helper<Event>::getModifierForEvent(event);
+}
+
+template <>
+QFlags<Qt::KeyboardModifier> getForEvent<EmscriptenKeyboardEvent>(
+ const EmscriptenKeyboardEvent& event);
+
+} // namespace KeyboardModifier
+
+struct Q_CORE_EXPORT Event
+{
+ EventType type;
+};
+
+struct Q_CORE_EXPORT MouseEvent : public Event
+{
+ QPoint point;
+ Qt::MouseButton mouseButton;
+ Qt::MouseButtons mouseButtons;
+ QFlags<Qt::KeyboardModifier> modifiers;
+
+ static constexpr Qt::MouseButton buttonFromWeb(int webButton) {
+ switch (webButton) {
+ case 0:
+ return Qt::LeftButton;
+ case 1:
+ return Qt::MiddleButton;
+ case 2:
+ return Qt::RightButton;
+ default:
+ return Qt::NoButton;
+ }
+ }
+
+ static constexpr Qt::MouseButtons buttonsFromWeb(unsigned short webButtons) {
+ // Coincidentally, Qt and web bitfields match.
+ return Qt::MouseButtons::fromInt(webButtons);
+ }
+
+ static constexpr QEvent::Type mouseEventTypeFromEventType(
+ EventType eventType, WindowArea windowArea) {
+ switch (eventType) {
+ case EventType::PointerDown :
+ return windowArea == WindowArea::Client ?
+ QEvent::MouseButtonPress : QEvent::NonClientAreaMouseButtonPress;
+ case EventType::PointerUp :
+ return windowArea == WindowArea::Client ?
+ QEvent::MouseButtonRelease : QEvent::NonClientAreaMouseButtonRelease;
+ case EventType::PointerMove :
+ return windowArea == WindowArea::Client ?
+ QEvent::MouseMove : QEvent::NonClientAreaMouseMove;
+ default:
+ return QEvent::None;
+ }
+ }
+};
+
+struct Q_CORE_EXPORT PointerEvent : public MouseEvent
+{
+ static std::optional<PointerEvent> fromWeb(emscripten::val webEvent);
+
+ PointerType pointerType;
+ int pointerId;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWASMEVENT_H
diff --git a/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp b/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp
index 9d65bd58f8..2fd1a30401 100644
--- a/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp
+++ b/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp
@@ -5,9 +5,13 @@
#include <QtGui/qpa/qwindowsysteminterface.h>
+QT_BEGIN_NAMESPACE
+
// Note: All event dispatcher functionality is implemented in QEventDispatcherWasm
// in QtCore, except for processWindowSystemEvents() below which uses API from QtGui.
void QWasmEventDispatcher::processWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
{
QWindowSystemInterface::sendWindowSystemEvents(flags);
}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
index 065688f1d2..01f15e7dff 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
@@ -18,50 +18,57 @@
#include <private/qmakearray_p.h>
#include <QtCore/qnamespace.h>
#include <QCursor>
+#include <QtCore/private/qstringiterator_p.h>
#include <emscripten/bind.h>
#include <iostream>
+QT_BEGIN_NAMESPACE
+
using namespace emscripten;
-QT_BEGIN_NAMESPACE
+namespace {
+constexpr std::string_view WebDeadKeyValue = "Dead";
+
+struct Emkb2QtData
+{
+ static constexpr char StringTerminator = '\0';
-typedef struct emkb2qt {
const char *em;
unsigned int qt;
- constexpr bool operator <=(const emkb2qt &that) const noexcept
+ constexpr bool operator<=(const Emkb2QtData &that) const noexcept
{
return !(strcmp(that) > 0);
}
- bool operator <(const emkb2qt &that) const noexcept
+ bool operator<(const Emkb2QtData &that) const noexcept { return ::strcmp(em, that.em) < 0; }
+
+ constexpr bool operator==(const Emkb2QtData &that) const noexcept { return strcmp(that) == 0; }
+
+ constexpr int strcmp(const Emkb2QtData &that, const int i = 0) const
{
- return ::strcmp(em, that.em) < 0;
+ return em[i] == StringTerminator && that.em[i] == StringTerminator ? 0
+ : em[i] == StringTerminator ? -1
+ : that.em[i] == StringTerminator ? 1
+ : em[i] < that.em[i] ? -1
+ : em[i] > that.em[i] ? 1
+ : strcmp(that, i + 1);
}
- constexpr int strcmp(const emkb2qt &that, const int i = 0) const
- {
- return em[i] == 0 && that.em[i] == 0 ? 0
- : em[i] == 0 ? -1
- : that.em[i] == 0 ? 1
- : em[i] < that.em[i] ? -1
- : em[i] > that.em[i] ? 1
- : strcmp(that, i + 1);
- }
-} emkb2qt_t;
+};
template<unsigned int Qt, char ... EmChar>
struct Emkb2Qt
{
static constexpr const char storage[sizeof ... (EmChar) + 1] = {EmChar..., '\0'};
- using Type = emkb2qt_t;
+ using Type = Emkb2QtData;
static constexpr Type data() noexcept { return Type{storage, Qt}; }
};
template<unsigned int Qt, char ... EmChar> constexpr char Emkb2Qt<Qt, EmChar...>::storage[];
-static constexpr const auto KeyTbl = qMakeArray(
+static constexpr const auto WebToQtKeyCodeMappings = qMakeArray(
QSortedData<
Emkb2Qt< Qt::Key_Escape, 'E','s','c','a','p','e' >,
Emkb2Qt< Qt::Key_Tab, 'T','a','b' >,
@@ -119,7 +126,7 @@ static constexpr const auto KeyTbl = qMakeArray(
>::Data{}
);
-static constexpr const auto DeadKeyShiftTbl = qMakeArray(
+static constexpr const auto WebToQtKeyCodeMappingsWithShift = qMakeArray(
QSortedData<
// shifted
Emkb2Qt< Qt::Key_Agrave, '\xc3','\x80' >,
@@ -133,8 +140,10 @@ static constexpr const auto DeadKeyShiftTbl = qMakeArray(
Emkb2Qt< Qt::Key_Eacute, '\xc3','\x89' >,
Emkb2Qt< Qt::Key_Ecircumflex, '\xc3','\x8a' >,
Emkb2Qt< Qt::Key_Ediaeresis, '\xc3','\x8b' >,
+ Emkb2Qt< Qt::Key_Iacute, '\xc3','\x8d' >,
Emkb2Qt< Qt::Key_Icircumflex, '\xc3','\x8e' >,
Emkb2Qt< Qt::Key_Idiaeresis, '\xc3','\x8f' >,
+ Emkb2Qt< Qt::Key_Igrave, '\xc3','\x8c' >,
Emkb2Qt< Qt::Key_Ocircumflex, '\xc3','\x94' >,
Emkb2Qt< Qt::Key_Odiaeresis, '\xc3','\x96' >,
Emkb2Qt< Qt::Key_Ograve, '\xc3','\x92' >,
@@ -147,106 +156,38 @@ static constexpr const auto DeadKeyShiftTbl = qMakeArray(
Emkb2Qt< Qt::Key_Uacute, '\xc3','\x9a' >,
Emkb2Qt< Qt::Key_Ntilde, '\xc3','\x91' >,
Emkb2Qt< Qt::Key_Ccedilla, '\xc3','\x87' >,
- Emkb2Qt< Qt::Key_ydiaeresis, '\xc3','\x8f' >
+ Emkb2Qt< Qt::Key_ydiaeresis, '\xc3','\x8f' >,
+ Emkb2Qt< Qt::Key_Yacute, '\xc3','\x9d' >
>::Data{}
);
-QWasmEventTranslator::QWasmEventTranslator() : QObject()
-{
-}
-
-QWasmEventTranslator::~QWasmEventTranslator()
+std::optional<Qt::Key> findMappingByBisection(const char *toFind)
{
+ const Emkb2QtData searchKey{ toFind, 0 };
+ const auto it = std::lower_bound(WebToQtKeyCodeMappings.cbegin(), WebToQtKeyCodeMappings.cend(),
+ searchKey);
+ return it != WebToQtKeyCodeMappings.cend() && searchKey == *it ? static_cast<Qt::Key>(it->qt)
+ : std::optional<Qt::Key>();
}
-template <typename Event>
-QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translatKeyModifier(const Event *event)
+bool isDeadKeyEvent(const EmscriptenKeyboardEvent *emKeyEvent)
{
- // macOS CTRL <-> META switching. We most likely want to enable
- // the existing switching code in QtGui, but for now do it here.
-
- QFlags<Qt::KeyboardModifier> keyModifier = Qt::NoModifier;
- if (event->shiftKey)
- keyModifier |= Qt::ShiftModifier;
- if (event->ctrlKey) {
- if (g_usePlatformMacSpecifics)
- keyModifier |= Qt::MetaModifier;
- else
- keyModifier |= Qt::ControlModifier;
- }
- if (event->altKey)
- keyModifier |= Qt::AltModifier;
- if (event->metaKey) {
- if (g_usePlatformMacSpecifics)
- keyModifier |= Qt::ControlModifier;
- else
- keyModifier |= Qt::MetaModifier;
- }
-
- return keyModifier;
+ return qstrncmp(emKeyEvent->key, WebDeadKeyValue.data(), WebDeadKeyValue.size()) == 0;
}
-QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateKeyboardEventModifier(const EmscriptenKeyboardEvent *event)
+Qt::Key translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey)
{
- QFlags<Qt::KeyboardModifier> keyModifier = translatKeyModifier(event);
-
- if (event->location == DOM_KEY_LOCATION_NUMPAD) {
- keyModifier |= Qt::KeypadModifier;
+ if (isDeadKeyEvent(emscriptKey)) {
+ if (auto mapping = findMappingByBisection(emscriptKey->code))
+ return *mapping;
}
+ if (auto mapping = findMappingByBisection(emscriptKey->key))
+ return *mapping;
- return keyModifier;
-}
-
-QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateMouseEventModifier(const EmscriptenMouseEvent *mouseEvent)
-{
- return translatKeyModifier(mouseEvent);
-}
-
-QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateTouchEventModifier(const EmscriptenTouchEvent *touchEvent)
-{
- return translatKeyModifier(touchEvent);
-}
-
-Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey)
-{
- Qt::Key qtKey = Qt::Key_unknown;
-
- if (qstrncmp(emscriptKey->key, "Dead", 4) == 0 ) {
- emkb2qt_t searchKey1{emscriptKey->code, 0};
- for (auto it1 = KeyTbl.cbegin(); it1 != KeyTbl.end(); ++it1)
- if (it1 != KeyTbl.end() && (qstrcmp(searchKey1.em, it1->em) == 0)) {
- qtKey = static_cast<Qt::Key>(it1->qt);
- }
- }
- if (qtKey == Qt::Key_unknown) {
- emkb2qt_t searchKey{emscriptKey->key, 0};
- // search key
- auto it1 = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey);
- if (it1 != KeyTbl.end() && !(searchKey < *it1)) {
- qtKey = static_cast<Qt::Key>(it1->qt);
- }
- }
-
- if (qtKey == Qt::Key_unknown) {
- // cast to unicode key
- QString str = QString::fromUtf8(emscriptKey->key);
- ushort c = str.unicode()->toUpper().unicode(); // uppercase
- qtKey = static_cast<Qt::Key>(c);
- }
-
- return qtKey;
-}
-
-Qt::MouseButton QWasmEventTranslator::translateMouseButton(unsigned short button)
-{
- if (button == 0)
- return Qt::LeftButton;
- else if (button == 1)
- return Qt::MiddleButton;
- else if (button == 2)
- return Qt::RightButton;
-
- return Qt::NoButton;
+ // cast to unicode key
+ QString str = QString::fromUtf8(emscriptKey->key).toUpper();
+ QStringIterator i(str);
+ return static_cast<Qt::Key>(i.next(0));
}
struct KeyMapping { Qt::Key from, to; };
@@ -303,46 +244,45 @@ static Qt::Key find(const KeyMapping (&map)[N], Qt::Key key) noexcept
return find_impl(map, map + N, key);
}
-Qt::Key QWasmEventTranslator::translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey, bool is_mac)
+Qt::Key translateBaseKeyUsingDeadKey(Qt::Key accentBaseKey, Qt::Key deadKey)
{
- Qt::Key wasmKey = Qt::Key_unknown;
-
- if (deadKey == Qt::Key_QuoteLeft ) {
- if (is_mac) { // ` macOS: Key_Dead_Grave
- wasmKey = find(graveKeyTable, accentBaseKey);
- } else {
- wasmKey = find(diaeresisKeyTable, accentBaseKey);
- }
- return wasmKey;
- }
-
switch (deadKey) {
- // case Qt::Key_QuoteLeft:
+ case Qt::Key_QuoteLeft: {
+ // ` macOS: Key_Dead_Grave
+ return platform() == Platform::MacOS ? find(graveKeyTable, accentBaseKey)
+ : find(diaeresisKeyTable, accentBaseKey);
+ }
case Qt::Key_O: // ´ Key_Dead_Grave
- wasmKey = find(graveKeyTable, accentBaseKey);
- break;
+ return find(graveKeyTable, accentBaseKey);
case Qt::Key_E: // ´ Key_Dead_Acute
- wasmKey = find(acuteKeyTable, accentBaseKey);
- break;
+ return find(acuteKeyTable, accentBaseKey);
case Qt::Key_AsciiTilde:
- case Qt::Key_N:// Key_Dead_Tilde
- wasmKey = find(tildeKeyTable, accentBaseKey);
- break;
- case Qt::Key_U:// ¨ Key_Dead_Diaeresis
- wasmKey = find(diaeresisKeyTable, accentBaseKey);
- break;
- case Qt::Key_I:// macOS Key_Dead_Circumflex
- case Qt::Key_6:// linux
- case Qt::Key_Apostrophe:// linux
- wasmKey = find(circumflexKeyTable, accentBaseKey);
- break;
+ case Qt::Key_N: // Key_Dead_Tilde
+ return find(tildeKeyTable, accentBaseKey);
+ case Qt::Key_U: // ¨ Key_Dead_Diaeresis
+ return find(diaeresisKeyTable, accentBaseKey);
+ case Qt::Key_I: // macOS Key_Dead_Circumflex
+ case Qt::Key_6: // linux
+ case Qt::Key_Apostrophe: // linux
+ return find(circumflexKeyTable, accentBaseKey);
default:
- break;
-
+ return Qt::Key_unknown;
};
- return wasmKey;
}
+template<class T>
+std::optional<QString> findKeyTextByKeyId(const T &mappingArray, Qt::Key qtKey)
+{
+ const auto it = std::find_if(mappingArray.cbegin(), mappingArray.cend(),
+ [qtKey](const Emkb2QtData &data) { return data.qt == qtKey; });
+ return it != mappingArray.cend() ? it->em : std::optional<QString>();
+}
+} // namespace
+
+QWasmEventTranslator::QWasmEventTranslator() = default;
+
+QWasmEventTranslator::~QWasmEventTranslator() = default;
+
QCursor QWasmEventTranslator::cursorForMode(QWasmCompositor::ResizeMode m)
{
switch (m) {
@@ -364,62 +304,57 @@ QCursor QWasmEventTranslator::cursorForMode(QWasmCompositor::ResizeMode m)
return Qt::ArrowCursor;
}
-QString QWasmEventTranslator::getKeyText(const EmscriptenKeyboardEvent *keyEvent)
+QWasmEventTranslator::TranslatedEvent
+QWasmEventTranslator::translateKeyEvent(int emEventType, const EmscriptenKeyboardEvent *keyEvent)
{
- QString keyText;
- Qt::Key qtKey = translateEmscriptKey(keyEvent);
- //Qt::KeyboardModifiers modifiers = translateKeyboardEventModifier(keyEvent);
-
- if (m_emDeadKey != Qt::Key_unknown) {
- Qt::Key transformedKey = translateDeadKey(m_emDeadKey, qtKey);
-
- if (transformedKey != Qt::Key_unknown)
- qtKey = transformedKey;
-
- if (keyEvent->shiftKey == 0) {
- for (auto it = KeyTbl.cbegin(); it != KeyTbl.end(); ++it) {
- if (it != KeyTbl.end() && (qtKey == static_cast<Qt::Key>(it->qt))) {
- keyText = it->em;
- m_emDeadKey = Qt::Key_unknown;
- break;
- }
- }
- } else {
- for (auto it = DeadKeyShiftTbl.cbegin(); it != DeadKeyShiftTbl.end(); ++it) {
- if (it != DeadKeyShiftTbl.end() && (qtKey == static_cast<Qt::Key>(it->qt))) {
- keyText = it->em;
- m_emDeadKey = Qt::Key_unknown;
- break;
- }
- }
- }
- }
+ TranslatedEvent ret;
+ switch (emEventType) {
+ case EMSCRIPTEN_EVENT_KEYDOWN:
+ ret.type = QEvent::KeyPress;
+ break;
+ case EMSCRIPTEN_EVENT_KEYUP:
+ ret.type = QEvent::KeyRelease;
+ break;
+ default:
+ // Should not be reached - do not call with this event type.
+ Q_ASSERT(false);
+ break;
+ };
- return keyText;
-}
+ ret.key = translateEmscriptKey(keyEvent);
-Qt::Key QWasmEventTranslator::getKey(const EmscriptenKeyboardEvent *keyEvent)
-{
- Qt::Key qtKey = translateEmscriptKey(keyEvent);
-
- if (qstrncmp(keyEvent->key, "Dead", 4) == 0 || qtKey == Qt::Key_AltGr) {
- qtKey = translateEmscriptKey(keyEvent);
- m_emStickyDeadKey = true;
- if (keyEvent->shiftKey == 1 && qtKey == Qt::Key_QuoteLeft)
- qtKey = Qt::Key_AsciiTilde;
- m_emDeadKey = qtKey;
+ if (isDeadKeyEvent(keyEvent) || ret.key == Qt::Key_AltGr) {
+ if (keyEvent->shiftKey && ret.key == Qt::Key_QuoteLeft)
+ ret.key = Qt::Key_AsciiTilde;
+ m_emDeadKey = ret.key;
}
- return qtKey;
-}
-
-void QWasmEventTranslator::setStickyDeadKey(const EmscriptenKeyboardEvent *keyEvent)
-{
- Qt::Key qtKey = translateEmscriptKey(keyEvent);
-
- if (m_emStickyDeadKey && qtKey != Qt::Key_Alt) {
- m_emStickyDeadKey = false;
+ if (m_emDeadKey != Qt::Key_unknown
+ && (m_keyModifiedByDeadKeyOnPress == Qt::Key_unknown
+ || ret.key == m_keyModifiedByDeadKeyOnPress)) {
+ const Qt::Key baseKey = ret.key;
+ const Qt::Key translatedKey = translateBaseKeyUsingDeadKey(baseKey, m_emDeadKey);
+ if (translatedKey != Qt::Key_unknown)
+ ret.key = translatedKey;
+
+ if (auto text = keyEvent->shiftKey
+ ? findKeyTextByKeyId(WebToQtKeyCodeMappingsWithShift, ret.key)
+ : findKeyTextByKeyId(WebToQtKeyCodeMappings, ret.key)) {
+ if (ret.type == QEvent::KeyPress) {
+ Q_ASSERT(m_keyModifiedByDeadKeyOnPress == Qt::Key_unknown);
+ m_keyModifiedByDeadKeyOnPress = baseKey;
+ } else {
+ Q_ASSERT(ret.type == QEvent::KeyRelease);
+ Q_ASSERT(m_keyModifiedByDeadKeyOnPress == baseKey);
+ m_keyModifiedByDeadKeyOnPress = Qt::Key_unknown;
+ m_emDeadKey = Qt::Key_unknown;
+ }
+ ret.text = *text;
+ return ret;
+ }
}
+ ret.text = QString::fromUtf8(keyEvent->key);
+ return ret;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.h b/src/plugins/platforms/wasm/qwasmeventtranslator.h
index ca7cd94844..8f4e9f6d05 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.h
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.h
@@ -12,6 +12,8 @@
#include <QtGui/qinputdevice.h>
#include <QHash>
#include <QCursor>
+#include "qwasmevent.h"
+#include "qwasmplatform.h"
QT_BEGIN_NAMESPACE
@@ -22,38 +24,24 @@ class QWasmEventTranslator : public QObject
Q_OBJECT
public:
-
+ struct TranslatedEvent
+ {
+ QEvent::Type type;
+ Qt::Key key;
+ QString text;
+ };
explicit QWasmEventTranslator();
~QWasmEventTranslator();
- template <typename Event>
- QFlags<Qt::KeyboardModifier> translatKeyModifier(const Event *event);
-
- static Qt::Key translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey);
- QFlags<Qt::KeyboardModifier> translateKeyboardEventModifier(const EmscriptenKeyboardEvent *keyEvent);
- QFlags<Qt::KeyboardModifier> translateMouseEventModifier(const EmscriptenMouseEvent *mouseEvent);
- QFlags<Qt::KeyboardModifier> translateTouchEventModifier(const EmscriptenTouchEvent *touchEvent);
- static Qt::MouseButton translateMouseButton(unsigned short button);
static QCursor cursorForMode(QWasmCompositor::ResizeMode mode);
- QString getKeyText(const EmscriptenKeyboardEvent *keyEvent);
- Qt::Key getKey(const EmscriptenKeyboardEvent *keyEvent);
- void setStickyDeadKey(const EmscriptenKeyboardEvent *keyEvent);
-
- void setIsMac(bool is_mac) {g_usePlatformMacSpecifics = is_mac;};
- bool g_usePlatformMacSpecifics = false;
-
-Q_SIGNALS:
- void getWindowAt(const QPoint &point, QWindow **window);
-private:
- static Qt::Key translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey, bool is_mac = false);
+ TranslatedEvent translateKeyEvent(int emEventType, const EmscriptenKeyboardEvent *keyEvent);
private:
static quint64 getTimestamp();
Qt::Key m_emDeadKey = Qt::Key_unknown;
- bool m_emStickyDeadKey = false;
-
+ Qt::Key m_keyModifiedByDeadKeyOnPress = Qt::Key_unknown;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasminputcontext.cpp b/src/plugins/platforms/wasm/qwasminputcontext.cpp
index 96d0c272c0..9da0a9dc34 100644
--- a/src/plugins/platforms/wasm/qwasminputcontext.cpp
+++ b/src/plugins/platforms/wasm/qwasminputcontext.cpp
@@ -13,6 +13,8 @@
#include <qwindow.h>
#include <QKeySequence>
#include <qpa/qwindowsysteminterface.h>
+
+QT_BEGIN_NAMESPACE
using namespace qstdweb;
static void inputCallback(emscripten::val event)
@@ -48,7 +50,7 @@ QWasmInputContext::QWasmInputContext()
m_inputElement.set("style", "position:absolute;left:-1000px;top:-1000px"); // offscreen
m_inputElement.set("contentaediable","true");
- if (QWasmIntegration::get()->platform == QWasmIntegration::AndroidPlatform) {
+ if (platform() == Platform::Android) {
emscripten::val body = document["body"];
body.call<void>("appendChild", m_inputElement);
@@ -63,8 +65,7 @@ QWasmInputContext::QWasmInputContext()
&androidKeyboardCallback);
}
- if (QWasmIntegration::get()->platform == QWasmIntegration::MacOSPlatform ||
- QWasmIntegration::get()->platform == QWasmIntegration::iPhonePlatform)
+ if (platform() == Platform::MacOS || platform() == Platform::iPhone)
{
auto callback = [=](emscripten::val) {
m_inputElement["parentElement"].call<void>("removeChild", m_inputElement);
@@ -79,7 +80,7 @@ QWasmInputContext::QWasmInputContext()
QWasmInputContext::~QWasmInputContext()
{
- if (QWasmIntegration::get()->platform == QWasmIntegration::AndroidPlatform)
+ if (platform() == Platform::Android)
emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, 0, NULL);
}
@@ -105,7 +106,7 @@ void QWasmInputContext::update(Qt::InputMethodQueries queries)
void QWasmInputContext::showInputPanel()
{
- if (QWasmIntegration::get()->platform == QWasmIntegration::WindowsPlatform
+ if (platform() == Platform::Windows
&& inputPanelIsOpen) // call this only once for win32
return;
// this is called each time the keyboard is touched
@@ -117,9 +118,9 @@ void QWasmInputContext::showInputPanel()
// captured by the keyboard event handler installed on the
// canvas.
- if (QWasmIntegration::get()->platform == QWasmIntegration::MacOSPlatform // keep for compatibility
- || QWasmIntegration::get()->platform == QWasmIntegration::iPhonePlatform
- || QWasmIntegration::get()->platform == QWasmIntegration::WindowsPlatform) {
+ if (platform() == Platform::MacOS // keep for compatibility
+ || platform() == Platform::iPhone
+ || platform() == Platform::Windows) {
emscripten::val canvas = focusCanvas();
if (canvas == emscripten::val::undefined())
return;
@@ -162,3 +163,5 @@ int QWasmInputContext::androidKeyboardCallback(int eventType,
return true;
}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasminputcontext.h b/src/plugins/platforms/wasm/qwasminputcontext.h
index 34492377b7..58f3920c30 100644
--- a/src/plugins/platforms/wasm/qwasminputcontext.h
+++ b/src/plugins/platforms/wasm/qwasminputcontext.h
@@ -12,6 +12,8 @@
#include <emscripten/html5.h>
#include <emscripten/emscripten.h>
+QT_BEGIN_NAMESPACE
+
class QWasmInputContext : public QPlatformInputContext
{
Q_DISABLE_COPY(QWasmInputContext)
@@ -42,4 +44,6 @@ private:
bool inputPanelIsOpen = false;
};
+QT_END_NAMESPACE
+
#endif // QWASMINPUTCONTEXT_H
diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp
index 32f2fefb9a..a29e18e98a 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.cpp
+++ b/src/plugins/platforms/wasm/qwasmintegration.cpp
@@ -8,6 +8,7 @@
#include "qwasmopenglcontext.h"
#include "qwasmtheme.h"
#include "qwasmclipboard.h"
+#include "qwasmaccessibility.h"
#include "qwasmservices.h"
#include "qwasmoffscreensurface.h"
#include "qwasmstring.h"
@@ -32,9 +33,11 @@
// this is where EGL headers are pulled in, make sure it is last
#include "qwasmscreen.h"
#include <private/qsimpledrag_p.h>
-using namespace emscripten;
+
QT_BEGIN_NAMESPACE
+using namespace emscripten;
+
using namespace Qt::StringLiterals;
static void addContainerElement(emscripten::val element)
@@ -77,27 +80,12 @@ QWasmIntegration *QWasmIntegration::s_instance;
QWasmIntegration::QWasmIntegration()
: m_fontDb(nullptr),
m_desktopServices(nullptr),
- m_clipboard(new QWasmClipboard)
+ m_clipboard(new QWasmClipboard),
+ m_accessibility(new QWasmAccessibility)
{
s_instance = this;
touchPoints = emscripten::val::global("navigator")["maxTouchPoints"].as<int>();
- // The Platform Detect: expand coverage as needed
- platform = GenericPlatform;
- emscripten::val rawPlatform = emscripten::val::global("navigator")["platform"];
-
- if (rawPlatform.call<bool>("includes", emscripten::val("Mac")))
- platform = MacOSPlatform;
- if (rawPlatform.call<bool>("includes", emscripten::val("iPhone")))
- platform = iPhonePlatform;
- if (rawPlatform.call<bool>("includes", emscripten::val("Win32")))
- platform = WindowsPlatform;
- if (rawPlatform.call<bool>("includes", emscripten::val("Linux"))) {
- platform = LinuxPlatform;
- emscripten::val uAgent = emscripten::val::global("navigator")["userAgent"];
- if (uAgent.call<bool>("includes", emscripten::val("Android")))
- platform = AndroidPlatform;
- }
// Create screens for container elements. Each container element can be a div element (preferred),
// or a canvas element (legacy). Qt versions prior to 6.x read the "qtCanvasElements" module property,
@@ -119,7 +107,7 @@ QWasmIntegration::QWasmIntegration()
}
} else if (!qtCanvasElements.isUndefined()) {
qWarning() << "The qtCanvaseElements property is deprecated. Qt will stop reading"
- << "it in some future veresion, please use qtContainerElements instead";
+ << "it in some future version, please use qtContainerElements instead";
emscripten::val length = qtCanvasElements["length"];
int count = length.as<int>();
for (int i = 0; i < count; ++i)
@@ -168,6 +156,7 @@ QWasmIntegration::~QWasmIntegration()
if (m_platformInputContext)
delete m_platformInputContext;
delete m_drag;
+ delete m_accessibility;
for (const auto &elementAndScreen : m_screens)
elementAndScreen.second->deleteScreen();
@@ -297,6 +286,14 @@ QPlatformClipboard* QWasmIntegration::clipboard() const
return m_clipboard;
}
+#ifndef QT_NO_ACCESSIBILITY
+QPlatformAccessibility *QWasmIntegration::accessibility() const
+{
+ return m_accessibility;
+}
+#endif
+
+
void QWasmIntegration::addScreen(const emscripten::val &element)
{
QWasmScreen *screen = new QWasmScreen(element);
diff --git a/src/plugins/platforms/wasm/qwasmintegration.h b/src/plugins/platforms/wasm/qwasmintegration.h
index d996ec3065..76296ff1a7 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.h
+++ b/src/plugins/platforms/wasm/qwasmintegration.h
@@ -33,21 +33,13 @@ class QWasmScreen;
class QWasmCompositor;
class QWasmBackingStore;
class QWasmClipboard;
+class QWasmAccessibility;
class QWasmServices;
class QWasmIntegration : public QObject, public QPlatformIntegration
{
Q_OBJECT
public:
- enum Platform {
- GenericPlatform,
- MacOSPlatform,
- WindowsPlatform,
- LinuxPlatform,
- AndroidPlatform,
- iPhonePlatform
- };
-
QWasmIntegration();
~QWasmIntegration();
@@ -66,6 +58,9 @@ public:
QPlatformTheme *createPlatformTheme(const QString &name) const override;
QPlatformServices *services() const override;
QPlatformClipboard *clipboard() const override;
+#ifndef QT_NO_ACCESSIBILITY
+ QPlatformAccessibility *accessibility() const override;
+#endif
void initialize() override;
QPlatformInputContext *inputContext() const override;
@@ -85,7 +80,6 @@ public:
void removeBackingStore(QWindow* window);
static quint64 getTimestamp();
- Platform platform;
int touchPoints;
private:
@@ -94,6 +88,8 @@ private:
mutable QHash<QWindow *, QWasmBackingStore *> m_backingStores;
QList<QPair<emscripten::val, QWasmScreen *>> m_screens;
mutable QWasmClipboard *m_clipboard;
+ mutable QWasmAccessibility *m_accessibility;
+
qreal m_fontDpi = -1;
mutable QScopedPointer<QPlatformInputContext> m_inputContext;
static QWasmIntegration *s_instance;
diff --git a/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp b/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp
index bb04a66fcb..79ec9af62b 100644
--- a/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp
+++ b/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp
@@ -3,6 +3,8 @@
#include "qwasmoffscreensurface.h"
+QT_BEGIN_NAMESPACE
+
QWasmOffscrenSurface::QWasmOffscrenSurface(QOffscreenSurface *offscreenSurface)
:QPlatformOffscreenSurface(offscreenSurface)
{
@@ -13,3 +15,5 @@ QWasmOffscrenSurface::~QWasmOffscrenSurface()
{
}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmplatform.cpp b/src/plugins/platforms/wasm/qwasmplatform.cpp
new file mode 100644
index 0000000000..c641e345e4
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmplatform.cpp
@@ -0,0 +1,31 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "qwasmplatform.h"
+
+QT_BEGIN_NAMESPACE
+
+Platform platform()
+{
+ static const Platform qtDetectedPlatform = ([]() {
+ // The Platform Detect: expand coverage as needed
+ emscripten::val rawPlatform = emscripten::val::global("navigator")["platform"];
+
+ if (rawPlatform.call<bool>("includes", emscripten::val("Mac")))
+ return Platform::MacOS;
+ if (rawPlatform.call<bool>("includes", emscripten::val("iPhone")))
+ return Platform::iPhone;
+ if (rawPlatform.call<bool>("includes", emscripten::val("Win32")))
+ return Platform::Windows;
+ if (rawPlatform.call<bool>("includes", emscripten::val("Linux"))) {
+ emscripten::val uAgent = emscripten::val::global("navigator")["userAgent"];
+ if (uAgent.call<bool>("includes", emscripten::val("Android")))
+ return Platform::Android;
+ return Platform::Linux;
+ }
+ return Platform::Generic;
+ })();
+ return qtDetectedPlatform;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmplatform.h b/src/plugins/platforms/wasm/qwasmplatform.h
new file mode 100644
index 0000000000..239efdeae9
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmplatform.h
@@ -0,0 +1,29 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QWASMPLATFORM_H
+#define QWASMPLATFORM_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qnamespace.h>
+
+#include <QPoint>
+
+#include <emscripten/val.h>
+
+QT_BEGIN_NAMESPACE
+
+enum class Platform {
+ Generic,
+ MacOS,
+ Windows,
+ Linux,
+ Android,
+ iPhone,
+};
+
+Platform platform();
+
+QT_END_NAMESPACE
+
+#endif // QWASMPLATFORM_H
diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp
index 51593b9d29..92a23c9206 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.cpp
+++ b/src/plugins/platforms/wasm/qwasmscreen.cpp
@@ -11,19 +11,15 @@
#include <emscripten/bind.h>
#include <emscripten/val.h>
-#include <QtGui/private/qeglconvenience_p.h>
-#ifndef QT_NO_OPENGL
-# include <QtGui/private/qeglplatformcontext_p.h>
-#endif
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/qcoreapplication.h>
#include <QtGui/qguiapplication.h>
#include <private/qhighdpiscaling_p.h>
-using namespace emscripten;
-
QT_BEGIN_NAMESPACE
+using namespace emscripten;
+
const char * QWasmScreen::m_canvasResizeObserverCallbackContextPropertyName = "data-qtCanvasResizeObserverCallbackContext";
QWasmScreen::QWasmScreen(const emscripten::val &containerOrCanvas)
@@ -51,8 +47,15 @@ QWasmScreen::QWasmScreen(const emscripten::val &containerOrCanvas)
style.set("height", std::string("100%"));
}
- // Configure canvas
emscripten::val style = m_canvas["style"];
+
+ // Configure container and canvas for accessibility support: set "position: relative"
+ // so that a11y child elements can be positioned with "position: absolute", and hide
+ // the canvas from screen readers.
+ m_container["style"].set("position", std::string("relative"));
+ m_canvas.call<void>("setAttribute", std::string("aria-hidden"), std::string("true")); // FIXME make the canvas non-focusable, as required by the aria-hidden role
+ style.set("z-index", std::string("1")); // a11y elements are at 0
+
style.set("border", std::string("0px none"));
style.set("background-color", std::string("white"));
@@ -78,9 +81,14 @@ QWasmScreen::QWasmScreen(const emscripten::val &containerOrCanvas)
// apps/ages only, since Emscripten uses the main document to look up the element.
// As a workaround for this, Emscripten supports registering custom mappings in the
// "specialHTMLTargets" object. Add a mapping for the canvas for this screen.
- emscripten::val specialHtmlTargets = emscripten::val::module_property("specialHTMLTargets");
- std::string id = std::string("!qtcanvas_") + std::to_string(uint32_t(this));
- specialHtmlTargets.set(id, m_canvas);
+ //
+ // This functionality is gated on "specialHTMLTargets" being available as a module
+ // property. One way to ensure this is the case is to add it to EXPORTED_RUNTIME_METHODS.
+ // Qt does not currently do this by default since if added it _must_ be used in order
+ // to avoid an undefined reference error at startup, and there are cases when Qt won't use
+ // it, for example if QGuiApplication is not usded.
+ if (hasSpecialHtmlTargets())
+ emscripten::val::module_property("specialHTMLTargets").set(canvasSpecialHtmlTargetId(), m_canvas);
// Install event handlers on the container/canvas. This must be
// done after the canvas has been created above.
@@ -97,9 +105,9 @@ QWasmScreen::~QWasmScreen()
// event handlers.
m_compositor = nullptr;
- emscripten::val specialHtmlTargets = emscripten::val::module_property("specialHTMLTargets");
- std::string id = std::string("!qtcanvas_") + std::to_string(uint32_t(this));
- specialHtmlTargets.set(id, emscripten::val::undefined());
+ if (hasSpecialHtmlTargets())
+ emscripten::val::module_property("specialHTMLTargets")
+ .set(canvasSpecialHtmlTargetId(), emscripten::val::undefined());
m_canvas.set(m_canvasResizeObserverCallbackContextPropertyName, emscripten::val(intptr_t(0)));
}
@@ -117,6 +125,8 @@ QWasmScreen *QWasmScreen::get(QPlatformScreen *screen)
QWasmScreen *QWasmScreen::get(QScreen *screen)
{
+ if (!screen)
+ return nullptr;
return get(screen->handle());
}
@@ -146,13 +156,37 @@ QString QWasmScreen::canvasId() const
return QWasmString::toQString(m_canvas["id"]);
}
-// Returns the canvas _target_ id, for use with Emscripten's
-// event registration functions. The target id is a globally
-// unique id, unlike the html element id which is only unique
-// within one html document. See specialHtmlTargets.
+// Returns the canvas _target_ id, for use with Emscripten's event registration
+// functions. This either based on the id registered in specialHtmlTargets, or
+// on the canvas id.
QString QWasmScreen::canvasTargetId() const
{
- return QStringLiteral("!qtcanvas_") + QString::number(int32_t(this));
+ if (hasSpecialHtmlTargets())
+ return QString::fromStdString(canvasSpecialHtmlTargetId());
+ else
+ return QStringLiteral("#") + canvasId();
+}
+
+std::string QWasmScreen::canvasSpecialHtmlTargetId() const
+{
+ // Return a globally unique id for the canvas. We can choose any string,
+ // as long as it starts with a "!".
+ return std::string("!qtcanvas_") + std::to_string(uint32_t(this));
+}
+
+bool QWasmScreen::hasSpecialHtmlTargets() const
+{
+ static bool gotIt = []{
+ // Enable use of specialHTMLTargets, if available
+ emscripten::val htmlTargets = emscripten::val::module_property("specialHTMLTargets");
+ if (htmlTargets.isUndefined())
+ return false;
+
+ // Check that the object has the expected type - it can also be
+ // defined as an abort() function which prints an error on usage.
+ return htmlTargets["constructor"]["name"].as<std::string>() == std::string("Array");
+ }();
+ return gotIt;
}
QRect QWasmScreen::geometry() const
@@ -229,6 +263,15 @@ QWindow *QWasmScreen::topLevelAt(const QPoint &p) const
return m_compositor->windowAt(p);
}
+QPoint QWasmScreen::translateAndClipGlobalPoint(const QPoint &p) const
+{
+ return QPoint(
+ std::max(screen()->geometry().left(),
+ std::min(screen()->geometry().right(), screen()->geometry().left() + p.x())),
+ std::max(screen()->geometry().top(),
+ std::min(screen()->geometry().bottom(), screen()->geometry().top() + p.y())));
+}
+
void QWasmScreen::invalidateSize()
{
m_geometry = QRect();
@@ -261,7 +304,7 @@ void QWasmScreen::updateQScreenAndCanvasRenderSize()
m_canvas.set("width", canvasSize.width());
m_canvas.set("height", canvasSize.height());
- // Returns the html elments document/body position
+ // Returns the html elements document/body position
auto getElementBodyPosition = [](const emscripten::val &element) -> QPoint {
emscripten::val bodyRect = element["ownerDocument"]["body"].call<emscripten::val>("getBoundingClientRect");
emscripten::val canvasRect = element.call<emscripten::val>("getBoundingClientRect");
diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h
index 9887e8abab..405ea7e7b8 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.h
+++ b/src/plugins/platforms/wasm/qwasmscreen.h
@@ -53,6 +53,8 @@ public:
QWindow *topWindow() const;
QWindow *topLevelAt(const QPoint &p) const override;
+ QPoint translateAndClipGlobalPoint(const QPoint &p) const;
+
void invalidateSize();
void updateQScreenAndCanvasRenderSize();
void installCanvasResizeObserver();
@@ -62,6 +64,9 @@ public slots:
void setGeometry(const QRect &rect);
private:
+ std::string canvasSpecialHtmlTargetId() const;
+ bool hasSpecialHtmlTargets() const;
+
emscripten::val m_container;
emscripten::val m_canvas;
std::unique_ptr<QWasmCompositor> m_compositor;
diff --git a/src/plugins/platforms/wasm/qwasmstylepixmaps_p.h b/src/plugins/platforms/wasm/qwasmstylepixmaps_p.h
index 1b443259e3..0f061a38b3 100644
--- a/src/plugins/platforms/wasm/qwasmstylepixmaps_p.h
+++ b/src/plugins/platforms/wasm/qwasmstylepixmaps_p.h
@@ -15,6 +15,8 @@
// We mean it.
//
+QT_BEGIN_NAMESPACE
+
/* XPM */
static const char * const qt_menu_xpm[] = {
"16 16 72 1",
@@ -153,5 +155,5 @@ static const char * const qt_normalizeup_xpm[] = {
".######...",
".........."};
-
+QT_END_NAMESPACE
#endif // QWASMSTYLEPIXMAPS_P_H
diff --git a/src/plugins/platforms/wasm/qwasmtheme.cpp b/src/plugins/platforms/wasm/qwasmtheme.cpp
index 5fa9b5125d..51399159c4 100644
--- a/src/plugins/platforms/wasm/qwasmtheme.cpp
+++ b/src/plugins/platforms/wasm/qwasmtheme.cpp
@@ -26,6 +26,8 @@ QVariant QWasmTheme::themeHint(ThemeHint hint) const
{
if (hint == QPlatformTheme::StyleNames)
return QVariant(QStringList() << "Fusion"_L1);
+ if (hint == QPlatformTheme::UiEffects)
+ return QVariant(int(HoverEffect));
return QPlatformTheme::themeHint(hint);
}
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp
index c40543cd4c..bfcc556d6d 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.cpp
+++ b/src/plugins/platforms/wasm/qwasmwindow.cpp
@@ -14,10 +14,11 @@
#include <iostream>
-Q_GUI_EXPORT int qt_defaultDpiX();
QT_BEGIN_NAMESPACE
+Q_GUI_EXPORT int qt_defaultDpiX();
+
QWasmWindow::QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore)
: QPlatformWindow(w),
m_window(w),
@@ -119,14 +120,16 @@ QMargins QWasmWindow::frameMargins() const
void QWasmWindow::raise()
{
m_compositor->raise(this);
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
+ if (window()->isVisible())
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
invalidate();
}
void QWasmWindow::lower()
{
m_compositor->lower(this);
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
+ if (window()->isVisible())
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
invalidate();
}
@@ -228,8 +231,7 @@ QRegion QWasmWindow::resizeRegion() const
bool QWasmWindow::isPointOnTitle(QPoint point) const
{
- bool ok = titleGeometry().contains(point);
- return ok;
+ return hasTitleBar() ? titleGeometry().contains(point) : false;
}
bool QWasmWindow::isPointOnResizeRegion(QPoint point) const
@@ -393,19 +395,7 @@ qreal QWasmWindow::devicePixelRatio() const
void QWasmWindow::requestUpdate()
{
- if (m_compositor) {
- m_compositor->requestUpdateWindow(this, QWasmCompositor::UpdateRequestDelivery);
- return;
- }
-
- static auto frame = [](double time, void *context) -> int {
- Q_UNUSED(time);
- QWasmWindow *window = static_cast<QWasmWindow *>(context);
- window->m_requestAnimationFrameId = -1;
- window->deliverUpdateRequest();
- return 0;
- };
- m_requestAnimationFrameId = emscripten_request_animation_frame(frame, this);
+ m_compositor->requestUpdateWindow(this, QWasmCompositor::UpdateRequestDelivery);
}
bool QWasmWindow::hasTitleBar() const
diff --git a/src/plugins/platforms/wasm/wasm_shell.html b/src/plugins/platforms/wasm/wasm_shell.html
index 9ec18abe5b..ecbce6c043 100644
--- a/src/plugins/platforms/wasm/wasm_shell.html
+++ b/src/plugins/platforms/wasm/wasm_shell.html
@@ -29,12 +29,13 @@
<canvas id="qtcanvas"></canvas>
<script type='text/javascript'>
+ let qtLoader = undefined;
function init() {
var spinner = document.querySelector('#qtspinner');
var canvas = document.querySelector('#qtcanvas');
var status = document.querySelector('#qtstatus')
- var qtLoader = QtLoader({
+ qtLoader = QtLoader({
canvasElements : [canvas],
showLoader: function(loaderStatus) {
spinner.style.display = 'block';
diff --git a/src/plugins/platforms/windows/CMakeLists.txt b/src/plugins/platforms/windows/CMakeLists.txt
index d71d7e547f..af9c1fccb4 100644
--- a/src/plugins/platforms/windows/CMakeLists.txt
+++ b/src/plugins/platforms/windows/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from windows.pro.
#####################################################################
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index f16c4ff709..9a65603e24 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -106,6 +106,7 @@ enum WindowsEventType // Simplify event types
ExitSizeMoveEvent = WindowEventFlag + 23,
PointerActivateWindowEvent = WindowEventFlag + 24,
DpiScaledSizeEvent = WindowEventFlag + 25,
+ DpiChangedAfterParentEvent = WindowEventFlag + 27,
MouseEvent = MouseEventFlag + 1,
MouseWheelEvent = MouseEventFlag + 2,
CursorEvent = MouseEventFlag + 3,
@@ -139,8 +140,7 @@ 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,
@@ -257,8 +257,6 @@ 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:
case WM_SYSCOLORCHANGE: // Handle color change as theme change (QTBUG-34170).
case WM_DWMCOLORIZATIONCOLORCHANGED:
@@ -292,6 +290,8 @@ 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:
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index ae4128d073..c95f2ef272 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
-Q_LOGGING_CATEGORY(lcQpaWindows, "qt.qpa.windows")
+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")
@@ -71,6 +71,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;
@@ -371,32 +372,30 @@ int QWindowsContext::processDpiAwareness()
void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness)
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << dpiAwareness;
+ qCDebug(lcQpaWindow) << __FUNCTION__ << dpiAwareness;
const HRESULT hr = SetProcessDpiAwareness(static_cast<PROCESS_DPI_AWARENESS>(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())) {
+ if (FAILED(hr) && (hr != E_ACCESSDENIED || lcQpaWindow().isDebugEnabled())) {
qWarning().noquote().nospace() << "SetProcessDpiAwareness("
<< dpiAwareness << ") failed: " << QWindowsContext::comErrorString(hr)
<< ", using " << QWindowsContext::processDpiAwareness();
}
}
-void QWindowsContext::setProcessDpiV2Awareness()
+bool QWindowsContext::setProcessDpiV2Awareness()
{
- qCDebug(lcQpaWindows) << __FUNCTION__;
+ qCDebug(lcQpaWindow) << __FUNCTION__;
const BOOL ok = SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
- if (ok) {
- QWindowsContextPrivate::m_v2DpiAware = true;
- } else {
+ if (!ok) {
const HRESULT errorCode = GetLastError();
- // ERROR_ACCESS_DENIED means set externally (MSVC manifest or external app loading Qt plugin).
- // Silence warning in that case unless debug is enabled.
- if (errorCode != ERROR_ACCESS_DENIED || lcQpaWindows().isDebugEnabled()) {
- qWarning().noquote().nospace() << "setProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) failed: "
- << QWindowsContext::comErrorString(errorCode);
- }
+ qCWarning(lcQpaWindow).noquote().nospace() << "setProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) failed: "
+ << QWindowsContext::comErrorString(errorCode);
+ return false;
}
+
+ QWindowsContextPrivate::m_v2DpiAware = true;
+ return true;
}
bool QWindowsContext::isDarkMode()
@@ -592,7 +591,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;
@@ -734,6 +733,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;
@@ -1093,29 +1094,24 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
#else
return false;
#endif
- case QtWindows::DisplayChangedEvent:
- if (QWindowsTheme *t = QWindowsTheme::instance())
- t->displayChanged();
- QWindowsWindow::displayChanged();
- d->m_screenManager.handleScreenChanges();
- return false;
case QtWindows::SettingChangedEvent: {
QWindowsWindow::settingsChanged();
// Only refresh the window theme if the user changes the personalize settings.
if ((wParam == 0) && (lParam != 0) // lParam sometimes may be NULL.
&& (wcscmp(reinterpret_cast<LPCWSTR>(lParam), L"ImmersiveColorSet") == 0)) {
const bool darkMode = QWindowsTheme::queryDarkMode();
- if (darkMode != QWindowsContextPrivate::m_darkMode) {
- QWindowsContextPrivate::m_darkMode = darkMode;
- auto integration = QWindowsIntegration::instance();
+ const bool darkModeChanged = darkMode != QWindowsContextPrivate::m_darkMode;
+ QWindowsContextPrivate::m_darkMode = darkMode;
+ auto integration = QWindowsIntegration::instance();
+ if (integration->darkModeHandling().testFlag(QWindowsApplication::DarkModeStyle)) {
+ QWindowsTheme::instance()->refresh();
+ QWindowSystemInterface::handleThemeChange();
+ }
+ if (darkModeChanged) {
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();
- QWindowSystemInterface::handleThemeChange();
- }
}
}
return d->m_screenManager.handleScreenChanges();
@@ -1327,6 +1323,9 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
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();
@@ -1565,7 +1564,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();
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index ac65f745e7..47c5ead772 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -20,7 +20,7 @@ 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)
@@ -31,6 +31,7 @@ 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;
@@ -121,7 +122,7 @@ public:
static void setTabletAbsoluteRange(int a);
void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness);
static int processDpiAwareness();
- void setProcessDpiV2Awareness();
+ bool setProcessDpiV2Awareness();
static bool isDarkMode();
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index a923b48f6c..5b904709ef 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -43,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();
}
}
@@ -131,9 +131,9 @@ 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();
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index bfd2608648..d851964b9d 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -106,6 +106,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
/*!
@@ -178,20 +194,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;
}
}
@@ -303,41 +324,6 @@ 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()
@@ -1233,7 +1219,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);
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
index de272289c0..64f40bc3a9 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
@@ -31,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/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index a281172651..2faeb7456b 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -188,8 +188,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);
@@ -209,7 +212,7 @@ void QWindowsIntegrationPrivate::parseOptions(QWindowsIntegration *q, const QStr
QtWindows::ProcessDpiAwareness dpiAwareness = QtWindows::ProcessPerMonitorV2DpiAware;
int tabletAbsoluteRange = -1;
- DarkModeHandling darkModeHandling;
+ DarkModeHandling darkModeHandling = DarkModeHandlingFlag::DarkModeWindowFrames;
m_options = ::parseOptions(paramList, &tabletAbsoluteRange, &dpiAwareness, &darkModeHandling);
q->setDarkModeHandling(darkModeHandling);
QWindowsFontDatabase::setFontOptions(m_options);
@@ -223,16 +226,20 @@ void QWindowsIntegrationPrivate::parseOptions(QWindowsIntegration *q, const QStr
if (!dpiAwarenessSet) { // Set only once in case of repeated instantiations of QGuiApplication.
if (!QCoreApplication::testAttribute(Qt::AA_PluginApplication)) {
-
- // DpiAwareV2 requires using new API
if (dpiAwareness == QtWindows::ProcessPerMonitorV2DpiAware) {
- m_context.setProcessDpiV2Awareness();
- qCDebug(lcQpaWindows)
- << __FUNCTION__ << "DpiAwareness: DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2";
- } else {
+ // DpiAwareV2 requires using new API
+ if (m_context.setProcessDpiV2Awareness()) {
+ qCDebug(lcQpaWindow, "DpiAwareness: DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2");
+ dpiAwarenessSet = true;
+ } else {
+ // fallback to old API
+ dpiAwareness = QtWindows::ProcessPerMonitorDpiAware;
+ }
+ }
+
+ if (!dpiAwarenessSet) {
m_context.setProcessDpiAwareness(dpiAwareness);
- qCDebug(lcQpaWindows)
- << __FUNCTION__ << "DpiAwareness=" << dpiAwareness
+ qCDebug(lcQpaWindow) << "DpiAwareness=" << dpiAwareness
<< "effective process DPI awareness=" << QWindowsContext::processDpiAwareness();
}
}
@@ -260,7 +267,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);
}
@@ -311,7 +318,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;
}
@@ -329,7 +336,7 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
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)
@@ -366,7 +373,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;
}
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 6b60083759..6f0b949b67 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -333,7 +333,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;
}
@@ -344,7 +344,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;
}
@@ -380,7 +380,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;
@@ -513,8 +513,45 @@ QPlatformScreen::SubpixelAntialiasingType QWindowsScreen::subpixelAntialiasingTy
\internal
*/
+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();
+ QWindowsContext::instance()->screenManager().handleScreenChanges();
+ }
+
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
QWindowsScreenManager::QWindowsScreenManager() = default;
+void QWindowsScreenManager::initialize()
+{
+ qCDebug(lcQpaScreen) << "Initializing screen manager";
+
+ auto className = QWindowsContext::instance()->registerWindowClass(
+ QWindowsContext::classNamePrefix() + QLatin1String("ScreenChangeObserverWindow"),
+ qDisplayChangeObserverWndProc);
+
+ // 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);
+
+ qCDebug(lcQpaScreen) << "Created display change observer" << m_displayChangeObserver;
+
+ handleScreenChanges();
+}
+
+QWindowsScreenManager::~QWindowsScreenManager()
+{
+ DestroyWindow(m_displayChangeObserver);
+}
bool QWindowsScreenManager::isSingleScreen()
{
@@ -558,7 +595,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
@@ -610,7 +647,7 @@ 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
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index babb9de758..b1c94d2204 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -10,6 +10,7 @@
#include <QtCore/qpair.h>
#include <QtCore/qscopedpointer.h>
#include <qpa/qplatformscreen.h>
+#include <qpa/qplatformscreen_p.h>
QT_BEGIN_NAMESPACE
@@ -38,6 +39,7 @@ struct QWindowsScreenData
};
class QWindowsScreen : public QPlatformScreen
+ , public QNativeInterface::Private::QWindowsScreen
{
public:
#ifndef QT_NO_CURSOR
@@ -69,7 +71,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(); }
@@ -92,10 +94,13 @@ private:
class QWindowsScreenManager
{
+ Q_DISABLE_COPY_MOVE(QWindowsScreenManager)
public:
using WindowsScreenList = QList<QWindowsScreen *>;
QWindowsScreenManager();
+ void initialize();
+ ~QWindowsScreenManager();
void clearScreens();
@@ -110,6 +115,7 @@ public:
private:
void removeScreen(int index);
+ HWND m_displayChangeObserver = nullptr;
WindowsScreenList m_screens;
};
diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
index 25d29a2302..cf150b5772 100644
--- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
+++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
@@ -94,9 +94,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) {
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 0f377d1241..adc4befaec 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -46,6 +46,19 @@
#include <algorithm>
+#if QT_CONFIG(cpp_winrt) && !defined(Q_CC_CLANG)
+# include <winrt/base.h>
+// Workaround for Windows SDK bug.
+// See https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/issues/47
+namespace winrt::impl
+{
+ template <typename Async>
+ auto wait_for(Async const& async, Windows::Foundation::TimeSpan const& timeout);
+}
+# include <winrt/Windows.UI.ViewManagement.h>
+# define HAS_UISETTINGS 1
+#endif
+
#if defined(__IImageList_INTERFACE_DEFINED__) && defined(__IID_DEFINED__)
# define USE_IIMAGELIST
#endif
@@ -98,6 +111,13 @@ static inline QColor getSysColor(int index)
return COLORREFToQColor(GetSysColor(index));
}
+#if defined(HAS_UISETTINGS)
+static constexpr QColor getSysColor(winrt::Windows::UI::Color &&color)
+{
+ return QColor(color.R, color.G, color.B, color.A);
+}
+#endif
+
// 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.
@@ -208,14 +228,6 @@ static bool shGetFileInfoBackground(const QString &fileName, DWORD attributes,
return result;
}
-// Dark Mode constants
-enum DarkModeColors : QRgb {
- darkModeBtnHighlightRgb = 0xc0c0c0,
- darkModeBtnShadowRgb = 0x808080,
- darkModeHighlightRgb = 0x0055ff, // deviating from 0x800080
- darkModeMenuHighlightRgb = darkModeHighlightRgb
-};
-
// from QStyle::standardPalette
static inline QPalette standardPalette()
{
@@ -239,16 +251,36 @@ static QColor placeHolderColor(QColor textColor)
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)
{
+ QColor background = getSysColor(COLOR_BTNFACE);
+ QColor textColor = getSysColor(COLOR_WINDOWTEXT);
+ QColor accent = getSysColor(COLOR_HIGHLIGHT);
+
+#if defined(HAS_UISETTINGS)
+ if (QWindowsIntegration::instance()->darkModeHandling().testFlag(QWindowsApplication::DarkModeStyle)) {
+ using namespace winrt::Windows::UI::ViewManagement;
+ const auto settings = UISettings();
+
+ background = getSysColor(settings.GetColorValue(UIColorType::Background));
+ textColor = getSysColor(settings.GetColorValue(UIColorType::Foreground));
+ accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
+ }
+#endif
+
+ const QColor btnFace = background;
+ const QColor btnHighlight = getSysColor(COLOR_BTNHIGHLIGHT);
+
+ result.setColor(QPalette::Highlight, accent);
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));
- const QColor textColor = getSysColor(COLOR_WINDOWTEXT);
result.setColor(QPalette::Text, textColor);
result.setColor(QPalette::PlaceholderText, placeHolderColor(textColor));
result.setColor(QPalette::BrightText, btnHighlight);
@@ -257,30 +289,81 @@ static void populateLightSystemBasePalette(QPalette &result)
result.setColor(QPalette::ButtonText, getSysColor(COLOR_BTNTEXT));
result.setColor(QPalette::Midlight, getSysColor(COLOR_3DLIGHT));
result.setColor(QPalette::Shadow, getSysColor(COLOR_3DDKSHADOW));
- result.setColor(QPalette::Highlight, getSysColor(COLOR_HIGHLIGHT));
result.setColor(QPalette::HighlightedText, getSysColor(COLOR_HIGHLIGHTTEXT));
+
+ result.setColor(QPalette::Link, Qt::blue);
+ result.setColor(QPalette::LinkVisited, Qt::magenta);
+ result.setColor(QPalette::Inactive, QPalette::Button, result.button().color());
+ result.setColor(QPalette::Inactive, QPalette::Window, result.window().color());
+ result.setColor(QPalette::Inactive, QPalette::Light, result.light().color());
+ result.setColor(QPalette::Inactive, QPalette::Dark, result.dark().color());
+
+ if (result.midlight() == result.button())
+ result.setColor(QPalette::Midlight, result.button().color().lighter(110));
}
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::PlaceholderText, placeHolderColor(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);
+#if defined(HAS_UISETTINGS)
+ 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));
+ const QColor linkColor = accent;
+#else
+ const QColor foreground = Qt::white;
+ const QColor background = QColor(0x1E, 0x1E, 0x1E);
+ const QColor accent = QColor(0x00, 0x55, 0xff);
+ 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);
+ const QColor linkColor = Qt::blue;
+#endif
+ 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, accentDarkest);
+ result.setColor(QPalette::All, QPalette::ToolTipText, accentLightest);
+ result.setColor(QPalette::All, QPalette::PlaceholderText, placeHolderColor(foreground));
}
static QPalette systemPalette(bool light)
@@ -291,22 +374,14 @@ static QPalette systemPalette(bool light)
else
populateDarkSystemBasePalette(result);
- result.setColor(QPalette::Link, Qt::blue);
- result.setColor(QPalette::LinkVisited, Qt::magenta);
- 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());
- result.setColor(QPalette::Inactive, QPalette::Dark, result.dark().color());
-
- 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));
+ 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());
+ const QColor disabled = mixColors(result.windowText().color(), result.button().color());
result.setColorGroup(QPalette::Disabled, result.windowText(), result.button(),
result.light(), result.dark(), result.mid(),
@@ -315,20 +390,20 @@ static QPalette systemPalette(bool light)
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());
+ 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::Base, result.window().color());
return result;
}
static inline QPalette toolTipPalette(const QPalette &systemPalette, bool light)
{
+ if (!light)
+ return systemPalette;
+
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 = getSysColor(COLOR_INFOBK);
+ const QColor tipTextColor = getSysColor(COLOR_INFOTEXT);
result.setColor(QPalette::All, QPalette::Button, tipBgColor);
result.setColor(QPalette::All, QPalette::Window, tipBgColor);
@@ -342,8 +417,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);
@@ -355,11 +429,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);
@@ -368,9 +444,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,
@@ -395,13 +469,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;
}
@@ -512,22 +587,32 @@ void QWindowsTheme::refreshPalettes()
const bool light =
!QWindowsContext::isDarkMode()
|| !QWindowsIntegration::instance()->darkModeHandling().testFlag(QWindowsApplication::DarkModeStyle);
+ clearPalettes();
m_palettes[SystemPalette] = new QPalette(systemPalette(light));
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) {
+#if defined(HAS_UISETTINGS)
+ 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));
+ m_palettes[CheckBoxPalette] = new QPalette(*m_palettes[SystemPalette]);
+ m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Base, accent);
+ m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Button, accentLight);
+ m_palettes[CheckBoxPalette]->setColor(QPalette::Inactive, QPalette::Base, accentDarkest);
+#else
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::ButtonText, Qt::white);
+#endif
m_palettes[RadioButtonPalette] = new QPalette(*m_palettes[CheckBoxPalette]);
-
}
}
@@ -571,9 +656,9 @@ void QWindowsTheme::refreshFonts()
if (!QGuiApplication::desktopSettingsAware())
return;
NONCLIENTMETRICS ncm;
- auto screenManager = QWindowsContext::instance()->screenManager();
+ auto &screenManager = QWindowsContext::instance()->screenManager();
QWindowsContext::nonClientMetricsForScreen(&ncm, screenManager.screens().value(0));
- qCDebug(lcQpaWindows) << __FUNCTION__ << ncm;
+ qCDebug(lcQpaWindow) << __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);
@@ -646,7 +731,7 @@ void QWindowsTheme::refreshIconPixmapSizes()
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
@@ -898,7 +983,7 @@ QPixmap QWindowsFileIconEngine::filePixmap(const QSize &size, QIcon::Mode, QIcon
{
/* We don't use the variable, but by storing it statically, we
* ensure CoInitialize is only called once. */
- static HRESULT comInit = CoInitialize(nullptr);
+ static HRESULT comInit = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
Q_UNUSED(comInit);
static QCache<QString, FakePointer<int> > dirIconEntryCache(1000);
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index db51d4fbae..468b028b8b 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -475,15 +475,15 @@ static bool shouldShowMaximizeButton(const QWindow *w, Qt::WindowFlags flags)
// 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);
const bool needsLayered = (flags & Qt::WindowTransparentForInput)
|| (hasAlpha && (flags & Qt::FramelessWindowHint)) || 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;
@@ -640,13 +640,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;
}
}
@@ -790,60 +795,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
+ // 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
+ 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 ;
+ 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;
+ 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;
}
- 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;
+ 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;
}
}
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;
+ if (QWindowsIntegration::instance()->darkModeHandling().testFlag(QWindowsApplication::DarkModeStyle))
+ return true;
+ // 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.
+ const QPalette defaultPalette;
+ return defaultPalette.color(QPalette::WindowText).lightness()
+ > defaultPalette.color(QPalette::Window).lightness();
}
QWindowsWindowData
@@ -878,7 +891,7 @@ QWindowsWindowData
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
@@ -904,7 +917,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;
@@ -947,7 +960,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 "
@@ -1021,7 +1034,7 @@ QMargins QWindowsGeometryHint::frameOnPrimaryScreen(const QWindow *w, DWORD styl
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;
@@ -1046,7 +1059,7 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, DWORD style, DWORD exStyl
}
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;
@@ -1059,7 +1072,7 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, HWND hwnd, DWORD style, D
return {};
if (QWindowsScreenManager::isSingleScreen())
return frameOnPrimaryScreen(w, style, exStyle);
- auto screenManager = QWindowsContext::instance()->screenManager();
+ auto &screenManager = QWindowsContext::instance()->screenManager();
auto screen = screenManager.screenForHwnd(hwnd);
if (!screen)
screen = screenManager.screens().value(0);
@@ -1071,8 +1084,8 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, HWND hwnd)
{
if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
return {};
- return frame(w, hwnd, DWORD(GetWindowLongPtrW(hwnd, GWL_STYLE)),
- DWORD(GetWindowLongPtrW(hwnd, GWL_EXSTYLE)));
+ return frame(w, hwnd, DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
+ DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE)));
}
// For newly created windows.
@@ -1086,7 +1099,7 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, const QRect &geometry,
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);
@@ -1108,7 +1121,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;
@@ -1144,7 +1157,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
@@ -1159,7 +1172,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,
@@ -1194,7 +1207,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)
@@ -1255,7 +1268,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
@@ -1266,14 +1279,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()));
}
@@ -1340,7 +1353,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.
@@ -1358,7 +1371,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
@@ -1420,7 +1433,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 << '+'
@@ -1440,7 +1453,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).
@@ -1556,7 +1569,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)
@@ -1663,7 +1676,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.
@@ -1705,7 +1718,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();
@@ -1885,7 +1898,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);
@@ -1966,7 +1979,6 @@ void QWindowsWindow::handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT *
void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
const UINT dpi = HIWORD(wParam);
- const qreal scale = qreal(dpi) / qreal(savedDpi());
setSavedDpi(dpi);
// Send screen change first, so that the new screen is set during any following resize
@@ -1995,16 +2007,21 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
prcNewWindow->right - prcNewWindow->left,
prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
}
+}
- // Scale child QPlatformWindow size. Windows sends WM_DPICHANGE to top-level windows only.
- for (QWindow *childWindow : window()->findChildren<QWindow *>()) {
- QWindowsWindow *platformChildWindow = static_cast<QWindowsWindow *>(childWindow->handle());
- if (!platformChildWindow)
- continue;
- QRect currentGeometry = platformChildWindow->geometry();
- QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
- platformChildWindow->setGeometry(scaledGeometry);
- }
+void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
+{
+ const UINT dpi = GetDpiForWindow(hwnd);
+ const qreal scale = qreal(dpi) / qreal(savedDpi());
+ 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)
@@ -2086,8 +2103,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),
@@ -2150,12 +2171,14 @@ 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
@@ -2164,7 +2187,7 @@ void QWindowsWindow::checkForScreenChanged(ScreenChangeMode mode)
&& !equalDpi(currentScreen->logicalDpi(), newScreen->logicalDpi())) {
return;
}
- qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
+ qCDebug(lcQpaWindow).noquote().nospace() << __FUNCTION__
<< ' ' << window() << " \"" << (currentScreen ? currentScreen->name() : QString())
<< "\"->\"" << newScreen->name() << '"';
updateFullFrameMargins();
@@ -2202,7 +2225,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;
@@ -2233,7 +2256,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();
}
@@ -2287,7 +2310,7 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
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
if (!GetUpdateRect(m_data.hwnd, 0, FALSE))
@@ -2319,7 +2342,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) {
@@ -2337,7 +2360,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;
}
@@ -2358,7 +2381,7 @@ QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
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);
@@ -2425,7 +2448,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();
@@ -2551,12 +2574,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);
@@ -2564,7 +2587,7 @@ void QWindowsWindow::setStyle(unsigned s) const
void QWindowsWindow::setExStyle(unsigned s) const
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << debugWinExStyle(s);
+ qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << debugWinExStyle(s);
SetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE, s);
}
@@ -2590,7 +2613,7 @@ 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)
@@ -2640,7 +2663,7 @@ bool QWindowsWindow::handleGeometryChanging(MSG *message) const
void QWindowsWindow::setFullFrameMargins(const QMargins &newMargins)
{
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;
}
}
@@ -2679,7 +2702,7 @@ QMargins QWindowsWindow::fullFrameMargins() const
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)
@@ -2739,7 +2762,7 @@ void QWindowsWindow::setMask(const QRegion &region)
void QWindowsWindow::requestActivateWindow()
{
- qCDebug(lcQpaWindows) << __FUNCTION__ << this << window();
+ qCDebug(lcQpaWindow) << __FUNCTION__ << this << window();
// 'Active' state handling is based in focus since it needs to work for
// child windows as well.
if (m_data.hwnd) {
@@ -2782,7 +2805,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) {
@@ -2796,7 +2819,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;
@@ -2901,7 +2924,7 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
}
}
- qCDebug(lcQpaWindows) << __FUNCTION__ << window() << *mmi;
+ qCDebug(lcQpaWindow) << __FUNCTION__ << window() << *mmi;
}
bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *result) const
@@ -3013,7 +3036,7 @@ void QWindowsWindow::setCursor(const CursorHandlePtr &c)
}
if (changed) {
const bool apply = applyNewCursor(window());
- qCDebug(lcQpaWindows) << window() << __FUNCTION__
+ qCDebug(lcQpaWindow) << window() << __FUNCTION__
<< c->handle() << " doApply=" << apply;
m_cursor = c;
if (apply)
@@ -3176,7 +3199,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);
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 9ed6197eae..29dfbdb856 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -286,6 +286,7 @@ public:
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();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp
index 33900a8d66..8eb9baa8ef 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp
@@ -16,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)
@@ -36,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;
@@ -54,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;
@@ -72,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/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index bd8553532a..2d5d91a7ea 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -295,14 +295,16 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow
break;
case UIA_SelectionPatternId:
// Lists of items.
- if (accessible->role() == QAccessible::List) {
+ if (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)) {
+ || (accessible->role() == QAccessible::ListItem)
+ || (accessible->role() == QAccessible::PageTab)) {
*pRetVal = new QWindowsUiaSelectionItemProvider(id());
}
break;
@@ -342,9 +344,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;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp
index 14ec29c75b..7e829b24a7 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp
@@ -40,8 +40,8 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::Select()
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.
@@ -77,8 +77,8 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::AddToSelection()
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.
@@ -102,7 +102,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::RemoveFromSelection(
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());
}
@@ -126,6 +126,8 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_IsSelected(BOOL
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;
@@ -149,11 +151,10 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContain
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 (QAccessibleInterface *parent = accessible->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/qwindowsuiaselectionprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp
index 1d110a637e..45f3b20552 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp
@@ -45,8 +45,14 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::GetSelection(SAFEARRAY *
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 (accessible->role() == QAccessible::PageTabList) {
+ if (child->role() == QAccessible::PageTab && child->state().focused) {
+ selectedList.append(child);
+ }
+ } else {
+ if (child->state().selected) {
+ selectedList.append(child);
+ }
}
}
}
@@ -90,18 +96,23 @@ 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;
+ 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;
+ *pRetVal = anySelected && !accessible->state().multiSelectable && !accessible->state().extSelectable;
+ }
return S_OK;
}
diff --git a/src/plugins/platforms/xcb/CMakeLists.txt b/src/plugins/platforms/xcb/CMakeLists.txt
index c73b2de73f..60029345a7 100644
--- a/src/plugins/platforms/xcb/CMakeLists.txt
+++ b/src/plugins/platforms/xcb/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from xcb.pro.
#####################################################################
diff --git a/src/plugins/platforms/xcb/gl_integrations/CMakeLists.txt b/src/plugins/platforms/xcb/gl_integrations/CMakeLists.txt
index 210a924550..253540455b 100644
--- a/src/plugins/platforms/xcb/gl_integrations/CMakeLists.txt
+++ b/src/plugins/platforms/xcb/gl_integrations/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from gl_integrations.pro.
if(QT_FEATURE_xcb_egl_plugin)
diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h
index 6e841370d8..c6492f02ae 100644
--- a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h
+++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h
@@ -14,7 +14,7 @@ class QPlatformOffscreenSurface;
class QOffscreenSurface;
class QXcbNativeInterfaceHandler;
-Q_XCB_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcQpaGl)
+Q_DECLARE_EXPORTED_LOGGING_CATEGORY(lcQpaGl, Q_XCB_EXPORT)
class Q_XCB_EXPORT QXcbGlIntegration
{
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/CMakeLists.txt b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/CMakeLists.txt
index 4a62c8ad46..c36a8bede5 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/CMakeLists.txt
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from xcb_egl.pro.
#####################################################################
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
index 2ab89f07d6..1e93ea6805 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
@@ -6,12 +6,55 @@
#include "qxcbeglcontext.h"
#include <QtGui/QOffscreenSurface>
+#include <QtGui/private/qeglconvenience_p.h>
#include <QtGui/private/qeglstreamconvenience_p.h>
+#include <optional>
#include "qxcbeglnativeinterfacehandler.h"
QT_BEGIN_NAMESPACE
+namespace {
+
+struct VisualInfo
+{
+ xcb_visualtype_t visualType;
+ uint8_t depth;
+};
+
+std::optional<VisualInfo> getVisualInfo(xcb_screen_t *screen,
+ std::optional<xcb_visualid_t> requestedVisualId,
+ std::optional<uint8_t> requestedDepth = std::nullopt)
+{
+ xcb_depth_iterator_t depthIterator = xcb_screen_allowed_depths_iterator(screen);
+
+ while (depthIterator.rem) {
+ xcb_depth_t *depth = depthIterator.data;
+ xcb_visualtype_iterator_t visualTypeIterator = xcb_depth_visuals_iterator(depth);
+
+ while (visualTypeIterator.rem) {
+ xcb_visualtype_t *visualType = visualTypeIterator.data;
+ if (requestedVisualId && visualType->visual_id != *requestedVisualId) {
+ xcb_visualtype_next(&visualTypeIterator);
+ continue;
+ }
+
+ if (requestedDepth && depth->depth != *requestedDepth) {
+ xcb_visualtype_next(&visualTypeIterator);
+ continue;
+ }
+
+ return VisualInfo{ *visualType, depth->depth };
+ }
+
+ xcb_depth_next(&depthIterator);
+ }
+
+ return std::nullopt;
+}
+
+} // namespace
+
QXcbEglIntegration::QXcbEglIntegration()
: m_connection(nullptr)
, m_egl_display(EGL_NO_DISPLAY)
@@ -31,15 +74,26 @@ bool QXcbEglIntegration::initialize(QXcbConnection *connection)
const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+#if QT_CONFIG(xcb_xlib)
if (extensions && strstr(extensions, "EGL_EXT_platform_x11")) {
QEGLStreamConvenience streamFuncs;
m_egl_display = streamFuncs.get_platform_display(EGL_PLATFORM_X11_KHR,
- xlib_display(),
+ m_connection->xlib_display(),
nullptr);
}
+#if QT_CONFIG(egl_x11)
if (!m_egl_display)
- m_egl_display = eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(xlib_display()));
+ m_egl_display = eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(m_connection->xlib_display()));
+#endif
+#else
+ if (extensions && (strstr(extensions, "EGL_EXT_platform_xcb") || strstr(extensions, "EGL_MESA_platform_xcb"))) {
+ QEGLStreamConvenience streamFuncs;
+ m_egl_display = streamFuncs.get_platform_display(EGL_PLATFORM_XCB_KHR,
+ reinterpret_cast<void *>(connection->xcb_connection()),
+ nullptr);
+ }
+#endif
EGLint major, minor;
bool success = eglInitialize(m_egl_display, &major, &minor);
@@ -84,13 +138,99 @@ QPlatformOffscreenSurface *QXcbEglIntegration::createPlatformOffscreenSurface(QO
return new QEGLPbuffer(eglDisplay(), screen->surfaceFormatFor(surface->requestedFormat()), surface);
}
-void *QXcbEglIntegration::xlib_display() const
+xcb_visualid_t QXcbEglIntegration::getCompatibleVisualId(xcb_screen_t *screen, EGLConfig config) const
{
-#if QT_CONFIG(xcb_xlib)
- return m_connection->xlib_display();
-#else
- return EGL_DEFAULT_DISPLAY;
-#endif
+ xcb_visualid_t visualId = 0;
+ EGLint eglValue = 0;
+
+ EGLint configRedSize = 0;
+ eglGetConfigAttrib(eglDisplay(), config, EGL_RED_SIZE, &configRedSize);
+
+ EGLint configGreenSize = 0;
+ eglGetConfigAttrib(eglDisplay(), config, EGL_GREEN_SIZE, &configGreenSize);
+
+ EGLint configBlueSize = 0;
+ eglGetConfigAttrib(eglDisplay(), config, EGL_BLUE_SIZE, &configBlueSize);
+
+ EGLint configAlphaSize = 0;
+ eglGetConfigAttrib(eglDisplay(), config, EGL_ALPHA_SIZE, &configAlphaSize);
+
+ eglGetConfigAttrib(eglDisplay(), config, EGL_CONFIG_ID, &eglValue);
+ int configId = eglValue;
+
+ // See if EGL provided a valid VisualID:
+ eglGetConfigAttrib(eglDisplay(), config, EGL_NATIVE_VISUAL_ID, &eglValue);
+ visualId = eglValue;
+ if (visualId) {
+ // EGL has suggested a visual id, so get the rest of the visual info for that id:
+ std::optional<VisualInfo> chosenVisualInfo = getVisualInfo(screen, visualId);
+ if (chosenVisualInfo) {
+ // Skip size checks if implementation supports non-matching visual
+ // and config (QTBUG-9444).
+ if (q_hasEglExtension(eglDisplay(), "EGL_NV_post_convert_rounding"))
+ return visualId;
+ // Skip also for i.MX6 where 565 visuals are suggested for the default 444 configs and it works just fine.
+ const char *vendor = eglQueryString(eglDisplay(), EGL_VENDOR);
+ if (vendor && strstr(vendor, "Vivante"))
+ return visualId;
+
+ int visualRedSize = qPopulationCount(chosenVisualInfo->visualType.red_mask);
+ int visualGreenSize = qPopulationCount(chosenVisualInfo->visualType.green_mask);
+ int visualBlueSize = qPopulationCount(chosenVisualInfo->visualType.blue_mask);
+ int visualAlphaSize = chosenVisualInfo->depth - visualRedSize - visualBlueSize - visualGreenSize;
+
+ const bool visualMatchesConfig = visualRedSize >= configRedSize
+ && visualGreenSize >= configGreenSize
+ && visualBlueSize >= configBlueSize
+ && visualAlphaSize >= configAlphaSize;
+
+ // In some cases EGL tends to suggest a 24-bit visual for 8888
+ // configs. In such a case we have to fall back to getVisualInfo.
+ if (!visualMatchesConfig) {
+ visualId = 0;
+ qCDebug(lcQpaGl,
+ "EGL suggested using X Visual ID %d (%d %d %d %d depth %d) for EGL config %d"
+ "(%d %d %d %d), but this is incompatible",
+ visualId, visualRedSize, visualGreenSize, visualBlueSize, visualAlphaSize, chosenVisualInfo->depth,
+ configId, configRedSize, configGreenSize, configBlueSize, configAlphaSize);
+ }
+ } else {
+ qCDebug(lcQpaGl, "EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID",
+ visualId, configId);
+ visualId = 0;
+ }
+ }
+ else
+ qCDebug(lcQpaGl, "EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId);
+
+ if (visualId) {
+ qCDebug(lcQpaGl, configAlphaSize > 0
+ ? "Using ARGB Visual ID %d provided by EGL for config %d"
+ : "Using Opaque Visual ID %d provided by EGL for config %d", visualId, configId);
+ return visualId;
+ }
+
+ // Finally, try to use getVisualInfo and only use the bit depths to match on:
+ if (!visualId) {
+ uint8_t depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize;
+ std::optional<VisualInfo> matchingVisual = getVisualInfo(screen, std::nullopt, depth);
+ if (!matchingVisual) {
+ // Try again without taking the alpha channel into account:
+ depth = configRedSize + configGreenSize + configBlueSize;
+ matchingVisual = getVisualInfo(screen, std::nullopt, depth);
+ }
+
+ if (matchingVisual)
+ visualId = matchingVisual->visualType.visual_id;
+ }
+
+ if (visualId) {
+ qCDebug(lcQpaGl, "Using Visual ID %d provided by getVisualInfo for EGL config %d", visualId, configId);
+ return visualId;
+ }
+
+ qWarning("Unable to find an X11 visual which matches EGL config %d", configId);
+ return 0;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h
index 5ea37c0924..ff0804678f 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h
@@ -38,7 +38,8 @@ public:
bool supportsThreadedOpenGL() const override { return true; }
EGLDisplay eglDisplay() const { return m_egl_display; }
- void *xlib_display() const;
+
+ xcb_visualid_t getCompatibleVisualId(xcb_screen_t *screen, EGLConfig config) const;
private:
QXcbConnection *m_connection;
EGLDisplay m_egl_display;
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp
index e5ca2b4864..4d87b08db8 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp
@@ -6,7 +6,6 @@
#include "qxcbeglintegration.h"
#include <QtGui/private/qeglconvenience_p.h>
-#include <QtGui/private/qxlibeglintegration_p.h>
QT_BEGIN_NAMESPACE
@@ -29,29 +28,15 @@ void QXcbEglWindow::resolveFormat(const QSurfaceFormat &format)
m_format = q_glFormatFromConfig(m_glIntegration->eglDisplay(), m_config, format);
}
-#if QT_CONFIG(xcb_xlib)
const xcb_visualtype_t *QXcbEglWindow::createVisual()
{
QXcbScreen *scr = xcbScreen();
if (!scr)
return QXcbWindow::createVisual();
- Display *xdpy = static_cast<Display *>(m_glIntegration->xlib_display());
- VisualID id = QXlibEglIntegration::getCompatibleVisualId(xdpy, m_glIntegration->eglDisplay(), m_config);
-
- XVisualInfo visualInfoTemplate;
- memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
- visualInfoTemplate.visualid = id;
-
- XVisualInfo *visualInfo;
- int matchingCount = 0;
- visualInfo = XGetVisualInfo(xdpy, VisualIDMask, &visualInfoTemplate, &matchingCount);
- const xcb_visualtype_t *xcb_visualtype = scr->visualForId(visualInfo->visualid);
- XFree(visualInfo);
-
- return xcb_visualtype;
+ xcb_visualid_t id = m_glIntegration->getCompatibleVisualId(scr->screen(), m_config);
+ return scr->visualForId(id);
}
-#endif
void QXcbEglWindow::create()
{
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h
index 79f1df0493..935a0c6d43 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h
@@ -25,10 +25,7 @@ public:
protected:
void create() override;
void resolveFormat(const QSurfaceFormat &format) override;
-
-#if QT_CONFIG(xcb_xlib)
const xcb_visualtype_t *createVisual() override;
-#endif
private:
QXcbEglIntegration *m_glIntegration;
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/CMakeLists.txt b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/CMakeLists.txt
index ae81eba545..f676aeae91 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/CMakeLists.txt
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from xcb_glx.pro.
#####################################################################
diff --git a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp
index 2a84431cde..186a3cf9d7 100644
--- a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp
+++ b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp
@@ -1437,22 +1437,16 @@ QPixmap QX11PlatformPixmap::transformed(const QTransform &transform, Qt::Transfo
transform.m21(), transform.m22(), transform.m23(),
0., 0., 1);
bool complex_xform = false;
- qreal scaledWidth;
- qreal scaledHeight;
if (mat.type() <= QTransform::TxScale) {
- scaledHeight = qAbs(mat.m22()) * hs + 0.9999;
- scaledWidth = qAbs(mat.m11()) * ws + 0.9999;
- h = qAbs(int(scaledHeight));
- w = qAbs(int(scaledWidth));
+ h = qRound(qAbs(mat.m22()) * hs);
+ w = qRound(qAbs(mat.m11()) * ws);
} else { // rotation or shearing
QPolygonF a(QRectF(0, 0, ws, hs));
a = mat.map(a);
QRect r = a.boundingRect().toAlignedRect();
w = r.width();
h = r.height();
- scaledWidth = w;
- scaledHeight = h;
complex_xform = true;
}
mat = QPixmap::trueMatrix(mat, ws, hs); // true matrix
@@ -1461,7 +1455,7 @@ QPixmap QX11PlatformPixmap::transformed(const QTransform &transform, Qt::Transfo
mat = mat.inverted(&invertible); // invert matrix
if (h == 0 || w == 0 || !invertible
- || qAbs(scaledWidth) >= 32768 || qAbs(scaledHeight) >= 32768 )
+ || qAbs(h) >= 32768 || qAbs(w) >= 32768 )
// error, return null pixmap
return QPixmap();
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index d6cc0bc2af..f3905dff81 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -866,6 +866,7 @@ void QXcbBackingStore::render(xcb_window_t window, const QRegion &region, const
}
QPlatformBackingStore::FlushResult QXcbBackingStore::rhiFlush(QWindow *window,
+ qreal sourceDevicePixelRatio,
const QRegion &region,
const QPoint &offset,
QPlatformTextureList *textures,
@@ -876,7 +877,7 @@ QPlatformBackingStore::FlushResult QXcbBackingStore::rhiFlush(QWindow *window,
m_image->flushScrolledRegion(true);
- QPlatformBackingStore::rhiFlush(window, region, offset, textures, translucentBackground);
+ QPlatformBackingStore::rhiFlush(window, sourceDevicePixelRatio, region, offset, textures, translucentBackground);
QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle());
if (platformWindow->needsSync()) {
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h
index c3ee4a9e31..979b254326 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.h
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.h
@@ -24,6 +24,7 @@ public:
QPaintDevice *paintDevice() override;
void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
FlushResult rhiFlush(QWindow *window,
+ qreal sourceDevicePixelRatio,
const QRegion &region,
const QPoint &offset,
QPlatformTextureList *textures,
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index cf2a2af457..51530e0055 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -449,12 +449,12 @@ void QXcbConnection::printXcbError(const char *message, xcb_generic_error_t *err
uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1);
uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1);
- qCWarning(lcQpaXcb, "%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
- message,
- int(error->error_code), xcb_errors[clamped_error_code],
- int(error->sequence), int(error->resource_id),
- int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
- int(error->minor_code));
+ qCDebug(lcQpaXcb, "%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
+ message,
+ int(error->error_code), xcb_errors[clamped_error_code],
+ int(error->sequence), int(error->resource_id),
+ int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
+ int(error->minor_code));
}
static Qt::MouseButtons translateMouseButtons(int s)
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 8cb4e5d603..f528e8b593 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -651,7 +651,7 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
{
auto *xiEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event);
setTime(xiEvent->time);
- if (m_xiSlavePointerIds.contains(xiEvent->deviceid)) {
+ if (m_xiSlavePointerIds.contains(xiEvent->deviceid) && xiEvent->event_type != XCB_INPUT_PROPERTY) {
if (!m_duringSystemMoveResize)
return;
if (xiEvent->event == XCB_NONE)
@@ -1512,11 +1512,10 @@ bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletD
}
// TODO maybe have a hash of tabletData->deviceId to device data so we can
// look up the tablet name here, and distinguish multiple tablets
- if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
- qCDebug(lcQpaXInputDevices, "XI2 proximity change on tablet %d %s (USB %x): last tool: %x id %x current tool: %x id %x %s",
- tabletData->deviceId, qPrintable(tabletData->name), ptr[_WACSER_USB_ID],
- ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID],
- ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], toolName(tabletData->tool));
+ qCDebug(lcQpaXInputDevices, "XI2 proximity change on tablet %d %s (USB %x): last tool: %x id %x current tool: %x id %x %s",
+ tabletData->deviceId, qPrintable(tabletData->name), ptr[_WACSER_USB_ID],
+ ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID],
+ ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], toolName(tabletData->tool));
}
}
}
@@ -1550,6 +1549,9 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD
double pressure = 0, rotation = 0, tangentialPressure = 0;
int xTilt = 0, yTilt = 0;
static const bool useValuators = !qEnvironmentVariableIsSet("QT_XCB_TABLET_LEGACY_COORDINATES");
+ const QPointingDevice *dev = QPointingDevicePrivate::tabletDevice(QInputDevice::DeviceType(tabletData->tool),
+ QPointingDevice::PointerType(tabletData->pointerType),
+ QPointingDeviceUniqueId::fromNumericId(tabletData->serialId));
// Valuators' values are relative to the physical size of the current virtual
// screen. Therefore we cannot use QScreen/QWindow geometry and should use
@@ -1597,7 +1599,8 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD
tangentialPressure = normalizedValue * 2.0 - 1.0; // Convert 0..1 range to -1..+1 range
break;
case QInputDevice::DeviceType::Stylus:
- rotation = normalizedValue * 360.0 - 180.0; // Convert 0..1 range to -180..+180 degrees
+ if (dev->capabilities().testFlag(QInputDevice::Capability::Rotation))
+ rotation = normalizedValue * 360.0 - 180.0; // Convert 0..1 range to -180..+180 degrees
break;
default: // Other types of styli do not use this valuator
break;
@@ -1616,11 +1619,10 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD
local.x(), local.y(), global.x(), global.y(),
(int)tabletData->buttons, pressure, xTilt, yTilt, rotation, (int)modifiers);
- QWindowSystemInterface::handleTabletEvent(window, ev->time, local, global,
- int(tabletData->tool), int(tabletData->pointerType),
+ QWindowSystemInterface::handleTabletEvent(window, ev->time, dev, local, global,
tabletData->buttons, pressure,
xTilt, yTilt, tangentialPressure,
- rotation, 0, tabletData->serialId, modifiers);
+ rotation, 0, modifiers);
}
QXcbConnection::TabletData *QXcbConnection::tabletDataForDevice(int id)
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index abda9c9d0a..2cc39f1e85 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -255,10 +255,10 @@ QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c)
if (pixmapCacheKey) {
bitmapCacheKey = pixmapCacheKey;
} else {
- 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();
}
}
}
@@ -583,8 +583,8 @@ xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor)
qCWarning(lcQpaXcb, "xrender >= 0.5 required to create pixmap cursors");
} else {
xcb_connection_t *conn = xcb_connection();
- xcb_pixmap_t cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap(Qt::ReturnByValue).toImage());
- xcb_pixmap_t mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask(Qt::ReturnByValue).toImage());
+ xcb_pixmap_t cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap().toImage());
+ xcb_pixmap_t mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask().toImage());
c = xcb_generate_id(conn);
xcb_create_cursor(conn, c, cp, mp, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF,
spot.x(), spot.y());
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 893b11c8c3..8b49fb73ca 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -20,6 +20,7 @@
#ifndef QT_NO_SESSIONMANAGER
#include "qxcbsessionmanager.h"
#endif
+#include "qxcbxsettings.h"
#include <xcb/xcb.h>
@@ -48,9 +49,9 @@
#include <QtGui/QOpenGLContext>
#include <QtGui/QScreen>
#include <QtGui/QOffscreenSurface>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <qpa/qplatformaccessibility.h>
-#ifndef QT_NO_ACCESSIBILITY_ATSPI_BRIDGE
+#if QT_CONFIG(accessibility_atspi_bridge)
#include <QtGui/private/qspiaccessiblebridge_p.h>
#endif
#endif
@@ -383,7 +384,7 @@ QPlatformInputContext *QXcbIntegration::inputContext() const
return m_inputContext.data();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QPlatformAccessibility *QXcbIntegration::accessibility() const
{
#if !defined(QT_NO_ACCESSIBILITY_ATSPI_BRIDGE)
@@ -423,12 +424,30 @@ QPlatformTheme *QXcbIntegration::createPlatformTheme(const QString &name) const
return QGenericUnixTheme::createUnixTheme(name);
}
+#define RETURN_VALID_XSETTINGS(key) { \
+ auto value = connection()->primaryScreen()->xSettings()->setting(key); \
+ if (value.isValid()) return value; \
+}
+
QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
{
switch (hint) {
- case QPlatformIntegration::CursorFlashTime:
- case QPlatformIntegration::KeyboardInputInterval:
+ case QPlatformIntegration::CursorFlashTime: {
+ bool ok = false;
+ // If cursor blinking is off, returns 0 to keep the cursor awlays display.
+ if (connection()->primaryScreen()->xSettings()->setting(QByteArrayLiteral("Net/CursorBlink")).toInt(&ok) == 0 && ok)
+ return 0;
+
+ RETURN_VALID_XSETTINGS(QByteArrayLiteral("Net/CursorBlinkTime"));
+ break;
+ }
case QPlatformIntegration::MouseDoubleClickInterval:
+ RETURN_VALID_XSETTINGS(QByteArrayLiteral("Net/DoubleClickTime"));
+ break;
+ case QPlatformIntegration::MouseDoubleClickDistance:
+ RETURN_VALID_XSETTINGS(QByteArrayLiteral("Net/DoubleClickDistance"));
+ break;
+ case QPlatformIntegration::KeyboardInputInterval:
case QPlatformIntegration::StartDragTime:
case QPlatformIntegration::KeyboardAutoRepeatRate:
case QPlatformIntegration::PasswordMaskDelay:
@@ -438,6 +457,8 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
// TODO using various xcb, gnome or KDE settings
break; // Not implemented, use defaults
case QPlatformIntegration::StartDragDistance: {
+ RETURN_VALID_XSETTINGS(QByteArrayLiteral("Net/DndDragThreshold"));
+
// The default (in QPlatformTheme::defaultThemeHint) is 10 pixels, but
// on a high-resolution screen it makes sense to increase it.
qreal dpi = 100.0;
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index 4553bbe700..abdfe7112c 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -68,7 +68,7 @@ public:
QPlatformInputContext *inputContext() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QPlatformAccessibility *accessibility() const override;
#endif
@@ -110,7 +110,7 @@ private:
QScopedPointer<QPlatformInputContext> m_inputContext;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
mutable QScopedPointer<QPlatformAccessibility> m_accessibility;
#endif
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 79fef496b4..0666fac735 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -405,7 +405,7 @@ static xkb_layout_index_t lockedGroup(quint16 state)
void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
{
- if (m_config && !connection()->hasXKB()) {
+ if (m_config) {
struct xkb_state *xkbState = m_xkbState.get();
xkb_mod_mask_t modsDepressed = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_DEPRESSED);
xkb_mod_mask_t modsLatched = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_LATCHED);
@@ -427,7 +427,7 @@ void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo)
{
- if (m_config && !connection()->hasXKB()) {
+ if (m_config) {
auto *mods = static_cast<xcb_input_modifier_info_t *>(modInfo);
auto *group = static_cast<xcb_input_group_info_t *>(groupInfo);
const xkb_state_component changedComponents
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index bb33f393ec..2a538c9b6e 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -499,6 +499,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
, m_crtc(output ? output->crtc : XCB_NONE)
, m_outputName(getOutputName(output))
, m_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize())
+ , m_cursor(std::make_unique<QXcbCursor>(connection, this))
{
if (connection->isAtLeastXRandR12()) {
xcb_randr_select_input(xcb_connection(), screen()->root, true);
@@ -519,8 +520,6 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
if (m_sizeMillimeters.isEmpty())
m_sizeMillimeters = virtualDesktop->physicalSize();
- m_cursor = new QXcbCursor(connection, this);
-
updateColorSpaceAndEdid();
}
@@ -585,6 +584,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
: QXcbObject(connection)
, m_virtualDesktop(virtualDesktop)
, m_monitor(monitorInfo)
+ , m_cursor(std::make_unique<QXcbCursor>(connection, this))
{
setMonitor(monitorInfo, timestamp);
}
@@ -598,6 +598,7 @@ void QXcbScreen::setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp
m_crtcs.clear();
m_output = XCB_NONE;
m_crtc = XCB_NONE;
+ m_singlescreen = false;
if (!monitorInfo) {
m_monitor = nullptr;
@@ -678,12 +679,11 @@ void QXcbScreen::setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp
m_sizeMillimeters = virtualDesktop()->physicalSize();
m_outputName = getName(monitorInfo);
- if (connection()->primaryScreenNumber() == virtualDesktop()->number() && monitorInfo->primary)
- m_primary = true;
- else
- m_primary = false;
-
- m_cursor = new QXcbCursor(connection(), this);
+ m_primary = false;
+ if (connection()->primaryScreenNumber() == virtualDesktop()->number()) {
+ if (monitorInfo->primary || isPrimaryInXScreen())
+ m_primary = true;
+ }
updateColorSpaceAndEdid();
}
@@ -700,9 +700,19 @@ QString QXcbScreen::defaultName()
return name;
}
+bool QXcbScreen::isPrimaryInXScreen()
+{
+ auto primary = Q_XCB_REPLY(xcb_randr_get_output_primary, connection()->xcb_connection(), root());
+ if (!primary)
+ qWarning("failed to get the primary output of the screen");
+
+ const bool isPrimary = primary ? (m_monitor ? m_outputs.contains(primary->output) : m_output == primary->output) : false;
+
+ return isPrimary;
+}
+
QXcbScreen::~QXcbScreen()
{
- delete m_cursor;
}
QString QXcbScreen::getOutputName(xcb_randr_get_output_info_reply_t *outputInfo)
@@ -869,7 +879,7 @@ QDpi QXcbScreen::logicalDpi() const
QPlatformCursor *QXcbScreen::cursor() const
{
- return m_cursor;
+ return m_cursor.get();
}
void QXcbScreen::setOutput(xcb_randr_output_t outputId,
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 12c13ef80e..49165d3ba4 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -18,6 +18,8 @@
#include <QtGui/private/qedidparser_p.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QXcbConnection;
@@ -161,6 +163,7 @@ public:
void setCrtc(xcb_randr_crtc_t crtc) { m_crtc = crtc; }
void setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp_t timestamp = XCB_NONE);
QString defaultName();
+ bool isPrimaryInXScreen();
void windowShown(QXcbWindow *window);
QString windowManagerName() const { return m_virtualDesktop->windowManagerName(); }
@@ -212,7 +215,7 @@ private:
QRect m_availableGeometry;
QColorSpace m_colorSpace;
Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
- QXcbCursor *m_cursor;
+ std::unique_ptr<QXcbCursor> m_cursor;
qreal m_refreshRate = 60.0;
QEdidParser m_edid;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 0162d058a6..a37c03cc60 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -440,10 +440,8 @@ void QXcbWindow::create()
setWindowFlags(window()->flags());
setWindowTitle(window()->title());
-#if QT_CONFIG(xcb_xlib)
// force sync to read outstanding requests - see QTBUG-29106
- XSync(static_cast<Display*>(platformScreen->connection()->xlib_display()), false);
-#endif
+ connection()->sync();
#if QT_CONFIG(draganddrop)
connection()->drag()->dndEnable(this, true);
@@ -515,6 +513,8 @@ void QXcbWindow::destroy()
void QXcbWindow::setGeometry(const QRect &rect)
{
+ setWindowState(Qt::WindowNoState);
+
QPlatformWindow::setGeometry(rect);
propagateSizeHints();
diff --git a/src/plugins/platformthemes/CMakeLists.txt b/src/plugins/platformthemes/CMakeLists.txt
index a3c1f4fa9b..dd8e3bdf54 100644
--- a/src/plugins/platformthemes/CMakeLists.txt
+++ b/src/plugins/platformthemes/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from platformthemes.pro.
if(QT_FEATURE_dbus AND QT_FEATURE_mimetype AND QT_FEATURE_regularexpression AND UNIX AND NOT APPLE)
diff --git a/src/plugins/platformthemes/gtk3/CMakeLists.txt b/src/plugins/platformthemes/gtk3/CMakeLists.txt
index 62e752bd92..218d63b443 100644
--- a/src/plugins/platformthemes/gtk3/CMakeLists.txt
+++ b/src/plugins/platformthemes/gtk3/CMakeLists.txt
@@ -1,7 +1,13 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from gtk3.pro.
qt_find_package(GTK3) # special case
-qt_find_package(X11) # special case
+
+if(QT_FEATURE_xlib)
+ qt_find_package(X11) # special case
+endif()
#####################################################################
## QGtk3ThemePlugin Plugin:
@@ -24,6 +30,10 @@ qt_internal_add_plugin(QGtk3ThemePlugin
Qt::CorePrivate
Qt::Gui
Qt::GuiPrivate
+)
+
+qt_internal_extend_target(QGtk3ThemePlugin CONDITION QT_FEATURE_xlib
+ LIBRARIES
X11::X11 # special case
)
diff --git a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp
index dac0f47d22..9826d1f4b1 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp
+++ b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp
@@ -17,12 +17,15 @@
#undef signals
#include <gtk/gtk.h>
#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
#include <pango/pango.h>
+#if QT_CONFIG(xlib) && defined(GDK_WINDOWING_X11)
+#include <gdk/gdkx.h>
+#endif
+
// The size of the preview we display for selected image files. We set height
// larger than width because generally there is more free space vertically
-// than horiztonally (setting the preview image will alway expand the width of
+// than horizontally (setting the preview image will always expand the width of
// the dialog, but usually not the height). The image's aspect ratio will always
// be preserved.
#define PREVIEW_WIDTH 256
@@ -105,12 +108,14 @@ bool QGtk3Dialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWind
GdkWindow *gdkWindow = gtk_widget_get_window(gtkWidget);
if (parent) {
+#if QT_CONFIG(xlib) && defined(GDK_WINDOWING_X11)
if (GDK_IS_X11_WINDOW(gdkWindow)) {
GdkDisplay *gdkDisplay = gdk_window_get_display(gdkWindow);
XSetTransientForHint(gdk_x11_display_get_xdisplay(gdkDisplay),
gdk_x11_window_get_xid(gdkWindow),
parent->winId());
}
+#endif
}
if (modality != Qt::NonModal) {
diff --git a/src/plugins/platformthemes/gtk3/qgtk3menu.cpp b/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
index 5ca50920a2..5589ff8836 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
+++ b/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
@@ -49,6 +49,7 @@ QGtk3MenuItem::QGtk3MenuItem()
m_checkable(false),
m_checked(false),
m_enabled(true),
+ m_exclusive(false),
m_underline(false),
m_invalid(true),
m_menu(nullptr),
diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
index 22a079732a..8551966678 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
+++ b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
@@ -6,14 +6,19 @@
#include "qgtk3menu.h"
#include <QVariant>
#include <QtCore/qregularexpression.h>
+#include <QGuiApplication>
#undef signals
#include <gtk/gtk.h>
+#if QT_CONFIG(xcb_xlib)
#include <X11/Xlib.h>
+#endif
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
const char *QGtk3Theme::name = "gtk3";
template <typename T>
@@ -49,13 +54,25 @@ void gtkMessageHandler(const gchar *log_domain,
QGtk3Theme::QGtk3Theme()
{
+ // Ensure gtk uses the same windowing system, but let it
+ // fallback in case GDK_BACKEND environment variable
+ // filters the preferred one out
+ if (QGuiApplication::platformName().startsWith("wayland"_L1))
+ gdk_set_allowed_backends("wayland,x11");
+ else if (QGuiApplication::platformName() == "xcb"_L1)
+ gdk_set_allowed_backends("x11,wayland");
+
+#if QT_CONFIG(xcb_xlib)
// gtk_init will reset the Xlib error handler, and that causes
// Qt applications to quit on X errors. Therefore, we need to manually restore it.
int (*oldErrorHandler)(Display *, XErrorEvent *) = XSetErrorHandler(nullptr);
+#endif
gtk_init(nullptr, nullptr);
+#if QT_CONFIG(xcb_xlib)
XSetErrorHandler(oldErrorHandler);
+#endif
/* Initialize some types here so that Gtk+ does not crash when reading
* the treemodel for GtkFontChooser.
diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.h b/src/plugins/platformthemes/gtk3/qgtk3theme.h
index 0f274234d5..8c7a1da7cc 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3theme.h
+++ b/src/plugins/platformthemes/gtk3/qgtk3theme.h
@@ -4,6 +4,7 @@
#ifndef QGTK3THEME_H
#define QGTK3THEME_H
+#include <private/qtguiglobal_p.h>
#include <private/qgenericunixthemes_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platformthemes/xdgdesktopportal/CMakeLists.txt b/src/plugins/platformthemes/xdgdesktopportal/CMakeLists.txt
index 82fb94e31d..960ea3f0d0 100644
--- a/src/plugins/platformthemes/xdgdesktopportal/CMakeLists.txt
+++ b/src/plugins/platformthemes/xdgdesktopportal/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from xdgdesktopportal.pro.
#####################################################################
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
index 55eb0b5aff..2ef591a591 100644
--- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
@@ -3,6 +3,10 @@
#include "qxdgdesktopportalfiledialog_p.h"
+#include <private/qgenericunixservices_p.h>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusPendingCall>
@@ -69,15 +73,12 @@ const QDBusArgument &operator >>(const QDBusArgument &arg, QXdgDesktopPortalFile
class QXdgDesktopPortalFileDialogPrivate
{
public:
- QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog)
+ QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog, uint fileChooserPortalVersion)
: nativeFileDialog(nativeFileDialog)
+ , fileChooserPortalVersion(fileChooserPortalVersion)
{ }
- WId winId = 0;
- bool directoryMode = false;
- bool modal = false;
- bool multipleFiles = false;
- bool saveFile = false;
+ QEventLoop loop;
QString acceptLabel;
QString directory;
QString title;
@@ -88,19 +89,27 @@ public:
QString selectedMimeTypeFilter;
QString selectedNameFilter;
QStringList selectedFiles;
- QPlatformFileDialogHelper *nativeFileDialog = nullptr;
+ std::unique_ptr<QPlatformFileDialogHelper> nativeFileDialog;
+ uint fileChooserPortalVersion = 0;
+ bool failedToOpen = false;
+ bool directoryMode = false;
+ bool multipleFiles = false;
+ bool saveFile = false;
};
-QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog)
+QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog, uint fileChooserPortalVersion)
: QPlatformFileDialogHelper()
- , d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog))
+ , d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog, fileChooserPortalVersion))
{
Q_D(QXdgDesktopPortalFileDialog);
if (d->nativeFileDialog) {
- connect(d->nativeFileDialog, SIGNAL(accept()), this, SIGNAL(accept()));
- connect(d->nativeFileDialog, SIGNAL(reject()), this, SIGNAL(reject()));
+ connect(d->nativeFileDialog.get(), SIGNAL(accept()), this, SIGNAL(accept()));
+ connect(d->nativeFileDialog.get(), SIGNAL(reject()), this, SIGNAL(reject()));
}
+
+ d->loop.connect(this, SIGNAL(accept()), SLOT(quit()));
+ d->loop.connect(this, SIGNAL(reject()), SLOT(quit()));
}
QXdgDesktopPortalFileDialog::~QXdgDesktopPortalFileDialog()
@@ -144,7 +153,7 @@ void QXdgDesktopPortalFileDialog::initializeDialog()
setDirectory(options()->initialDirectory());
}
-void QXdgDesktopPortalFileDialog::openPortal()
+void QXdgDesktopPortalFileDialog::openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
{
Q_D(QXdgDesktopPortalFileDialog);
@@ -152,13 +161,11 @@ void QXdgDesktopPortalFileDialog::openPortal()
"/org/freedesktop/portal/desktop"_L1,
"org.freedesktop.portal.FileChooser"_L1,
d->saveFile ? "SaveFile"_L1 : "OpenFile"_L1);
- QString parentWindowId = "x11:"_L1 + QString::number(d->winId, 16);
-
QVariantMap options;
if (!d->acceptLabel.isEmpty())
options.insert("accept_label"_L1, d->acceptLabel);
- options.insert("modal"_L1, d->modal);
+ options.insert("modal"_L1, windowModality != Qt::NonModal);
options.insert("multiple"_L1, d->multipleFiles);
options.insert("directory"_L1, d->directoryMode);
@@ -257,14 +264,29 @@ void QXdgDesktopPortalFileDialog::openPortal()
// TODO choices a(ssa(ss)s)
// List of serialized combo boxes to add to the file chooser.
- message << parentWindowId << d->title << options;
+ auto unixServices = dynamic_cast<QGenericUnixServices *>(
+ QGuiApplicationPrivate::platformIntegration()->services());
+ if (parent && unixServices)
+ message << unixServices->portalWindowIdentifier(parent);
+ else
+ message << QString();
+
+ message << d->title << options;
QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
- connect(watcher, &QDBusPendingCallWatcher::finished, this, [this] (QDBusPendingCallWatcher *watcher) {
+ connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, d, windowFlags, windowModality, parent] (QDBusPendingCallWatcher *watcher) {
QDBusPendingReply<QDBusObjectPath> reply = *watcher;
- if (reply.isError()) {
- Q_EMIT reject();
+ // Any error means the dialog is not shown and we need to fallback
+ d->failedToOpen = reply.isError();
+ if (d->failedToOpen) {
+ if (d->nativeFileDialog) {
+ d->nativeFileDialog->show(windowFlags, windowModality, parent);
+ if (d->loop.isRunning())
+ d->nativeFileDialog->exec();
+ } else {
+ Q_EMIT reject();
+ }
} else {
QDBusConnection::sessionBus().connect(nullptr,
reply.value().path(),
@@ -298,7 +320,7 @@ QUrl QXdgDesktopPortalFileDialog::directory() const
{
Q_D(const QXdgDesktopPortalFileDialog);
- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+ if (d->nativeFileDialog && useNativeFileDialog())
return d->nativeFileDialog->directory();
return d->directory;
@@ -320,7 +342,7 @@ QList<QUrl> QXdgDesktopPortalFileDialog::selectedFiles() const
{
Q_D(const QXdgDesktopPortalFileDialog);
- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+ if (d->nativeFileDialog && useNativeFileDialog())
return d->nativeFileDialog->selectedFiles();
QList<QUrl> files;
@@ -375,16 +397,13 @@ void QXdgDesktopPortalFileDialog::exec()
{
Q_D(QXdgDesktopPortalFileDialog);
- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly)) {
+ if (d->nativeFileDialog && useNativeFileDialog()) {
d->nativeFileDialog->exec();
return;
}
// HACK we have to avoid returning until we emit that the dialog was accepted or rejected
- QEventLoop loop;
- loop.connect(this, SIGNAL(accept()), SLOT(quit()));
- loop.connect(this, SIGNAL(reject()), SLOT(quit()));
- loop.exec();
+ d->loop.exec();
}
void QXdgDesktopPortalFileDialog::hide()
@@ -401,13 +420,10 @@ bool QXdgDesktopPortalFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowMo
initializeDialog();
- d->modal = windowModality != Qt::NonModal;
- d->winId = parent ? parent->winId() : 0;
-
- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+ if (d->nativeFileDialog && useNativeFileDialog(OpenFallback))
return d->nativeFileDialog->show(windowFlags, windowModality, parent);
- openPortal();
+ openPortal(windowFlags, windowModality, parent);
return true;
}
@@ -437,6 +453,23 @@ void QXdgDesktopPortalFileDialog::gotResponse(uint response, const QVariantMap &
}
}
+bool QXdgDesktopPortalFileDialog::useNativeFileDialog(QXdgDesktopPortalFileDialog::FallbackType fallbackType) const
+{
+ Q_D(const QXdgDesktopPortalFileDialog);
+
+ if (d->failedToOpen && fallbackType != OpenFallback)
+ return true;
+
+ if (d->fileChooserPortalVersion < 3) {
+ if (options()->fileMode() == QFileDialogOptions::Directory)
+ return true;
+ else if (options()->fileMode() == QFileDialogOptions::DirectoryOnly)
+ return true;
+ }
+
+ return false;
+}
+
QT_END_NAMESPACE
#include "moc_qxdgdesktopportalfiledialog_p.cpp"
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
index 4ae84ba726..f309307cd6 100644
--- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
@@ -15,6 +15,11 @@ class QXdgDesktopPortalFileDialog : public QPlatformFileDialogHelper
Q_OBJECT
Q_DECLARE_PRIVATE(QXdgDesktopPortalFileDialog)
public:
+ enum FallbackType {
+ GenericFallback,
+ OpenFallback
+ };
+
enum ConditionType : uint {
GlobalPattern = 0,
MimeType = 1
@@ -33,7 +38,7 @@ public:
};
typedef QList<Filter> FilterList;
- QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr);
+ QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr, uint fileChooserPortalVersion = 0);
~QXdgDesktopPortalFileDialog();
bool defaultNameFilterDisables() const override;
@@ -56,7 +61,8 @@ private Q_SLOTS:
private:
void initializeDialog();
- void openPortal();
+ void openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent);
+ bool useNativeFileDialog(FallbackType fallbackType = GenericFallback) const;
QScopedPointer<QXdgDesktopPortalFileDialogPrivate> d_ptr;
};
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
index 60d5474ed2..e6a72e4289 100644
--- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
@@ -166,11 +166,12 @@ QPlatformDialogHelper* QXdgDesktopPortalTheme::createPlatformDialogHelper(Dialog
{
Q_D(const QXdgDesktopPortalTheme);
- if (type == FileDialog) {
+ if (type == FileDialog && d->fileChooserPortalVersion) {
// Older versions of FileChooser portal don't support opening directories, therefore we fallback
// to native file dialog opened inside the sandbox to open a directory.
- if (d->fileChooserPortalVersion < 3 && d->baseTheme->usePlatformNativeDialog(type))
- return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type)));
+ if (d->baseTheme->usePlatformNativeDialog(type))
+ return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type)),
+ d->fileChooserPortalVersion);
return new QXdgDesktopPortalFileDialog;
}
diff --git a/src/plugins/printsupport/CMakeLists.txt b/src/plugins/printsupport/CMakeLists.txt
index 6d265f9285..dcf3c200d7 100644
--- a/src/plugins/printsupport/CMakeLists.txt
+++ b/src/plugins/printsupport/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from printsupport.pro.
if(QT_FEATURE_cups AND UNIX AND NOT APPLE)
diff --git a/src/plugins/printsupport/cups/CMakeLists.txt b/src/plugins/printsupport/cups/CMakeLists.txt
index 1132ff0845..419387b9fd 100644
--- a/src/plugins/printsupport/cups/CMakeLists.txt
+++ b/src/plugins/printsupport/cups/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from cups.pro.
qt_find_package(Cups PROVIDED_TARGETS Cups::Cups) # special case
diff --git a/src/plugins/printsupport/cups/qcupsprintersupport.cpp b/src/plugins/printsupport/cups/qcupsprintersupport.cpp
index c8077bdbf1..539cd55c54 100644
--- a/src/plugins/printsupport/cups/qcupsprintersupport.cpp
+++ b/src/plugins/printsupport/cups/qcupsprintersupport.cpp
@@ -129,12 +129,9 @@ QStringList QCupsPrinterSupport::availablePrintDeviceIds() const
list.reserve(count);
for (int i = 0; i < count; ++i) {
QString printerId = QString::fromLocal8Bit(dests[i].name);
- if (dests[i].instance) {
+ if (dests[i].instance)
printerId += u'/' + QString::fromLocal8Bit(dests[i].instance);
- list.append(printerId);
- } else if (cupsGetOption("printer-uri-supported", dests[i].num_options, dests[i].options)) {
- list.append(printerId);
- }
+ list.append(printerId);
}
cupsFreeDests(count, dests);
return list;
diff --git a/src/plugins/sqldrivers/.cmake.conf b/src/plugins/sqldrivers/.cmake.conf
index f7a41402e0..377be0059e 100644
--- a/src/plugins/sqldrivers/.cmake.conf
+++ b/src/plugins/sqldrivers/.cmake.conf
@@ -1 +1 @@
-set(QT_REPO_MODULE_VERSION "6.4.0")
+set(QT_REPO_MODULE_VERSION "6.5.0")
diff --git a/src/plugins/sqldrivers/CMakeLists.txt b/src/plugins/sqldrivers/CMakeLists.txt
index b704e272f6..a9348d8de5 100644
--- a/src/plugins/sqldrivers/CMakeLists.txt
+++ b/src/plugins/sqldrivers/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from sqldrivers.pro.
# special case begin
diff --git a/src/plugins/sqldrivers/configure.cmake b/src/plugins/sqldrivers/configure.cmake
index 25384f3c52..feebecefa7 100644
--- a/src/plugins/sqldrivers/configure.cmake
+++ b/src/plugins/sqldrivers/configure.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
#### Inputs
diff --git a/src/plugins/sqldrivers/db2/CMakeLists.txt b/src/plugins/sqldrivers/db2/CMakeLists.txt
index 1c693faa3b..a3d667245e 100644
--- a/src/plugins/sqldrivers/db2/CMakeLists.txt
+++ b/src/plugins/sqldrivers/db2/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from db2.pro.
#####################################################################
diff --git a/src/plugins/sqldrivers/ibase/CMakeLists.txt b/src/plugins/sqldrivers/ibase/CMakeLists.txt
index 8cd5c24dfc..76c5c8d991 100644
--- a/src/plugins/sqldrivers/ibase/CMakeLists.txt
+++ b/src/plugins/sqldrivers/ibase/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
qt_internal_add_plugin(QIBaseDriverPlugin
OUTPUT_NAME qsqlibase
PLUGIN_TYPE sqldrivers
diff --git a/src/plugins/sqldrivers/mysql/CMakeLists.txt b/src/plugins/sqldrivers/mysql/CMakeLists.txt
index a05fc513f1..b965ab2daa 100644
--- a/src/plugins/sqldrivers/mysql/CMakeLists.txt
+++ b/src/plugins/sqldrivers/mysql/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from mysql.pro.
#####################################################################
diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
index 7b48decefb..450d551ac5 100644
--- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
+++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
@@ -372,7 +372,7 @@ void QMYSQLResult::cleanup()
if (d->result)
mysql_free_result(d->result);
-// must iterate trough leftover result sets from multi-selects or stored procedures
+// must iterate through leftover result sets from multi-selects or stored procedures
// if this isn't done subsequent queries will fail with "Commands out of sync"
while (driver() && d->drv_d_func()->mysql && mysql_next_result(d->drv_d_func()->mysql) == 0) {
MYSQL_RES *res = mysql_store_result(d->drv_d_func()->mysql);
@@ -1469,7 +1469,7 @@ QString QMYSQLDriver::formatValue(const QSqlField &field, bool trimStrings) cons
QVarLengthArray<char, 512> buffer(ba.size() * 2 + 1);
auto escapedSize = mysql_real_escape_string(d->mysql, buffer.data(), ba.data(), ba.size());
r.reserve(escapedSize + 3);
- r = u'\'' + QString::fromUtf8(buffer) + u'\'';
+ r = u'\'' + QString::fromUtf8(buffer.data(), escapedSize) + u'\'';
break;
} else {
qWarning("QMYSQLDriver::formatValue: Database not open");
diff --git a/src/plugins/sqldrivers/oci/CMakeLists.txt b/src/plugins/sqldrivers/oci/CMakeLists.txt
index 15ab7f7f87..9717fb4eaa 100644
--- a/src/plugins/sqldrivers/oci/CMakeLists.txt
+++ b/src/plugins/sqldrivers/oci/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from oci.pro.
#####################################################################
diff --git a/src/plugins/sqldrivers/oci/qsql_oci.cpp b/src/plugins/sqldrivers/oci/qsql_oci.cpp
index a1748a2bd3..2b844218bf 100644
--- a/src/plugins/sqldrivers/oci/qsql_oci.cpp
+++ b/src/plugins/sqldrivers/oci/qsql_oci.cpp
@@ -1563,7 +1563,7 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVariantList &boundValues, bool a
}
}
- //finaly we can execute
+ //finally we can execute
r = OCIStmtExecute(d->svc, d->sql, d->err,
arrayBind ? 1 : columns[0].recordCount,
0, NULL, NULL,
diff --git a/src/plugins/sqldrivers/odbc/CMakeLists.txt b/src/plugins/sqldrivers/odbc/CMakeLists.txt
index c521f38160..c4ebd5fc4b 100644
--- a/src/plugins/sqldrivers/odbc/CMakeLists.txt
+++ b/src/plugins/sqldrivers/odbc/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from odbc.pro.
#####################################################################
diff --git a/src/plugins/sqldrivers/psql/CMakeLists.txt b/src/plugins/sqldrivers/psql/CMakeLists.txt
index d3a6a8588e..59d5882479 100644
--- a/src/plugins/sqldrivers/psql/CMakeLists.txt
+++ b/src/plugins/sqldrivers/psql/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from psql.pro.
qt_find_package(PostgreSQL) # special case
diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp
index 87fdc41ef7..7365d71695 100644
--- a/src/plugins/sqldrivers/psql/qsql_psql.cpp
+++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp
@@ -1258,7 +1258,7 @@ bool QPSQLDriver::commitTransaction()
// XXX
// This hack is used to tell if the transaction has succeeded for the protocol versions of
// PostgreSQL below. For 7.x and other protocol versions we are left in the dark.
- // This hack can dissapear once there is an API to query this sort of information.
+ // This hack can disappear once there is an API to query this sort of information.
if (d->pro >= QPSQLDriver::Version8) {
transaction_failed = qstrcmp(PQcmdStatus(res), "ROLLBACK") == 0;
}
diff --git a/src/plugins/sqldrivers/qt_cmdline.cmake b/src/plugins/sqldrivers/qt_cmdline.cmake
index 93991fb2a9..5a1a1c9ba3 100644
--- a/src/plugins/sqldrivers/qt_cmdline.cmake
+++ b/src/plugins/sqldrivers/qt_cmdline.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
qt_commandline_option(mysql_config TYPE string)
qt_commandline_option(psql_config TYPE string)
qt_commandline_option(sqlite TYPE enum NAME system-sqlite MAPPING qt no system yes)
diff --git a/src/plugins/sqldrivers/sqlite/CMakeLists.txt b/src/plugins/sqldrivers/sqlite/CMakeLists.txt
index 1fba18290b..4caa518679 100644
--- a/src/plugins/sqldrivers/sqlite/CMakeLists.txt
+++ b/src/plugins/sqldrivers/sqlite/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from sqlite.pro.
#####################################################################
@@ -95,3 +98,8 @@ qt_internal_extend_target(QSQLiteDriverPlugin CONDITION NOT QT_FEATURE_dlopen AN
DEFINES
SQLITE_OMIT_LOAD_EXTENSION
)
+
+qt_internal_extend_target(QSQLiteDriverPlugin CONDITION NOT QT_FEATURE_thread AND NOT QT_FEATURE_system_sqlite
+ DEFINES
+ SQLITE_THREADSAFE=0
+)
diff --git a/src/plugins/styles/CMakeLists.txt b/src/plugins/styles/CMakeLists.txt
index 73329915f6..db89d0aca5 100644
--- a/src/plugins/styles/CMakeLists.txt
+++ b/src/plugins/styles/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from styles.pro.
if(QT_FEATURE_style_android)
diff --git a/src/plugins/styles/android/CMakeLists.txt b/src/plugins/styles/android/CMakeLists.txt
index 3dc0ed1e2e..b89693c122 100644
--- a/src/plugins/styles/android/CMakeLists.txt
+++ b/src/plugins/styles/android/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from android.pro.
#####################################################################
diff --git a/src/plugins/styles/mac/CMakeLists.txt b/src/plugins/styles/mac/CMakeLists.txt
index 98d6791d82..5fafc6d94f 100644
--- a/src/plugins/styles/mac/CMakeLists.txt
+++ b/src/plugins/styles/mac/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from mac.pro.
#####################################################################
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index 200f56cbf8..3646e16c8a 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -317,7 +317,7 @@ static const int closeButtonSize = 14;
static const qreal closeButtonCornerRadius = 2.0;
#endif // QT_CONFIG(tabbar)
-#ifndef QT_NO_ACCESSIBILITY // This ifdef to avoid "unused function" warning.
+#if QT_CONFIG(accessibility) // This ifdef to avoid "unused function" warning.
QBrush brushForToolButton(bool isOnKeyWindow)
{
// When a toolbutton in a toolbar is in the 'ON' state, we draw a
@@ -328,7 +328,7 @@ QBrush brushForToolButton(bool isOnKeyWindow)
return isOnKeyWindow ? QColor(0, 0, 0, 28) : QColor(0, 0, 0, 21);
}
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
static const int headerSectionArrowHeight = 6;
@@ -385,7 +385,6 @@ class AppearanceSync {
public:
AppearanceSync()
{
-#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave
&& !isDarkMode()) {
auto requiredAppearanceName = NSApplication.sharedApplication.effectiveAppearance.name;
@@ -394,7 +393,6 @@ public:
NSAppearance.currentAppearance = [NSAppearance appearanceNamed:requiredAppearanceName];
}
}
-#endif // QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
}
~AppearanceSync()
@@ -1815,13 +1813,9 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
|| widget.size == QStyleHelper::SizeDefault)
return nil;
- if (widget.type == Box) {
- if (__builtin_available(macOS 10.14, *)) {
- if (isDarkMode()) {
- // See render code in drawPrimitive(PE_FrameTabWidget)
- widget.type = Box_Dark;
- }
- }
+ if (widget.type == Box && isDarkMode()) {
+ // See render code in drawPrimitive(PE_FrameTabWidget)
+ widget.type = Box_Dark;
}
NSView *bv = cocoaControls.value(widget, nil);
@@ -2066,7 +2060,6 @@ QMacStyle::QMacStyle()
QCoreApplication::sendEvent(o, &event);
});
-#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
Q_D(QMacStyle);
// FIXME: Tie this logic into theme change, or even polish/unpolish
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) {
@@ -2077,7 +2070,6 @@ QMacStyle::QMacStyle()
d->cocoaControls.clear();
});
}
-#endif
}
QMacStyle::~QMacStyle()
@@ -2866,7 +2858,7 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w
case SH_ScrollBar_Transient:
if ((qobject_cast<const QScrollBar *>(w) && w->parent() &&
qobject_cast<QAbstractScrollArea*>(w->parent()->parent()))
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
|| (opt && QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ScrollBar))
#endif
) {
@@ -3541,7 +3533,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (const QStyleOptionToolButton *tb = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
QStyleOptionToolButton myTb = *tb;
myTb.state &= ~State_AutoRaise;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) {
QRect cr = tb->rect;
int shiftX = 0;
@@ -3631,7 +3623,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QCommonStyle::drawControl(ce, &myTb, p, w);
}
} else
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
{
QCommonStyle::drawControl(ce, &myTb, p, w);
}
@@ -5701,7 +5693,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
case CC_ToolButton:
if (const QStyleOptionToolButton *tb
= qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) {
if (tb->subControls & SC_ToolButtonMenu) {
QStyleOption arrowOpt = *tb;
@@ -5727,7 +5719,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
}
proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget);
} else
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
{
auto bflags = tb->state;
if (tb->subControls & SC_ToolButton)
@@ -6209,7 +6201,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
case CC_ToolButton:
ret = QCommonStyle::subControlRect(cc, opt, sc, widget);
if (sc == SC_ToolButtonMenu) {
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar))
ret.adjust(-toolButtonArrowMargin, 0, 0, 0);
#endif
diff --git a/src/plugins/styles/windowsvista/CMakeLists.txt b/src/plugins/styles/windowsvista/CMakeLists.txt
index efd552ab08..cd23ef81b8 100644
--- a/src/plugins/styles/windowsvista/CMakeLists.txt
+++ b/src/plugins/styles/windowsvista/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
# Generated from windowsvista.pro.
#####################################################################
diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
index db1df71be5..0380ef82d8 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
@@ -466,7 +466,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
}
break;
case PE_Frame: {
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (QStyleHelper::isInstanceOf(option->styleObject, QAccessible::EditableText)
|| QStyleHelper::isInstanceOf(option->styleObject, QAccessible::StaticText) ||
#else
@@ -639,7 +639,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
newStyle = !qobject_cast<const QTableView*>(view);
selectionBehavior = view->selectionBehavior();
selectionMode = view->selectionMode();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
} else if (!widget) {
newStyle = !QStyleHelper::hasAncestor(option->styleObject, QAccessible::MenuItem) ;
#endif
@@ -2263,9 +2263,14 @@ void QWindowsVistaStyle::polish(QWidget *widget)
widget->setAttribute(Qt::WA_Hover);
#if QT_CONFIG(commandlinkbutton)
else if (qobject_cast<QCommandLinkButton*>(widget)) {
+ widget->setProperty("_qt_usingVistaStyle", true);
QFont buttonFont = widget->font();
buttonFont.setFamilies(QStringList{QLatin1String("Segoe UI")});
widget->setFont(buttonFont);
+ QPalette pal = widget->palette();
+ pal.setColor(QPalette::ButtonText, QColor(21, 28, 85));
+ pal.setColor(QPalette::BrightText, QColor(7, 64, 229));
+ widget->setPalette(pal);
}
#endif // QT_CONFIG(commandlinkbutton)
else if (widget->inherits("QTipLabel")){
diff --git a/src/plugins/tls/CMakeLists.txt b/src/plugins/tls/CMakeLists.txt
index a17cda9594..f0d22e66a7 100644
--- a/src/plugins/tls/CMakeLists.txt
+++ b/src/plugins/tls/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
if(QT_FEATURE_securetransport)
add_subdirectory(securetransport)
endif()
diff --git a/src/plugins/tls/certonly/CMakeLists.txt b/src/plugins/tls/certonly/CMakeLists.txt
index 14b769cbba..657104e7c3 100644
--- a/src/plugins/tls/certonly/CMakeLists.txt
+++ b/src/plugins/tls/certonly/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
qt_internal_add_plugin(QTlsBackendCertOnlyPlugin
OUTPUT_NAME qcertonlybackend
CLASS_NAME QTlsBackendCertOnly
diff --git a/src/plugins/tls/openssl/CMakeLists.txt b/src/plugins/tls/openssl/CMakeLists.txt
index a7fb54f08c..4680fb415e 100644
--- a/src/plugins/tls/openssl/CMakeLists.txt
+++ b/src/plugins/tls/openssl/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
qt_internal_add_plugin(QTlsBackendOpenSSLPlugin
OUTPUT_NAME qopensslbackend
CLASS_NAME QTlsBackendOpenSSL
@@ -48,12 +51,9 @@ qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION WIN32
crypt32
)
-qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION QT_FEATURE_openssl_linked
- LIBRARIES
- WrapOpenSSL::WrapOpenSSL
-)
-
-qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION NOT QT_FEATURE_openssl_linked
- LIBRARIES
- WrapOpenSSLHeaders::WrapOpenSSLHeaders
-)
+if(QT_FEATURE_openssl_linked)
+ target_link_libraries(QTlsBackendOpenSSLPlugin PRIVATE WrapOpenSSL::WrapOpenSSL)
+else()
+ qt_internal_add_target_include_dirs(QTlsBackendOpenSSLPlugin
+ WrapOpenSSLHeaders::WrapOpenSSLHeaders)
+endif()
diff --git a/src/plugins/tls/openssl/qsslcontext_openssl.cpp b/src/plugins/tls/openssl/qsslcontext_openssl.cpp
index 9e59477634..33f0d41a09 100644
--- a/src/plugins/tls/openssl/qsslcontext_openssl.cpp
+++ b/src/plugins/tls/openssl/qsslcontext_openssl.cpp
@@ -63,9 +63,9 @@ static inline QString msgErrorSettingEllipticCurves(const QString &why)
return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
}
-long QSslContext::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
+qssloptions QSslContext::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
{
- long options;
+ qssloptions options;
switch (protocol) {
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
@@ -476,7 +476,7 @@ QT_WARNING_POP
}
// Enable bug workarounds.
- const long options = setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
+ const qssloptions options = setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
q_SSL_CTX_set_options(sslContext->ctx, options);
// Tell OpenSSL to release memory early
diff --git a/src/plugins/tls/openssl/qsslcontext_openssl_p.h b/src/plugins/tls/openssl/qsslcontext_openssl_p.h
index 55af2af292..3bd39baf0c 100644
--- a/src/plugins/tls/openssl/qsslcontext_openssl_p.h
+++ b/src/plugins/tls/openssl/qsslcontext_openssl_p.h
@@ -37,7 +37,8 @@ public:
bool allowRootCertOnDemandLoading);
static std::shared_ptr<QSslContext> sharedFromPrivateConfiguration(QSslSocket::SslMode mode, QSslConfigurationPrivate *privConfiguration,
bool allowRootCertOnDemandLoading);
- static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
+
+ static qssloptions setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
QSslError::SslError error() const;
QString errorString() const;
diff --git a/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp b/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp
index c3d05f134c..899a6c4819 100644
--- a/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp
+++ b/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp
@@ -123,7 +123,7 @@ DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMM
DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG)
DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return nullptr, return)
DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return)
-DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return)
+DEFINEFUNC2(qssloptions, SSL_CTX_set_options, SSL_CTX *ctx, ctx, qssloptions op, op, return 0, return)
using info_callback = void (*) (const SSL *ssl, int type, int val);
DEFINEFUNC2(void, SSL_set_info_callback, SSL *ssl, ssl, info_callback cb, cb, return, return)
DEFINEFUNC(const char *, SSL_alert_type_string, int value, value, return nullptr, return)
diff --git a/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h b/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h
index 97999d4c39..3c387ab96b 100644
--- a/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h
+++ b/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h
@@ -185,7 +185,11 @@ QT_BEGIN_NAMESPACE
// **************** Static declarations ******************
#endif // !defined QT_LINKED_OPENSSL
-
+#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
+typedef uint64_t qssloptions;
+#else
+typedef unsigned long qssloptions;
+#endif
// TODO: the following lines previously were a part of 1.1 - specific header.
// To reduce the amount of the change, I'm directly copying and pasting the
// content of the header here. Later, can be better sorted/split into groups,
@@ -209,7 +213,7 @@ void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data);
void q_OPENSSL_sk_free(OPENSSL_STACK *a);
void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b);
int q_SSL_session_reused(SSL *a);
-unsigned long q_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op);
+qssloptions q_SSL_CTX_set_options(SSL_CTX *ctx, qssloptions op);
int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen);
size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen);
diff --git a/src/plugins/tls/schannel/CMakeLists.txt b/src/plugins/tls/schannel/CMakeLists.txt
index f03964069a..196412ab57 100644
--- a/src/plugins/tls/schannel/CMakeLists.txt
+++ b/src/plugins/tls/schannel/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
qt_internal_add_plugin(QSchannelBackendPlugin
OUTPUT_NAME qschannelbackend
CLASS_NAME QSchannelBackend
diff --git a/src/plugins/tls/schannel/qtls_schannel.cpp b/src/plugins/tls/schannel/qtls_schannel.cpp
index 58e74357d8..ba14e61b57 100644
--- a/src/plugins/tls/schannel/qtls_schannel.cpp
+++ b/src/plugins/tls/schannel/qtls_schannel.cpp
@@ -139,7 +139,6 @@ QList<QSslCipher> defaultCiphers()
{
// Previously the code was in QSslSocketBackendPrivate.
QList<QSslCipher> ciphers;
- // @temp (I hope), stolen from qsslsocket_winrt.cpp
const QString protocolStrings[] = { QStringLiteral("TLSv1"), QStringLiteral("TLSv1.1"),
QStringLiteral("TLSv1.2"), QStringLiteral("TLSv1.3") };
QT_WARNING_PUSH
@@ -1556,132 +1555,129 @@ void TlsCryptographSchannel::transmit()
}
}
- if (q->isEncrypted()) { // Decrypt data from remote
- int totalRead = 0;
- bool hadIncompleteData = false;
- const auto readBufferMaxSize = d->maxReadBufferSize();
- while (!readBufferMaxSize || buffer.size() < readBufferMaxSize) {
- if (missingData > plainSocket->bytesAvailable()
- && (!readBufferMaxSize || readBufferMaxSize >= missingData)) {
+ int totalRead = 0;
+ bool hadIncompleteData = false;
+ const auto readBufferMaxSize = d->maxReadBufferSize();
+ while (!readBufferMaxSize || buffer.size() < readBufferMaxSize) {
+ if (missingData > plainSocket->bytesAvailable()
+ && (!readBufferMaxSize || readBufferMaxSize >= missingData)) {
#ifdef QSSLSOCKET_DEBUG
- qCDebug(lcTlsBackendSchannel, "We're still missing %lld bytes, will check later.",
- missingData);
+ qCDebug(lcTlsBackendSchannel, "We're still missing %lld bytes, will check later.",
+ missingData);
#endif
- break;
- }
+ break;
+ }
- missingData = 0;
- const qint64 bytesRead = readToBuffer(intermediateBuffer, plainSocket);
+ missingData = 0;
+ const qint64 bytesRead = readToBuffer(intermediateBuffer, plainSocket);
#ifdef QSSLSOCKET_DEBUG
- qCDebug(lcTlsBackendSchannel, "Read %lld encrypted bytes from the socket", bytesRead);
+ qCDebug(lcTlsBackendSchannel, "Read %lld encrypted bytes from the socket", bytesRead);
#endif
- if (intermediateBuffer.length() == 0 || (hadIncompleteData && bytesRead == 0)) {
+ if (intermediateBuffer.length() == 0 || (hadIncompleteData && bytesRead == 0)) {
#ifdef QSSLSOCKET_DEBUG
- qCDebug(lcTlsBackendSchannel,
- (hadIncompleteData ? "No new data received, leaving loop!"
- : "Nothing to decrypt, leaving loop!"));
+ qCDebug(lcTlsBackendSchannel,
+ hadIncompleteData ? "No new data received, leaving loop!"
+ : "Nothing to decrypt, leaving loop!");
#endif
- break;
- }
- hadIncompleteData = false;
+ break;
+ }
+ hadIncompleteData = false;
#ifdef QSSLSOCKET_DEBUG
- qCDebug(lcTlsBackendSchannel, "Total amount of bytes to decrypt: %d",
- intermediateBuffer.length());
+ qCDebug(lcTlsBackendSchannel, "Total amount of bytes to decrypt: %d",
+ intermediateBuffer.length());
#endif
- SecBuffer dataBuffer[4]{
- createSecBuffer(intermediateBuffer, SECBUFFER_DATA),
- createSecBuffer(nullptr, 0, SECBUFFER_EMPTY),
- createSecBuffer(nullptr, 0, SECBUFFER_EMPTY),
- createSecBuffer(nullptr, 0, SECBUFFER_EMPTY)
- };
- SecBufferDesc message{
- SECBUFFER_VERSION,
- ARRAYSIZE(dataBuffer),
- dataBuffer
- };
- auto status = DecryptMessage(&contextHandle, &message, 0, nullptr);
- if (status == SEC_E_OK || status == SEC_I_RENEGOTIATE || status == SEC_I_CONTEXT_EXPIRED) {
- // There can still be 0 output even if it succeeds, this is fine
- if (dataBuffer[1].cbBuffer > 0) {
- // It is always decrypted in-place.
- // But [0] is the STREAM_HEADER, [1] is the DATA and [2] is the STREAM_TRAILER.
- // The pointers in all of those still point into 'intermediateBuffer'.
- buffer.append(static_cast<char *>(dataBuffer[1].pvBuffer),
- dataBuffer[1].cbBuffer);
- totalRead += dataBuffer[1].cbBuffer;
+ SecBuffer dataBuffer[4]{
+ createSecBuffer(intermediateBuffer, SECBUFFER_DATA),
+ createSecBuffer(nullptr, 0, SECBUFFER_EMPTY),
+ createSecBuffer(nullptr, 0, SECBUFFER_EMPTY),
+ createSecBuffer(nullptr, 0, SECBUFFER_EMPTY)
+ };
+ SecBufferDesc message{
+ SECBUFFER_VERSION,
+ ARRAYSIZE(dataBuffer),
+ dataBuffer
+ };
+ auto status = DecryptMessage(&contextHandle, &message, 0, nullptr);
+ if (status == SEC_E_OK || status == SEC_I_RENEGOTIATE || status == SEC_I_CONTEXT_EXPIRED) {
+ // There can still be 0 output even if it succeeds, this is fine
+ if (dataBuffer[1].cbBuffer > 0) {
+ // It is always decrypted in-place.
+ // But [0] is the STREAM_HEADER, [1] is the DATA and [2] is the STREAM_TRAILER.
+ // The pointers in all of those still point into 'intermediateBuffer'.
+ buffer.append(static_cast<char *>(dataBuffer[1].pvBuffer),
+ dataBuffer[1].cbBuffer);
+ totalRead += dataBuffer[1].cbBuffer;
#ifdef QSSLSOCKET_DEBUG
- qCDebug(lcTlsBackendSchannel, "Decrypted %lu bytes. New read buffer size: %d",
- dataBuffer[1].cbBuffer, buffer.size());
+ qCDebug(lcTlsBackendSchannel, "Decrypted %lu bytes. New read buffer size: %d",
+ dataBuffer[1].cbBuffer, buffer.size());
#endif
- }
- if (dataBuffer[3].BufferType == SECBUFFER_EXTRA) {
- // https://docs.microsoft.com/en-us/windows/desktop/secauthn/extra-buffers-returned-by-schannel
- // dataBuffer[3].cbBuffer indicates the amount of bytes _NOT_ processed,
- // the rest need to be stored.
- retainExtraData(intermediateBuffer, dataBuffer[3]);
- } else {
- intermediateBuffer.resize(0);
- }
}
+ if (dataBuffer[3].BufferType == SECBUFFER_EXTRA) {
+ // https://docs.microsoft.com/en-us/windows/desktop/secauthn/extra-buffers-returned-by-schannel
+ // dataBuffer[3].cbBuffer indicates the amount of bytes _NOT_ processed,
+ // the rest need to be stored.
+ retainExtraData(intermediateBuffer, dataBuffer[3]);
+ } else {
+ intermediateBuffer.resize(0);
+ }
+ }
- if (status == SEC_E_INCOMPLETE_MESSAGE) {
- missingData = checkIncompleteData(dataBuffer[0]);
+ if (status == SEC_E_INCOMPLETE_MESSAGE) {
+ missingData = checkIncompleteData(dataBuffer[0]);
#ifdef QSSLSOCKET_DEBUG
- qCDebug(lcTlsBackendSchannel,
- "We didn't have enough data to decrypt anything, will try again!");
+ qCDebug(lcTlsBackendSchannel, "We didn't have enough data to decrypt anything, will try again!");
#endif
- // We try again, but if we don't get any more data then we leave
- hadIncompleteData = true;
- } else if (status == SEC_E_INVALID_HANDLE) {
- // I don't think this should happen, if it does we're done...
- qCWarning(lcTlsBackendSchannel, "The internal SSPI handle is invalid!");
- Q_UNREACHABLE();
- } else if (status == SEC_E_INVALID_TOKEN) {
- qCWarning(lcTlsBackendSchannel, "Got SEC_E_INVALID_TOKEN!");
- Q_UNREACHABLE(); // Happened once due to a bug, but shouldn't generally happen(?)
- } else if (status == SEC_E_MESSAGE_ALTERED) {
- // The message has been altered, disconnect now.
- shutdown = true; // skips sending the shutdown alert
- disconnectFromHost();
- setErrorAndEmit(d, QAbstractSocket::SslInternalError,
- schannelErrorToString(status));
- break;
- } else if (status == SEC_E_OUT_OF_SEQUENCE) {
- // @todo: I don't know if this one is actually "fatal"..
- // This path might never be hit as it seems this is for connection-oriented connections,
- // while SEC_E_MESSAGE_ALTERED is for stream-oriented ones (what we use).
- shutdown = true; // skips sending the shutdown alert
- disconnectFromHost();
- setErrorAndEmit(d, QAbstractSocket::SslInternalError,
- schannelErrorToString(status));
- break;
- } else if (status == SEC_I_CONTEXT_EXPIRED) {
- // 'remote' has initiated a shutdown
- disconnectFromHost();
- setErrorAndEmit(d, QAbstractSocket::RemoteHostClosedError,
- schannelErrorToString(status));
- break;
- } else if (status == SEC_I_RENEGOTIATE) {
- // 'remote' wants to renegotiate
+ // We try again, but if we don't get any more data then we leave
+ hadIncompleteData = true;
+ } else if (status == SEC_E_INVALID_HANDLE) {
+ // I don't think this should happen, if it does we're done...
+ qCWarning(lcTlsBackendSchannel, "The internal SSPI handle is invalid!");
+ Q_UNREACHABLE();
+ } else if (status == SEC_E_INVALID_TOKEN) {
+ qCWarning(lcTlsBackendSchannel, "Got SEC_E_INVALID_TOKEN!");
+ Q_UNREACHABLE(); // Happened once due to a bug, but shouldn't generally happen(?)
+ } else if (status == SEC_E_MESSAGE_ALTERED) {
+ // The message has been altered, disconnect now.
+ shutdown = true; // skips sending the shutdown alert
+ disconnectFromHost();
+ setErrorAndEmit(d, QAbstractSocket::SslInternalError,
+ schannelErrorToString(status));
+ break;
+ } else if (status == SEC_E_OUT_OF_SEQUENCE) {
+ // @todo: I don't know if this one is actually "fatal"..
+ // This path might never be hit as it seems this is for connection-oriented connections,
+ // while SEC_E_MESSAGE_ALTERED is for stream-oriented ones (what we use).
+ shutdown = true; // skips sending the shutdown alert
+ disconnectFromHost();
+ setErrorAndEmit(d, QAbstractSocket::SslInternalError,
+ schannelErrorToString(status));
+ break;
+ } else if (status == SEC_I_CONTEXT_EXPIRED) {
+ // 'remote' has initiated a shutdown
+ disconnectFromHost();
+ setErrorAndEmit(d, QAbstractSocket::RemoteHostClosedError,
+ schannelErrorToString(status));
+ break;
+ } else if (status == SEC_I_RENEGOTIATE) {
+ // 'remote' wants to renegotiate
#ifdef QSSLSOCKET_DEBUG
- qCDebug(lcTlsBackendSchannel, "The peer wants to renegotiate.");
+ qCDebug(lcTlsBackendSchannel, "The peer wants to renegotiate.");
#endif
- schannelState = SchannelState::Renegotiate;
- renegotiating = true;
+ schannelState = SchannelState::Renegotiate;
+ renegotiating = true;
- // We need to call 'continueHandshake' or else there's no guarantee it ever gets called
- continueHandshake();
- break;
- }
+ // We need to call 'continueHandshake' or else there's no guarantee it ever gets called
+ continueHandshake();
+ break;
}
+ }
- if (totalRead) {
- if (bool *readyReadEmittedPointer = d->readyReadPointer())
- *readyReadEmittedPointer = true;
- emit q->readyRead();
- emit q->channelReadyRead(0);
- }
+ if (totalRead) {
+ if (bool *readyReadEmittedPointer = d->readyReadPointer())
+ *readyReadEmittedPointer = true;
+ emit q->readyRead();
+ emit q->channelReadyRead(0);
}
}
@@ -1776,30 +1772,36 @@ void TlsCryptographSchannel::disconnectFromHost()
if (SecIsValidHandle(&contextHandle)) {
if (!shutdown) {
shutdown = true;
- if (plainSocket->state() != QAbstractSocket::UnconnectedState) {
- if (q->isEncrypted()) {
- // Read as much as possible because this is likely our last chance
- qint64 tempMax = d->maxReadBufferSize();
- d->setMaxReadBufferSize(0);
- transmit();
- d->setMaxReadBufferSize(tempMax);
- sendShutdown();
- }
+ if (plainSocket->state() != QAbstractSocket::UnconnectedState && q->isEncrypted()) {
+ sendShutdown();
+ transmit();
}
}
}
- if (plainSocket->state() != QAbstractSocket::UnconnectedState)
- plainSocket->disconnectFromHost();
+ plainSocket->disconnectFromHost();
}
void TlsCryptographSchannel::disconnected()
{
Q_ASSERT(d);
+ auto *plainSocket = d->plainTcpSocket();
+ Q_ASSERT(plainSocket);
+ d->setEncrypted(false);
shutdown = true;
- d->setEncrypted(false);
- deallocateContext();
- freeCredentialsHandle();
+ if (plainSocket->bytesAvailable() > 0 || hasUndecryptedData()) {
+ // Read as much as possible because this is likely our last chance
+ qint64 tempMax = d->maxReadBufferSize();
+ d->setMaxReadBufferSize(0); // Unlimited
+ transmit();
+ d->setMaxReadBufferSize(tempMax);
+ // Since there were bytes still available we don't want to deallocate
+ // our context yet. It will happen later, when the socket is re-used or
+ // destroyed.
+ } else {
+ deallocateContext();
+ freeCredentialsHandle();
+ }
}
QSslCipher TlsCryptographSchannel::sessionCipher() const
diff --git a/src/plugins/tls/securetransport/CMakeLists.txt b/src/plugins/tls/securetransport/CMakeLists.txt
index 0355049157..2d504cc1bf 100644
--- a/src/plugins/tls/securetransport/CMakeLists.txt
+++ b/src/plugins/tls/securetransport/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
qt_internal_add_plugin(QSecureTransportBackendPlugin
OUTPUT_NAME qsecuretransportbackend
CLASS_NAME QSecureTransportBackend
diff --git a/src/plugins/tls/securetransport/qtls_st.cpp b/src/plugins/tls/securetransport/qtls_st.cpp
index d2e5132752..39e2671692 100644
--- a/src/plugins/tls/securetransport/qtls_st.cpp
+++ b/src/plugins/tls/securetransport/qtls_st.cpp
@@ -315,42 +315,38 @@ void TlsCryptographSecureTransport::continueHandshake()
qCDebug(lcSecureTransport) << d->plainTcpSocket() << "connection encrypted";
#endif
-#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13_4, __IPHONE_11_0, __TVOS_11_0, __WATCHOS_4_0)
// Unlike OpenSSL, Secure Transport does not allow to negotiate protocols via
// a callback during handshake. We can only set our list of preferred protocols
// (and send it during handshake) and then receive what our peer has sent to us.
// And here we can finally try to find a match (if any).
const auto &configuration = q->sslConfiguration();
- if (__builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)) {
- const auto &requestedProtocols = configuration.allowedNextProtocols();
- if (const int requestedCount = requestedProtocols.size()) {
- QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNone);
- QTlsBackend::setNegotiatedProtocol(d, {});
-
- QCFType<CFArrayRef> cfArray;
- const OSStatus result = SSLCopyALPNProtocols(context, &cfArray);
- if (result == errSecSuccess && cfArray && CFArrayGetCount(cfArray)) {
- const int size = CFArrayGetCount(cfArray);
- QList<QString> peerProtocols(size);
- for (int i = 0; i < size; ++i)
- peerProtocols[i] = QString::fromCFString((CFStringRef)CFArrayGetValueAtIndex(cfArray, i));
-
- for (int i = 0; i < requestedCount; ++i) {
- const auto requestedName = QString::fromLatin1(requestedProtocols[i]);
- for (int j = 0; j < size; ++j) {
- if (requestedName == peerProtocols[j]) {
- QTlsBackend::setNegotiatedProtocol(d, requestedName.toLatin1());
- QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNegotiated);
- break;
- }
- }
- if (configuration.nextProtocolNegotiationStatus() == QSslConfiguration::NextProtocolNegotiationNegotiated)
+ const auto &requestedProtocols = configuration.allowedNextProtocols();
+ if (const int requestedCount = requestedProtocols.size()) {
+ QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNone);
+ QTlsBackend::setNegotiatedProtocol(d, {});
+
+ QCFType<CFArrayRef> cfArray;
+ const OSStatus result = SSLCopyALPNProtocols(context, &cfArray);
+ if (result == errSecSuccess && cfArray && CFArrayGetCount(cfArray)) {
+ const int size = CFArrayGetCount(cfArray);
+ QList<QString> peerProtocols(size);
+ for (int i = 0; i < size; ++i)
+ peerProtocols[i] = QString::fromCFString((CFStringRef)CFArrayGetValueAtIndex(cfArray, i));
+
+ for (int i = 0; i < requestedCount; ++i) {
+ const auto requestedName = QString::fromLatin1(requestedProtocols[i]);
+ for (int j = 0; j < size; ++j) {
+ if (requestedName == peerProtocols[j]) {
+ QTlsBackend::setNegotiatedProtocol(d, requestedName.toLatin1());
+ QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNegotiated);
break;
+ }
}
+ if (configuration.nextProtocolNegotiationStatus() == QSslConfiguration::NextProtocolNegotiationNegotiated)
+ break;
}
}
}
-#endif // QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE
if (!renegotiating)
emit q->encrypted();
@@ -694,35 +690,31 @@ bool TlsCryptographSecureTransport::initSslContext()
return false;
}
-#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13_4, __IPHONE_11_0, __TVOS_11_0, __WATCHOS_4_0)
- if (__builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)) {
- const auto protocolNames = configuration.allowedNextProtocols();
- QCFType<CFMutableArrayRef> cfNames(CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks));
- if (cfNames) {
- for (const QByteArray &name : protocolNames) {
- if (name.size() > 255) {
- qCWarning(lcSecureTransport) << "TLS ALPN extension" << name
- << "is too long and will be ignored.";
- continue;
- } else if (name.isEmpty()) {
- continue;
- }
- QCFString cfName(QString::fromLatin1(name).toCFString());
- CFArrayAppendValue(cfNames, cfName);
+ const auto protocolNames = configuration.allowedNextProtocols();
+ QCFType<CFMutableArrayRef> cfNames(CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks));
+ if (cfNames) {
+ for (const QByteArray &name : protocolNames) {
+ if (name.size() > 255) {
+ qCWarning(lcSecureTransport) << "TLS ALPN extension" << name
+ << "is too long and will be ignored.";
+ continue;
+ } else if (name.isEmpty()) {
+ continue;
}
+ QCFString cfName(QString::fromLatin1(name).toCFString());
+ CFArrayAppendValue(cfNames, cfName);
+ }
- if (CFArrayGetCount(cfNames)) {
- // Up to the application layer to check that negotiation
- // failed, and handle this non-TLS error, we do not handle
- // the result of this call as an error:
- if (SSLSetALPNProtocols(context, cfNames) != errSecSuccess)
- qCWarning(lcSecureTransport) << "SSLSetALPNProtocols failed - too long protocol names?";
- }
- } else {
- qCWarning(lcSecureTransport) << "failed to allocate ALPN names array";
+ if (CFArrayGetCount(cfNames)) {
+ // Up to the application layer to check that negotiation
+ // failed, and handle this non-TLS error, we do not handle
+ // the result of this call as an error:
+ if (SSLSetALPNProtocols(context, cfNames) != errSecSuccess)
+ qCWarning(lcSecureTransport) << "SSLSetALPNProtocols failed - too long protocol names?";
}
+ } else {
+ qCWarning(lcSecureTransport) << "failed to allocate ALPN names array";
}
-#endif // QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE
if (mode == QSslSocket::SslClientMode) {
// enable Server Name Indication (SNI)