summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/android/androidcontentfileengine.cpp2
-rw-r--r--src/plugins/platforms/android/extract.cpp1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaclipboard.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.h12
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.mm9
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm2
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.h2
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.mm1
-rw-r--r--src/plugins/platforms/cocoa/qmultitouch_mac_p.h9
-rw-r--r--src/plugins/platforms/cocoa/qnsview_dragging.mm2
-rw-r--r--src/plugins/platforms/ios/qiosapplicationdelegate.mm27
-rw-r--r--src/plugins/platforms/ios/qiosglobal.mm2
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm6
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.h4
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm53
-rw-r--r--src/plugins/platforms/wasm/qtloader.js3
-rw-r--r--src/plugins/platforms/wasm/qwasmclipboard.cpp110
-rw-r--r--src/plugins/platforms/wasm/qwasminputcontext.cpp309
-rw-r--r--src/plugins/platforms/wasm/qwasminputcontext.h23
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp181
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.h25
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style.cpp97
23 files changed, 417 insertions, 467 deletions
diff --git a/src/plugins/platforms/android/androidcontentfileengine.cpp b/src/plugins/platforms/android/androidcontentfileengine.cpp
index 6c02a73e7c8..7efe4d52d4c 100644
--- a/src/plugins/platforms/android/androidcontentfileengine.cpp
+++ b/src/plugins/platforms/android/androidcontentfileengine.cpp
@@ -1,7 +1,7 @@
// Copyright (C) 2019 Volker Krause <[email protected]>
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-// Qt-Security score:critical reason:file-handling
+// Qt-Security score:critical reason:data-parser
#include "androidcontentfileengine.h"
diff --git a/src/plugins/platforms/android/extract.cpp b/src/plugins/platforms/android/extract.cpp
index 48a2c4ecfaf..9160470e0cc 100644
--- a/src/plugins/platforms/android/extract.cpp
+++ b/src/plugins/platforms/android/extract.cpp
@@ -1,7 +1,6 @@
// Copyright (C) 2021 The Qt Company Ltd.
// Copyright (C) 2014 BogDan Vatra <[email protected]>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-// Qt-Security score:critical reason:data-serializing
#include <QtCore/QJniEnvironment>
diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.mm b/src/plugins/platforms/cocoa/qcocoaclipboard.mm
index 241faadbec0..0b84cae956b 100644
--- a/src/plugins/platforms/cocoa/qcocoaclipboard.mm
+++ b/src/plugins/platforms/cocoa/qcocoaclipboard.mm
@@ -3,6 +3,7 @@
#include "qcocoaclipboard.h"
+#include <QtGui/qguiapplication.h>
#include <QtGui/qutimimeconverter.h>
#ifndef QT_NO_CLIPBOARD
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.h b/src/plugins/platforms/cocoa/qcocoacursor.h
index 82c03573763..5c8aaeb1fde 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.h
+++ b/src/plugins/platforms/cocoa/qcocoacursor.h
@@ -4,9 +4,10 @@
#ifndef QWINDOWSCURSOR_H
#define QWINDOWSCURSOR_H
-#include <QtCore>
#include <qpa/qplatformcursor.h>
+#include <QtCore/qhash.h>
+
Q_FORWARD_DECLARE_OBJC_CLASS(NSCursor);
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.h b/src/plugins/platforms/cocoa/qcocoadrag.h
index c5c126ecf3e..09ba685078b 100644
--- a/src/plugins/platforms/cocoa/qcocoadrag.h
+++ b/src/plugins/platforms/cocoa/qcocoadrag.h
@@ -4,16 +4,12 @@
#ifndef QCOCOADRAG_H
#define QCOCOADRAG_H
-#include <QtGui>
#include <qpa/qplatformdrag.h>
-#include <private/qsimpledrag_p.h>
+#include <QtGui/private/qsimpledrag_p.h>
+#include <QtGui/private/qinternalmimedata_p.h>
#include <QtCore/private/qcore_mac_p.h>
-#include <QtGui/private/qdnd_p.h>
-#include <QtGui/private/qinternalmimedata_p.h>
-
-#include <QtCore/qeventloop.h>
Q_FORWARD_DECLARE_OBJC_CLASS(NSView);
Q_FORWARD_DECLARE_OBJC_CLASS(NSEvent);
@@ -21,6 +17,10 @@ Q_FORWARD_DECLARE_OBJC_CLASS(NSPasteboard);
QT_BEGIN_NAMESPACE
+class QDrag;
+class QEventLoop;
+class QMimeData;
+
class QCocoaDrag : public QPlatformDrag
{
public:
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm
index 64df903edcb..0f9df3f17ab 100644
--- a/src/plugins/platforms/cocoa/qcocoadrag.mm
+++ b/src/plugins/platforms/cocoa/qcocoadrag.mm
@@ -7,8 +7,15 @@
#include "qcocoadrag.h"
#include "qmacclipboard.h"
#include "qcocoahelpers.h"
-#include <QtGui/private/qcoregraphics_p.h>
+
+#include <QtGui/qfont.h>
+#include <QtGui/qfontmetrics.h>
+#include <QtGui/qpainter.h>
#include <QtGui/qutimimeconverter.h>
+#include <QtGui/private/qcoregraphics_p.h>
+#include <QtGui/private/qdnd_p.h>
+
+#include <QtCore/qeventloop.h>
#include <QtCore/private/qcore_mac_p.h>
#include <vector>
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 7ef958e5d9b..a569ce2ba4d 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -8,8 +8,6 @@
#include "qcocoahelpers.h"
#include "qnsview.h"
-#include <QtCore>
-#include <QtGui>
#include <qpa/qplatformscreen.h>
#include <private/qguiapplication_p.h>
#include <private/qwindow_p.h>
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.h b/src/plugins/platforms/cocoa/qmacclipboard.h
index 95267565f2d..dcc300797c9 100644
--- a/src/plugins/platforms/cocoa/qmacclipboard.h
+++ b/src/plugins/platforms/cocoa/qmacclipboard.h
@@ -4,10 +4,10 @@
#ifndef QMACCLIPBOARD_H
#define QMACCLIPBOARD_H
-#include <QtGui>
#include <QtGui/qutimimeconverter.h>
#include <QtCore/qpointer.h>
+#include <QtCore/qvariant.h>
#include <ApplicationServices/ApplicationServices.h>
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm
index edafa3b6a10..155c4aa826d 100644
--- a/src/plugins/platforms/cocoa/qmacclipboard.mm
+++ b/src/plugins/platforms/cocoa/qmacclipboard.mm
@@ -11,6 +11,7 @@
#include <QtGui/qbitmap.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qmetatype.h>
+#include <QtCore/qmimedata.h>
#include <QtCore/qdebug.h>
#include <QtCore/private/qcore_mac_p.h>
#include <QtGui/qguiapplication.h>
diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac_p.h b/src/plugins/platforms/cocoa/qmultitouch_mac_p.h
index d47d37729f5..63647246589 100644
--- a/src/plugins/platforms/cocoa/qmultitouch_mac_p.h
+++ b/src/plugins/platforms/cocoa/qmultitouch_mac_p.h
@@ -15,13 +15,12 @@
#ifndef QMULTITOUCH_MAC_P_H
#define QMULTITOUCH_MAC_P_H
-#include <QtCore/qglobal.h>
-#include <qpa/qwindowsysteminterface.h>
-#include <qhash.h>
-#include <QtCore>
+#include <QtCore/qhash.h>
+#include <QtCore/private/qcore_mac_p.h>
+
#include <QtGui/qpointingdevice.h>
-#include <QtCore/private/qcore_mac_p.h>
+#include <qpa/qwindowsysteminterface.h>
Q_FORWARD_DECLARE_OBJC_CLASS(NSTouch);
QT_FORWARD_DECLARE_OBJC_ENUM(NSTouchPhase, unsigned long);
diff --git a/src/plugins/platforms/cocoa/qnsview_dragging.mm b/src/plugins/platforms/cocoa/qnsview_dragging.mm
index b4c82ddc0d8..805cc7d59ea 100644
--- a/src/plugins/platforms/cocoa/qnsview_dragging.mm
+++ b/src/plugins/platforms/cocoa/qnsview_dragging.mm
@@ -3,6 +3,8 @@
// This file is included from qnsview.mm, and only used to organize the code
+#include <QtGui/qdrag.h>
+
@implementation QNSView (Dragging)
-(void)registerDragTypes
diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.mm b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
index a01c590bba8..990409f2d17 100644
--- a/src/plugins/platforms/ios/qiosapplicationdelegate.mm
+++ b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
@@ -73,22 +73,23 @@
UIWindowScene *windowScene = static_cast<UIWindowScene*>(scene);
QUIWindow *window = [[QUIWindow alloc] initWithWindowScene:windowScene];
+ window.rootViewController = [[[QIOSViewController alloc] initWithWindow:window] autorelease];
- QIOSScreen *screen = [&]{
- for (auto *screen : qGuiApp->screens()) {
- auto *platformScreen = static_cast<QIOSScreen*>(screen->handle());
-#if !defined(Q_OS_VISIONOS)
- if (platformScreen->uiScreen() == windowScene.screen)
-#endif
- return platformScreen;
- }
- Q_UNREACHABLE();
- }();
+ self.window = [window autorelease];
+}
- window.rootViewController = [[[QIOSViewController alloc]
- initWithWindow:window andScreen:screen] autorelease];
+- (void)windowScene:(UIWindowScene *)windowScene
+ didUpdateCoordinateSpace:(id<UICoordinateSpace>)previousCoordinateSpace
+ interfaceOrientation:(UIInterfaceOrientation)previousInterfaceOrientation
+ traitCollection:(UITraitCollection *)previousTraitCollection
+{
+ qCDebug(lcQpaWindowScene) << "Scene" << windowScene << "did update properties";
+ if (!self.window)
+ return;
- self.window = [window autorelease];
+ Q_ASSERT([self.window isKindOfClass:QUIWindow.class]);
+ auto *viewController = static_cast<QIOSViewController*>(self.window.rootViewController);
+ [viewController updatePlatformScreen];
}
- (void)sceneDidDisconnect:(UIScene *)scene
diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm
index 9ab490b2970..89a343061ee 100644
--- a/src/plugins/platforms/ios/qiosglobal.mm
+++ b/src/plugins/platforms/ios/qiosglobal.mm
@@ -13,7 +13,7 @@
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaApplication, "qt.qpa.application");
-Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods");
+Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods", QtCriticalMsg);
Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window");
Q_LOGGING_CATEGORY(lcQpaWindowScene, "qt.qpa.window.scene");
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 2926e6788ba..8544c497d43 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -640,8 +640,10 @@ void QIOSInputContext::update(Qt::InputMethodQueries updatedProperties)
// focus object. We try to detect code paths that fail this assertion and smooth
// over the situation by doing a manual update of the focus object.
if (qApp->focusObject() != m_imeState.focusObject && updatedProperties != Qt::ImQueryAll) {
- qWarning() << "stale focus object" << static_cast<void *>(m_imeState.focusObject)
- << ", doing manual update";
+ qCWarning(lcQpaInputMethods).verbosity(0) << "Updating input context" << updatedProperties
+ << "with last reported focus object" << m_imeState.focusObject
+ << "but qGuiApp reports" << qApp->focusObject()
+ << "which means someone failed to call QPlatformInputContext::setFocusObject()";
setFocusObject(qApp->focusObject());
return;
}
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.h b/src/plugins/platforms/ios/qiosviewcontroller.h
index 340cc6b6acb..b5ce88d6a33 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.h
+++ b/src/plugins/platforms/ios/qiosviewcontroller.h
@@ -12,10 +12,12 @@ QT_END_NAMESPACE
@interface QIOSViewController : UIViewController
-- (instancetype)initWithWindow:(UIWindow*)window andScreen:(QT_PREPEND_NAMESPACE(QIOSScreen) *)screen;
+- (instancetype)initWithWindow:(UIWindow*)window;
- (void)updateStatusBarProperties;
- (NSArray*)keyCommands;
- (void)handleShortcut:(UIKeyCommand*)keyCommand;
+- (void)updatePlatformScreen;
+
#ifndef Q_OS_TVOS
// UIViewController
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index b6b42c59b0b..169f8ae1754 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -231,11 +231,12 @@
@synthesize preferredStatusBarStyle;
#endif
-- (instancetype)initWithWindow:(UIWindow*)window andScreen:(QT_PREPEND_NAMESPACE(QIOSScreen) *)screen
+- (instancetype)initWithWindow:(UIWindow*)window
{
if (self = [self init]) {
self.window = window;
- self.platformScreen = screen;
+ self.platformScreen = nil;
+ [self updatePlatformScreen];
self.changingOrientation = NO;
#ifndef Q_OS_TVOS
@@ -314,6 +315,54 @@
// -------------------------------------------------------------------------
+- (void)updatePlatformScreen
+{
+ auto *windowScene = self.window.windowScene;
+
+ QIOSScreen *newPlatformScreen = [&]{
+ for (auto *screen : qGuiApp->screens()) {
+ auto *platformScreen = static_cast<QIOSScreen*>(screen->handle());
+#if !defined(Q_OS_VISIONOS)
+ if (platformScreen->uiScreen() == windowScene.screen)
+#endif
+ return platformScreen;
+ }
+ Q_UNREACHABLE();
+ }();
+
+ if (newPlatformScreen != self.platformScreen) {
+ QIOSScreen *oldPlatformScreen = self.platformScreen;
+ self.platformScreen = newPlatformScreen;
+
+ qCDebug(lcQpaWindow) << "View controller" << self << "moved from"
+ << oldPlatformScreen << "to" << newPlatformScreen;
+
+ QScreen *newScreen = newPlatformScreen ? newPlatformScreen->screen() : nullptr;
+
+ const bool isPrimaryScene = !qt_apple_sharedApplication().supportsMultipleScenes
+ && windowScene.session.role == UIWindowSceneSessionRoleApplication;
+
+ if (isPrimaryScene) {
+ // When we only have a single application-role scene we treat the
+ // active screen as the primary one, so that windows shown on the
+ // primary screen end up in our view controller.
+ QWindowSystemInterface::handlePrimaryScreenChanged(newPlatformScreen);
+ }
+
+ for (auto *window : qGuiApp->topLevelWindows()) {
+ // Move window to new screen if it was on the old screen,
+ // or if we're setting up the primary scene, in which case
+ // we want to adopt all existing windows to this screen.
+ if ((window->screen()->handle() == oldPlatformScreen)
+ || (isPrimaryScene && !oldPlatformScreen)) {
+ QWindowSystemInterface::handleWindowScreenChanged(window, newScreen);
+ }
+ }
+ }
+}
+
+// -------------------------------------------------------------------------
+
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration
{
self.changingOrientation = YES;
diff --git a/src/plugins/platforms/wasm/qtloader.js b/src/plugins/platforms/wasm/qtloader.js
index dc7f4583da8..909d8da8856 100644
--- a/src/plugins/platforms/wasm/qtloader.js
+++ b/src/plugins/platforms/wasm/qtloader.js
@@ -190,7 +190,8 @@ async function qtLoad(config)
const originalLocateFile = config.locateFile;
config.locateFile = filename => {
const originalLocatedFilename = originalLocateFile ? originalLocateFile(filename) : filename;
- if (originalLocatedFilename.startsWith('libQt6'))
+ if (originalLocatedFilename.startsWith(
+ 'libQt6')) // wasmqtdeploy rely on this behavior, update both in case of change
return `${config.qt.qtdir}/lib/${originalLocatedFilename}`;
return originalLocatedFilename;
}
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.cpp b/src/plugins/platforms/wasm/qwasmclipboard.cpp
index e5392f33cd7..44db371ca4d 100644
--- a/src/plugins/platforms/wasm/qwasmclipboard.cpp
+++ b/src/plugins/platforms/wasm/qwasmclipboard.cpp
@@ -48,10 +48,6 @@ static void commonCopyEvent(val event)
void QWasmClipboard::cut(val event)
{
- QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
- if (wasmInput && wasmInput->usingTextInput())
- return;
-
if (!QWasmIntegration::get()->getWasmClipboard()->hasClipboardApi()) {
// Send synthetic Ctrl+X to make the app cut data to Qt's clipboard
QWindowSystemInterface::handleKeyEvent(
@@ -63,10 +59,6 @@ void QWasmClipboard::cut(val event)
void QWasmClipboard::copy(val event)
{
- QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
- if (wasmInput && wasmInput->usingTextInput())
- return;
-
if (!QWasmIntegration::get()->getWasmClipboard()->hasClipboardApi()) {
// Send synthetic Ctrl+C to make the app copy data to Qt's clipboard
QWindowSystemInterface::handleKeyEvent(
@@ -77,10 +69,6 @@ void QWasmClipboard::copy(val event)
void QWasmClipboard::paste(val event)
{
- QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
- if (wasmInput && wasmInput->usingTextInput())
- return;
-
event.call<void>("preventDefault"); // prevent browser from handling drop event
QWasmIntegration::get()->getWasmClipboard()->sendClipboardData(event);
@@ -183,86 +171,42 @@ void QWasmClipboard::writeToClipboardApi()
{
Q_ASSERT(m_hasClipboardApi);
- // copy event
- // browser event handler detected ctrl c if clipboard API
- // or Qt call from keyboard event handler
-
- QMimeData *_mimes = mimeData(QClipboard::Clipboard);
- if (!_mimes)
+ QMimeData *mimeData = this->mimeData(QClipboard::Clipboard);
+ if (!mimeData)
return;
- emscripten::val clipboardWriteArray = emscripten::val::array();
- QByteArray ba;
-
- for (auto mimetype : _mimes->formats()) {
- // we need to treat binary and text differently, as the blob method below
- // fails for text mimetypes
- // ignore text types
-
- if (mimetype.contains("STRING", Qt::CaseSensitive) || mimetype.contains("TEXT", Qt::CaseSensitive))
- continue;
-
- if (_mimes->hasHtml()) { // prefer html over text
- ba = _mimes->html().toLocal8Bit();
- // force this mime
- mimetype = "text/html";
- } else if (mimetype.contains("text/plain")) {
- ba = _mimes->text().toLocal8Bit();
- } else if (mimetype.contains("image")) {
- QImage img = qvariant_cast<QImage>( _mimes->imageData());
+ // Support for plain text, html and images (png) are standardized,
+ // copy those to the clipboard data object.
+ emscripten::val clipboardData = emscripten::val::object();
+ for (const QString &mimetype: mimeData->formats()) {
+ if (mimetype == QLatin1String("text/plain")) {
+ emscripten::val text = mimeData->text().toEcmaString();
+ clipboardData.set(mimetype.toEcmaString(), text);
+ } else if (mimetype == QLatin1String("text/html")) {
+ emscripten::val html = mimeData->html().toEcmaString();
+ clipboardData.set(mimetype.toEcmaString(), html);
+ } else if (mimetype.contains(QLatin1String("image"))) {
+ // Serialize the Qt image data to browser supported png
+ QImage img = qvariant_cast<QImage>(mimeData->imageData());
+ QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
img.save(&buffer, "PNG");
- mimetype = "image/png"; // chrome only allows png
- // clipboard error "NotAllowedError" "Type application/x-qt-image not supported on write."
- // safari silently fails
- // so we use png internally for now
- } else {
- // DATA
- ba = _mimes->data(mimetype);
- }
- // Create file data Blob
- const char *content = ba.data();
- int dataLength = ba.length();
- if (dataLength < 1) {
- qDebug() << "no content found";
- return;
+ qstdweb::Blob blob = qstdweb::Blob::fromArrayBuffer(qstdweb::Uint8Array::copyFrom(ba).buffer());
+ clipboardData.set(std::string("image/png"), blob.val());
}
-
- emscripten::val document = emscripten::val::global("document");
- emscripten::val window = emscripten::val::global("window");
-
- emscripten::val fileContentView =
- emscripten::val(emscripten::typed_memory_view(dataLength, content));
- emscripten::val fileContentCopy = emscripten::val::global("ArrayBuffer").new_(dataLength);
- emscripten::val fileContentCopyView =
- emscripten::val::global("Uint8Array").new_(fileContentCopy);
- fileContentCopyView.call<void>("set", fileContentView);
-
- emscripten::val contentArray = emscripten::val::array();
- contentArray.call<void>("push", fileContentCopyView);
-
- // we have a blob, now create a ClipboardItem
- emscripten::val type = emscripten::val::array();
- type.set("type", mimetype.toEcmaString());
-
- emscripten::val contentBlob = emscripten::val::global("Blob").new_(contentArray, type);
-
- emscripten::val clipboardItemObject = emscripten::val::object();
- clipboardItemObject.set(mimetype.toEcmaString(), contentBlob);
-
- val clipboardItemData = val::global("ClipboardItem").new_(clipboardItemObject);
-
- clipboardWriteArray.call<void>("push", clipboardItemData);
-
- // Clipboard write is only supported with one ClipboardItem at the moment
- // but somehow this still works?
- // break;
}
- val navigator = val::global("navigator");
+ // Return if there is no data (creating an empty ClipboardItem is an error)
+ if (val::global("Object").call<val>("keys", clipboardData)["length"].as<int>() == 0)
+ return;
+ // Write a single clipboard item containing the data formats to the clipboard
+ emscripten::val clipboardItem = val::global("ClipboardItem").new_(clipboardData);
+ emscripten::val clipboardItemArray = emscripten::val::array();
+ clipboardItemArray.call<void>("push", clipboardItem);
+ val navigator = val::global("navigator");
qstdweb::Promise::make(
navigator["clipboard"], "write",
{
@@ -272,7 +216,7 @@ void QWasmClipboard::writeToClipboardApi()
<< QString::fromStdString(error["message"].as<std::string>());
}
},
- clipboardWriteArray);
+ clipboardItemArray);
}
void QWasmClipboard::writeToClipboard()
diff --git a/src/plugins/platforms/wasm/qwasminputcontext.cpp b/src/plugins/platforms/wasm/qwasminputcontext.cpp
index 2df7066b8e2..191e2947629 100644
--- a/src/plugins/platforms/wasm/qwasminputcontext.cpp
+++ b/src/plugins/platforms/wasm/qwasminputcontext.cpp
@@ -25,105 +25,88 @@ void QWasmInputContext::inputCallback(emscripten::val event)
{
qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO << "isComposing : " << event["isComposing"].as<bool>();
- QString inputStr = (event["data"] != emscripten::val::null()
- && event["data"] != emscripten::val::undefined()) ?
- QString::fromStdString(event["data"].as<std::string>()) : QString();
-
- QWasmInputContext *wasmInput =
- reinterpret_cast<QWasmInputContext *>(event["target"]["data-qinputcontext"].as<quintptr>());
-
emscripten::val inputType = event["inputType"];
- if (inputType != emscripten::val::null()
- && inputType != emscripten::val::undefined()) {
- const auto inputTypeString = inputType.as<std::string>();
- // There are many inputTypes for InputEvent
- // https://www.w3.org/TR/input-events-1/
- // Some of them should be implemented here later.
- qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO << "inputType : " << inputTypeString;
- if (!inputTypeString.compare("deleteContentBackward")) {
- QWindowSystemInterface::handleKeyEvent(0,
- QEvent::KeyPress,
- Qt::Key_Backspace,
- Qt::NoModifier);
- QWindowSystemInterface::handleKeyEvent(0,
- QEvent::KeyRelease,
- Qt::Key_Backspace,
- Qt::NoModifier);
- event.call<void>("stopImmediatePropagation");
- return;
- } else if (!inputTypeString.compare("deleteContentForward")) {
- QWindowSystemInterface::handleKeyEvent(0,
- QEvent::KeyPress,
- Qt::Key_Delete,
- Qt::NoModifier);
- QWindowSystemInterface::handleKeyEvent(0,
- QEvent::KeyRelease,
- Qt::Key_Delete,
- Qt::NoModifier);
- event.call<void>("stopImmediatePropagation");
- return;
- } else if (!inputTypeString.compare("insertCompositionText")) {
- qCDebug(qLcQpaWasmInputContext) << "inputString : " << inputStr;
- wasmInput->insertPreedit();
- event.call<void>("stopImmediatePropagation");
- return;
- } else if (!inputTypeString.compare("insertReplacementText")) {
- qCDebug(qLcQpaWasmInputContext) << "inputString : " << inputStr;
- //auto ranges = event.call<emscripten::val>("getTargetRanges");
- //qCDebug(qLcQpaWasmInputContext) << ranges["length"].as<int>();
- // WA For Korean IME
- // insertReplacementText should have targetRanges but
- // Safari cannot have it and just it seems to be supposed
- // to replace previous input.
- wasmInput->insertText(inputStr, true);
-
- event.call<void>("stopImmediatePropagation");
- return;
- } else if (!inputTypeString.compare("deleteCompositionText")) {
- wasmInput->setPreeditString("", 0);
- wasmInput->insertPreedit();
- event.call<void>("stopImmediatePropagation");
- return;
- } else if (!inputTypeString.compare("insertFromComposition")) {
- wasmInput->setPreeditString(inputStr, 0);
- wasmInput->insertPreedit();
- event.call<void>("stopImmediatePropagation");
- return;
- } else if (!inputTypeString.compare("insertText")) {
- wasmInput->insertText(inputStr);
- event.call<void>("stopImmediatePropagation");
+ if (inputType.isNull() || inputType.isUndefined())
+ return;
+ const auto inputTypeString = inputType.as<std::string>();
+
+ emscripten::val inputData = event["data"];
+ QString inputStr = (!inputData.isNull() && !inputData.isUndefined())
+ ? QString::fromEcmaString(inputData) : QString();
+
+ // There are many inputTypes for InputEvent
+ // https://www.w3.org/TR/input-events-1/
+ // Some of them should be implemented here later.
+ qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO << "inputType : " << inputTypeString;
+ if (!inputTypeString.compare("deleteContentBackward")) {
+ QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
+ QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyRelease, Qt::Key_Backspace, Qt::NoModifier);
+ event.call<void>("stopImmediatePropagation");
+ return;
+ } else if (!inputTypeString.compare("deleteContentForward")) {
+ QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier);
+ QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyRelease, Qt::Key_Delete, Qt::NoModifier);
+ event.call<void>("stopImmediatePropagation");
+ return;
+ } else if (!inputTypeString.compare("insertCompositionText")) {
+ qCDebug(qLcQpaWasmInputContext) << "inputString : " << inputStr;
+ insertPreedit();
+ event.call<void>("stopImmediatePropagation");
+ return;
+ } else if (!inputTypeString.compare("insertReplacementText")) {
+ qCDebug(qLcQpaWasmInputContext) << "inputString : " << inputStr;
+ //auto ranges = event.call<emscripten::val>("getTargetRanges");
+ //qCDebug(qLcQpaWasmInputContext) << ranges["length"].as<int>();
+ // WA For Korean IME
+ // insertReplacementText should have targetRanges but
+ // Safari cannot have it and just it seems to be supposed
+ // to replace previous input.
+ insertText(inputStr, true);
+
+ event.call<void>("stopImmediatePropagation");
+ return;
+ } else if (!inputTypeString.compare("deleteCompositionText")) {
+ setPreeditString("", 0);
+ insertPreedit();
+ event.call<void>("stopImmediatePropagation");
+ return;
+ } else if (!inputTypeString.compare("insertFromComposition")) {
+ setPreeditString(inputStr, 0);
+ insertPreedit();
+ event.call<void>("stopImmediatePropagation");
+ return;
+ } else if (!inputTypeString.compare("insertText")) {
+ insertText(inputStr);
+ event.call<void>("stopImmediatePropagation");
#if QT_CONFIG(clipboard)
- } else if (!inputTypeString.compare("insertFromPaste")) {
- wasmInput->insertText(QGuiApplication::clipboard()->text());
- event.call<void>("stopImmediatePropagation");
- // These can be supported here,
- // But now, keyCallback in QWasmWindow
- // will take them as exceptions.
- //} else if (!inputTypeString.compare("deleteByCut")) {
+ } else if (!inputTypeString.compare("insertFromPaste")) {
+ insertText(QGuiApplication::clipboard()->text());
+ event.call<void>("stopImmediatePropagation");
+ // These can be supported here,
+ // But now, keyCallback in QWasmWindow
+ // will take them as exceptions.
+ //} else if (!inputTypeString.compare("deleteByCut")) {
#endif
- } else {
- qCWarning(qLcQpaWasmInputContext) << Q_FUNC_INFO << "inputType \"" << inputType.as<std::string>() << "\" is not supported in Qt yet";
- }
+ } else {
+ qCWarning(qLcQpaWasmInputContext) << Q_FUNC_INFO << "inputType \"" <<
+ inputType.as<std::string>() << "\" is not supported in Qt yet";
}
}
void QWasmInputContext::compositionEndCallback(emscripten::val event)
{
- const auto inputStr = QString::fromStdString(event["data"].as<std::string>());
+ const auto inputStr = QString::fromEcmaString(event["data"]);
qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO << inputStr;
- QWasmInputContext *wasmInput =
- reinterpret_cast<QWasmInputContext *>(event["target"]["data-qinputcontext"].as<quintptr>());
-
- if (wasmInput->preeditString().isEmpty())
+ if (preeditString().isEmpty())
return;
- if (inputStr != wasmInput->preeditString()) {
+ if (inputStr != preeditString()) {
qCWarning(qLcQpaWasmInputContext) << Q_FUNC_INFO
<< "Composition string" << inputStr
- << "is differ from" << wasmInput->preeditString();
+ << "is differ from" << preeditString();
}
- wasmInput->commitPreeditAndClear();
+ commitPreeditAndClear();
}
void QWasmInputContext::compositionStartCallback(emscripten::val event)
@@ -151,19 +134,15 @@ static void beforeInputCallback(emscripten::val event)
void QWasmInputContext::compositionUpdateCallback(emscripten::val event)
{
- const auto compositionStr = QString::fromStdString(event["data"].as<std::string>());
+ const auto compositionStr = QString::fromEcmaString(event["data"]);
qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO << compositionStr;
- QWasmInputContext *wasmInput =
- reinterpret_cast<QWasmInputContext *>(event["target"]["data-qinputcontext"].as<quintptr>());
-
// WA for IOS.
// Not sure now because I cannot test it anymore.
// int replaceSize = 0;
// emscripten::val win = emscripten::val::global("window");
// emscripten::val sel = win.call<emscripten::val>("getSelection");
-// if (sel != emscripten::val::null()
-// && sel != emscripten::val::undefined()
+// if (!sel.isNull() && !sel.isUndefined()
// && sel["rangeCount"].as<int>() > 0) {
// QInputMethodQueryEvent queryEvent(Qt::ImQueryAll);
// QCoreApplication::sendEvent(QGuiApplication::focusObject(), &queryEvent);
@@ -172,8 +151,8 @@ void QWasmInputContext::compositionUpdateCallback(emscripten::val event)
// qCDebug(qLcQpaWasmInputContext) << "Qt text before cursor: " << queryEvent.value(Qt::ImTextBeforeCursor).toString();
// qCDebug(qLcQpaWasmInputContext) << "Qt text after cursor: " << queryEvent.value(Qt::ImTextAfterCursor).toString();
//
-// const QString &selectedStr = QString::fromUtf8(sel.call<emscripten::val>("toString").as<std::string>());
-// const auto &preeditStr = wasmInput->preeditString();
+// const QString &selectedStr = QString::fromEcmaString(sel.call<emscripten::val>("toString"));
+// const auto &preeditStr = preeditString();
// qCDebug(qLcQpaWasmInputContext) << "Selection.type : " << sel["type"].as<std::string>();
// qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO << "Selected: " << selectedStr;
// qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO << "PreeditString: " << preeditStr;
@@ -189,90 +168,13 @@ void QWasmInputContext::compositionUpdateCallback(emscripten::val event)
// qCDebug(qLcQpaWasmInputContext) << "Range.endOffset : " << range["endOffset"].as<int>();
// }
//
-// wasmInput->setPreeditString(compositionStr, replaceSize);
- wasmInput->setPreeditString(compositionStr, 0);
-}
-
-#if QT_CONFIG(clipboard)
-static void copyCallback(emscripten::val event)
-{
- qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO;
-
- QClipboard *clipboard = QGuiApplication::clipboard();
- QString inputStr = clipboard->text();
- qCDebug(qLcQpaWasmInputContext) << "QClipboard : " << inputStr;
- event["clipboardData"].call<void>("setData",
- emscripten::val("text/plain"),
- inputStr.toStdString());
- event.call<void>("preventDefault");
- event.call<void>("stopImmediatePropagation");
-}
-
-static void cutCallback(emscripten::val event)
-{
- qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO;
-
- QClipboard *clipboard = QGuiApplication::clipboard();
- QString inputStr = clipboard->text();
- qCDebug(qLcQpaWasmInputContext) << "QClipboard : " << inputStr;
- event["clipboardData"].call<void>("setData",
- emscripten::val("text/plain"),
- inputStr.toStdString());
- event.call<void>("preventDefault");
- event.call<void>("stopImmediatePropagation");
+// setPreeditString(compositionStr, replaceSize);
+ setPreeditString(compositionStr, 0);
}
-static void pasteCallback(emscripten::val event)
-{
- qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO;
-
- emscripten::val clipboardData = event["clipboardData"].call<emscripten::val>("getData", emscripten::val("text/plain"));
- QString clipboardStr = QString::fromStdString(clipboardData.as<std::string>());
- qCDebug(qLcQpaWasmInputContext) << "wasm clipboard : " << clipboardStr;
- QClipboard *clipboard = QGuiApplication::clipboard();
- if (clipboard->text() != clipboardStr)
- clipboard->setText(clipboardStr);
-
- // propagate to input event (insertFromPaste)
-}
-#endif // QT_CONFIG(clipboard)
-
QWasmInputContext::QWasmInputContext()
{
qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO;
- emscripten::val document = emscripten::val::global("document");
- // This 'input' can be an issue to handle multiple lines,
- // 'textarea' can be used instead.
- m_inputElement = document.call<emscripten::val>("createElement", std::string("input"));
- m_inputElement.set("type", "text");
- m_inputElement.set("contenteditable","true");
- m_inputElement.call<void>("setAttribute", std::string("aria-hidden"), std::string("true"));
-
- m_inputElement["style"].set("position", "absolute");
- m_inputElement["style"].set("left", 0);
- m_inputElement["style"].set("top", 0);
- m_inputElement["style"].set("opacity", 0);
- m_inputElement["style"].set("display", "");
- m_inputElement["style"].set("z-index", -2);
- m_inputElement["style"].set("width", "1px");
- m_inputElement["style"].set("height", "1px");
-
- m_inputElement.set("data-qinputcontext",
- emscripten::val(quintptr(reinterpret_cast<void *>(this))));
- emscripten::val body = document["body"];
- body.call<void>("appendChild", m_inputElement);
-
- m_inputCallback = QWasmEventHandler(m_inputElement, "input", QWasmInputContext::inputCallback);
- m_compositionEndCallback = QWasmEventHandler(m_inputElement, "compositionend", QWasmInputContext::compositionEndCallback);
- m_compositionStartCallback = QWasmEventHandler(m_inputElement, "compositionstart", QWasmInputContext::compositionStartCallback);
- m_compositionUpdateCallback = QWasmEventHandler(m_inputElement, "compositionupdate", QWasmInputContext::compositionUpdateCallback);
-
-#if QT_CONFIG(clipboard)
- // Clipboard for InputContext
- m_clipboardCut = QWasmEventHandler(m_inputElement, "cut", cutCallback);
- m_clipboardCopy = QWasmEventHandler(m_inputElement, "copy", copyCallback);
- m_clipboardPaste = QWasmEventHandler(m_inputElement, "paste", pasteCallback);
-#endif
}
QWasmInputContext::~QWasmInputContext()
@@ -303,6 +205,9 @@ void QWasmInputContext::showInputPanel()
void QWasmInputContext::updateGeometry()
{
+ if (m_inputElement.isNull())
+ return;
+
const QWindow *focusWindow = QGuiApplication::focusWindow();
if (!m_focusObject || !focusWindow || !m_inputMethodAccepted) {
m_inputElement["style"].set("left", "0px");
@@ -312,23 +217,12 @@ void QWasmInputContext::updateGeometry()
Q_ASSERT(m_focusObject);
Q_ASSERT(m_inputMethodAccepted);
- // Set the geometry
- QPoint globalPos;
- const QRect cursorRectangle = QPlatformInputContext::cursorRectangle().toRect();
- if (cursorRectangle.isValid()) {
- qCDebug(qLcQpaWasmInputContext)
- << Q_FUNC_INFO << "cursorRectangle: " << cursorRectangle;
- globalPos = focusWindow->mapToGlobal(cursorRectangle.topLeft());
- if (globalPos.x() > 0)
- globalPos.setX(globalPos.x() - 1);
- if (globalPos.y() > 0)
- globalPos.setY(globalPos.y() - 1);
- }
-
- const auto styleLeft = std::to_string(globalPos.x()) + "px";
- const auto styleTop = std::to_string(globalPos.y()) + "px";
- m_inputElement["style"].set("left", styleLeft);
- m_inputElement["style"].set("top", styleTop);
+ const QRect inputItemRectangle = QPlatformInputContext::inputItemRectangle().toRect();
+ qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO << "propagating inputItemRectangle:" << inputItemRectangle;
+ m_inputElement["style"].set("left", std::to_string(inputItemRectangle.x()) + "px");
+ m_inputElement["style"].set("top", std::to_string(inputItemRectangle.y()) + "px");
+ m_inputElement["style"].set("width", std::to_string(inputItemRectangle.width()) + "px");
+ m_inputElement["style"].set("height", std::to_string(inputItemRectangle.height()) + "px");
}
}
@@ -341,16 +235,21 @@ void QWasmInputContext::updateInputElement()
updateGeometry();
// If there is no focus object, or no visible input panel, remove focus
- const QWindow *focusWindow = QGuiApplication::focusWindow();
+ QWasmWindow *focusWindow = QWasmWindow::fromWindow(QGuiApplication::focusWindow());
if (!m_focusObject || !focusWindow || !m_inputMethodAccepted) {
- m_inputElement.set("value", "");
+ if (!m_inputElement.isNull()) {
+ m_inputElement.set("value", "");
+ m_inputElement.set("inputMode", std::string("none"));
+ }
- if (QWasmWindow *wasmwindow = QWasmWindow::fromWindow(focusWindow))
- wasmwindow->focus();
- else
- m_inputElement.call<void>("blur");
+ if (focusWindow) {
+ focusWindow->focus();
+ } else {
+ if (!m_inputElement.isNull())
+ m_inputElement.call<void>("blur");
+ }
- m_inputElement.set("inputMode", std::string("none"));
+ m_inputElement = emscripten::val::null();
return;
}
@@ -358,6 +257,8 @@ void QWasmInputContext::updateInputElement()
Q_ASSERT(m_focusObject);
Q_ASSERT(m_inputMethodAccepted);
+ m_inputElement = focusWindow->inputElement();
+
qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO << QRectF::fromDOMRect(m_inputElement.call<emscripten::val>("getBoundingClientRect"));
// Set the text input
@@ -375,7 +276,15 @@ void QWasmInputContext::updateInputElement()
m_inputElement.set("selectionStart", queryEvent.value(Qt::ImAnchorPosition).toUInt());
m_inputElement.set("selectionEnd", queryEvent.value(Qt::ImCursorPosition).toUInt());
+ QInputMethodQueryEvent query((Qt::InputMethodQueries(Qt::ImHints)));
+ QCoreApplication::sendEvent(m_focusObject, &query);
+ if (Qt::InputMethodHints(query.value(Qt::ImHints).toInt()).testFlag(Qt::ImhHiddenText))
+ m_inputElement.set("type", "password");
+ else
+ m_inputElement.set("type", "text");
+
m_inputElement.set("inputMode", std::string("text"));
+
m_inputElement.call<void>("focus");
}
@@ -383,16 +292,6 @@ void QWasmInputContext::setFocusObject(QObject *object)
{
qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO << object << inputMethodAccepted();
- QInputMethodQueryEvent query(Qt::InputMethodQueries(Qt::ImEnabled | Qt::ImHints));
- QCoreApplication::sendEvent(object, &query);
- if (query.value(Qt::ImEnabled).toBool()
- && Qt::InputMethodHints(query.value(Qt::ImHints).toInt()).testFlag(Qt::ImhHiddenText)) {
- m_inputElement.set("type", "password");
- } else {
- if (m_inputElement["type"].as<std::string>() != std::string("text"))
- m_inputElement.set("type", "text");
- }
-
// Commit the previous composition before change m_focusObject
if (m_focusObject && !m_preeditString.isEmpty())
commitPreeditAndClear();
diff --git a/src/plugins/platforms/wasm/qwasminputcontext.h b/src/plugins/platforms/wasm/qwasminputcontext.h
index 72476adfe1b..6d24c7fea0d 100644
--- a/src/plugins/platforms/wasm/qwasminputcontext.h
+++ b/src/plugins/platforms/wasm/qwasminputcontext.h
@@ -35,38 +35,33 @@ public:
void setPreeditString(QString preeditStr, int replaceSize);
void insertPreedit();
void commitPreeditAndClear();
- emscripten::val m_inputElement = emscripten::val::null();
void insertText(QString inputStr, bool replace = false);
- QWasmEventHandler m_inputCallback;
- QWasmEventHandler m_compositionEndCallback;
- QWasmEventHandler m_compositionStartCallback;
- QWasmEventHandler m_compositionUpdateCallback;
-
bool usingTextInput() const { return m_inputMethodAccepted; }
void setFocusObject(QObject *object) override;
- static void inputCallback(emscripten::val event);
- static void compositionEndCallback(emscripten::val event);
- static void compositionStartCallback(emscripten::val event);
- static void compositionUpdateCallback(emscripten::val event);
+ void inputCallback(emscripten::val event);
+ void compositionEndCallback(emscripten::val event);
+ void compositionStartCallback(emscripten::val event);
+ void compositionUpdateCallback(emscripten::val event);
void updateGeometry();
+ bool isActive() const {
+ return m_focusObject && m_inputMethodAccepted;
+ }
+
private:
void updateInputElement();
private:
- QWasmEventHandler m_clipboardCut;
- QWasmEventHandler m_clipboardCopy;
- QWasmEventHandler m_clipboardPaste;
-
QString m_preeditString;
int m_replaceSize = 0;
bool m_inputMethodAccepted = false;
QObject *m_focusObject = nullptr;
+ emscripten::val m_inputElement = emscripten::val::null();
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp
index d690bcfe10a..d27385be723 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.cpp
+++ b/src/plugins/platforms/wasm/qwasmwindow.cpp
@@ -51,7 +51,10 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport,
m_decoratedWindow(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
m_window(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
m_a11yContainer(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
- m_canvas(m_document.call<emscripten::val>("createElement", emscripten::val("canvas")))
+ m_canvas(m_document.call<emscripten::val>("createElement", emscripten::val("canvas"))),
+ m_focusHelper(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
+ m_inputElement(m_document.call<emscripten::val>("createElement", emscripten::val("input")))
+
{
m_decoratedWindow.set("className", "qt-decorated-window");
m_decoratedWindow["style"].set("display", std::string("none"));
@@ -80,17 +83,6 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport,
m_canvas["classList"].call<void>("add", emscripten::val("qt-window-canvas"));
- // Set contentEditable for two reasons;
- // 1) so that the window gets clipboard events,
- // 2) For applications who will handle keyboard events, but without having inputMethodAccepted()
- //
- // Set inputMode to none to avoid keyboard popping up on push buttons
- // This is a tradeoff, we are not able to separate between a push button and
- // a widget that reads keyboard events.
- m_canvas.call<void>("setAttribute", std::string("inputmode"), std::string("none"));
- m_canvas.call<void>("setAttribute", std::string("contenteditable"), std::string("true"));
- m_canvas["style"].set("outline", std::string("none"));
-
#if QT_CONFIG(clipboard)
if (QWasmClipboard::shouldInstallWindowEventHandlers()) {
m_cutCallback = QWasmEventHandler(m_canvas, "cut", QWasmClipboard::cut);
@@ -99,9 +91,37 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport,
}
#endif
- // Set inputMode to none to stop the mobile keyboard from opening
- // when the user clicks on the window.
- m_window.set("inputMode", std::string("none"));
+ // Set up m_focusHelper, which is an invisible child element of the window which takes
+ // focus on behalf of the window any time the window has focus in general, but none
+ // of the special child elements such as the inputElment or a11y elements have focus.
+ // Set inputMode=none set to prevent the virtual keyboard from popping up.
+ m_focusHelper["classList"].call<void>("add", emscripten::val("qt-window-focus-helper"));
+ m_focusHelper.set("inputMode", std::string("none"));
+ m_focusHelper.call<void>("setAttribute", std::string("aria-hidden"), std::string("true"));
+ m_focusHelper.call<void>("setAttribute", std::string("contenteditable"), std::string("true"));
+ m_focusHelper["style"].set("position", "absolute");
+ m_focusHelper["style"].set("left", 0);
+ m_focusHelper["style"].set("top", 0);
+ m_focusHelper["style"].set("width", "1px");
+ m_focusHelper["style"].set("height", "1px");
+ m_focusHelper["style"].set("z-index", -2);
+ m_focusHelper["style"].set("opacity", 0);
+ m_window.call<void>("appendChild", m_focusHelper);
+
+ // Set up m_inputElement, which takes focus whenever a Qt text input UI element has
+ // foucus.
+ m_inputElement["classList"].call<void>("add", emscripten::val("qt-window-input-element"));
+ m_inputElement.set("type", "text");
+ m_inputElement.call<void>("setAttribute", std::string("aria-hidden"), std::string("true"));
+ m_inputElement["style"].set("position", "absolute");
+ m_inputElement["style"].set("left", 0);
+ m_inputElement["style"].set("top", 0);
+ m_inputElement["style"].set("width", "1px");
+ m_inputElement["style"].set("height", "1px");
+ m_inputElement["style"].set("z-index", -2);
+ m_inputElement["style"].set("opacity", 0);
+ m_inputElement["style"].set("display", "");
+ m_window.call<void>("appendChild", m_inputElement);
// Hide the canvas from screen readers.
m_canvas.call<void>("setAttribute", std::string("aria-hidden"), std::string("true"));
@@ -193,21 +213,20 @@ void QWasmWindow::registerEventHandlers()
m_wheelEventCallback = QWasmEventHandler(m_window, "wheel",
[this](emscripten::val event) { this->handleWheelEvent(event); });
- QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
- if (wasmInput) {
- m_keyDownCallbackForInputContext =
- QWasmEventHandler(wasmInput->m_inputElement, "keydown",
- [this](emscripten::val event) { this->handleKeyForInputContextEvent(EventType::KeyDown, event); });
- m_keyUpCallbackForInputContext =
- QWasmEventHandler(wasmInput->m_inputElement, "keyup",
- [this](emscripten::val event) { this->handleKeyForInputContextEvent(EventType::KeyUp, event); });
- }
-
- m_keyDownCallback = QWasmEventHandler(m_canvas, "keydown",
+ m_keyDownCallback = QWasmEventHandler(m_window, "keydown",
[this](emscripten::val event) { this->handleKeyEvent(KeyEvent(EventType::KeyDown, event, m_deadKeySupport)); });
- m_keyUpCallback =QWasmEventHandler(m_canvas, "keyup",
+ m_keyUpCallback =QWasmEventHandler(m_window, "keyup",
[this](emscripten::val event) {this->handleKeyEvent(KeyEvent(EventType::KeyUp, event, m_deadKeySupport)); });
-}
+
+ m_inputCallback = QWasmEventHandler(m_window, "input",
+ [this](emscripten::val event){ handleInputEvent(event); });
+ m_compositionUpdateCallback = QWasmEventHandler(m_window, "compositionupdate",
+ [this](emscripten::val event){ handleCompositionUpdateEvent(event); });
+ m_compositionStartCallback = QWasmEventHandler(m_window, "compositionstart",
+ [this](emscripten::val event){ handleCompositionStartEvent(event); });
+ m_compositionEndCallback = QWasmEventHandler(m_window, "compositionend",
+ [this](emscripten::val event){ handleCompositionEndEvent(event); });
+ }
QWasmWindow::~QWasmWindow()
{
@@ -624,10 +643,15 @@ void QWasmWindow::commitParent(QWasmWindowTreeNode *parent)
void QWasmWindow::handleKeyEvent(const KeyEvent &event)
{
- qCDebug(qLcQpaWasmInputContext) << "processKey as KeyEvent";
- if (processKey(event)) {
- event.webEvent.call<void>("preventDefault");
- event.webEvent.call<void>("stopPropagation");
+ qCDebug(qLcQpaWasmInputContext) << "handleKeyEvent";
+
+ if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive()) {
+ handleKeyForInputContextEvent(event);
+ } else {
+ if (processKey(event)) {
+ event.webEvent.call<void>("preventDefault");
+ event.webEvent.call<void>("stopPropagation");
+ }
}
}
@@ -658,7 +682,7 @@ bool QWasmWindow::processKey(const KeyEvent &event)
#endif
}
-void QWasmWindow::handleKeyForInputContextEvent(EventType eventType, const emscripten::val &event)
+void QWasmWindow::handleKeyForInputContextEvent(const KeyEvent &keyEvent)
{
//
// Things to consider:
@@ -668,40 +692,43 @@ void QWasmWindow::handleKeyForInputContextEvent(EventType eventType, const emscr
// complex (i.e Chinese et al) input handling
// Multiline text edit backspace at start of line
//
- const QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
- if (wasmInput) {
+ emscripten::val event = keyEvent.webEvent;
+ bool useInputContext = [event]() -> bool {
+ const QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
+ if (!wasmInput)
+ return false;
+
const auto keyString = QString::fromStdString(event["key"].as<std::string>());
qCDebug(qLcQpaWasmInputContext) << "Key callback" << keyString << keyString.size();
- if (keyString == "Unidentified") {
- // Android makes a bunch of KeyEvents as "Unidentified"
- // They will be processed just in InputContext.
- return;
- } else if (event["isComposing"].as<bool>()) {
- // Handled by the input context
- return;
- } else if (event["ctrlKey"].as<bool>()
- || event["altKey"].as<bool>()
- || event["metaKey"].as<bool>()) {
- // Not all platforms use 'isComposing' for '~' + 'a', in this
- // case send the key with state ('ctrl', 'alt', or 'meta') to
- // processKeyForInputContext
-
- ; // fallthrough
- } else if (keyString.size() != 1) {
- // This is like; 'Shift','ArrowRight','AltGraph', ...
- // send all of these to processKeyForInputContext
-
- ; // fallthrough
- } else if (wasmInput->inputMethodAccepted()) {
- // processed in inputContext with skipping processKey
- return;
- }
- }
- qCDebug(qLcQpaWasmInputContext) << "processKey as KeyEvent";
- if (processKeyForInputContext(KeyEvent(eventType, event, m_deadKeySupport)))
- event.call<void>("preventDefault");
- event.call<void>("stopImmediatePropagation");
+ // Events with isComposing set are handled by the input context
+ bool composing = event["isComposing"].as<bool>();
+
+ // Android makes a bunch of KeyEvents as "Unidentified",
+ // make inputContext handle those.
+ bool androidUnidentified = (keyString == "Unidentified");
+
+ // Not all platforms use 'isComposing' for '~' + 'a', in this
+ // case send the key with state ('ctrl', 'alt', or 'meta') to
+ // processKeyForInputContext
+ bool hasModifiers = event["ctrlKey"].as<bool>()
+ || event["altKey"].as<bool>()
+ || event["metaKey"].as<bool>();
+
+ // This is like; 'Shift','ArrowRight','AltGraph', ...
+ // send all of these to processKeyForInputContext
+ bool hasNoncharacterKeyString = keyString.size() != 1;
+
+ bool overrideCompose = !hasModifiers && !hasNoncharacterKeyString && wasmInput->inputMethodAccepted();
+ return composing || androidUnidentified || overrideCompose;
+ }();
+
+ if (!useInputContext) {
+ qCDebug(qLcQpaWasmInputContext) << "processKey as KeyEvent";
+ if (processKeyForInputContext(keyEvent))
+ event.call<void>("preventDefault");
+ event.call<void>("stopImmediatePropagation");
+ }
}
bool QWasmWindow::processKeyForInputContext(const KeyEvent &event)
@@ -729,6 +756,30 @@ bool QWasmWindow::processKeyForInputContext(const KeyEvent &event)
return result;
}
+void QWasmWindow::handleInputEvent(emscripten::val event)
+{
+ if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
+ inputContext->inputCallback(event);
+}
+
+void QWasmWindow::handleCompositionStartEvent(emscripten::val event)
+{
+ if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
+ inputContext->compositionStartCallback(event);
+}
+
+void QWasmWindow::handleCompositionUpdateEvent(emscripten::val event)
+{
+ if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
+ inputContext->compositionUpdateCallback(event);
+}
+
+void QWasmWindow::handleCompositionEndEvent(emscripten::val event)
+{
+ if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
+ inputContext->compositionEndCallback(event);
+}
+
void QWasmWindow::handlePointerEnterLeaveEvent(const PointerEvent &event)
{
if (processPointerEnterLeave(event))
@@ -1040,7 +1091,7 @@ void QWasmWindow::requestActivateWindow()
void QWasmWindow::focus()
{
- m_canvas.call<void>("focus");
+ m_focusHelper.call<void>("focus");
}
bool QWasmWindow::setMouseGrabEnabled(bool grab)
diff --git a/src/plugins/platforms/wasm/qwasmwindow.h b/src/plugins/platforms/wasm/qwasmwindow.h
index 904e736a7e7..0c63ebdc16e 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.h
+++ b/src/plugins/platforms/wasm/qwasmwindow.h
@@ -100,6 +100,7 @@ public:
emscripten::val context2d() const { return m_context2d; }
emscripten::val a11yContainer() const { return m_a11yContainer; }
emscripten::val inputHandlerElement() const { return m_window; }
+ emscripten::val inputElement() const { return m_inputElement; }
// QNativeInterface::Private::QWasmWindow
emscripten::val document() const override { return m_document; }
@@ -137,8 +138,13 @@ private:
void handleKeyEvent(const KeyEvent &event);
bool processKey(const KeyEvent &event);
- void handleKeyForInputContextEvent(EventType eventType, const emscripten::val &event);
+ void handleKeyForInputContextEvent(const KeyEvent &event);
bool processKeyForInputContext(const KeyEvent &event);
+ void handleInputEvent(emscripten::val event);
+ void handleCompositionStartEvent(emscripten::val event);
+ void handleCompositionUpdateEvent(emscripten::val event);
+ void handleCompositionEndEvent(emscripten::val event);
+
void handlePointerEnterLeaveEvent(const PointerEvent &event);
bool processPointerEnterLeave(const PointerEvent &event);
void processPointer(const PointerEvent &event);
@@ -154,11 +160,14 @@ private:
QWasmDeadKeySupport *m_deadKeySupport;
QRect m_normalGeometry {0, 0, 0 ,0};
- emscripten::val m_document = emscripten::val::undefined();
- emscripten::val m_decoratedWindow = emscripten::val::undefined();
- emscripten::val m_window = emscripten::val::undefined();
- emscripten::val m_a11yContainer = emscripten::val::undefined();
- emscripten::val m_canvas = emscripten::val::undefined();
+ emscripten::val m_document;
+ emscripten::val m_decoratedWindow;
+ emscripten::val m_window;
+ emscripten::val m_a11yContainer;
+ emscripten::val m_canvas;
+ emscripten::val m_focusHelper;
+ emscripten::val m_inputElement;
+
emscripten::val m_context2d = emscripten::val::undefined();
std::unique_ptr<NonClientArea> m_nonClientArea;
@@ -169,6 +178,10 @@ private:
QWasmEventHandler m_keyUpCallback;
QWasmEventHandler m_keyDownCallbackForInputContext;
QWasmEventHandler m_keyUpCallbackForInputContext;
+ QWasmEventHandler m_inputCallback;
+ QWasmEventHandler m_compositionStartCallback;
+ QWasmEventHandler m_compositionUpdateCallback;
+ QWasmEventHandler m_compositionEndCallback;
QWasmEventHandler m_pointerDownCallback;
QWasmEventHandler m_pointerMoveCallback;
diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp
index 7ae48a302f4..84101b69e9f 100644
--- a/src/plugins/styles/modernwindows/qwindows11style.cpp
+++ b/src/plugins/styles/modernwindows/qwindows11style.cpp
@@ -183,30 +183,24 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt
QObject *styleObject = option->styleObject; // Can be widget or qquickitem
QRectF thumbRect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
- auto center = thumbRect.center();
const qreal outerRadius = qMin(8.0, (slider->orientation == Qt::Horizontal ? thumbRect.height() / 2.0 : thumbRect.width() / 2.0) - 1);
-
- thumbRect.setWidth(outerRadius);
- thumbRect.setHeight(outerRadius);
- thumbRect.moveCenter(center);
- QPointF cursorPos = widget ? widget->mapFromGlobal(QCursor::pos()) : QPointF();
- bool isInsideHandle = thumbRect.contains(cursorPos);
+ bool isInsideHandle = option->activeSubControls == SC_SliderHandle;
bool oldIsInsideHandle = styleObject->property("_q_insidehandle").toBool();
- int oldState = styleObject->property("_q_stylestate").toInt();
- int oldActiveControls = styleObject->property("_q_stylecontrols").toInt();
+ State oldState = State(styleObject->property("_q_stylestate").toInt());
+ SubControls oldActiveControls = SubControls(styleObject->property("_q_stylecontrols").toInt());
QRectF oldRect = styleObject->property("_q_stylerect").toRect();
styleObject->setProperty("_q_insidehandle", isInsideHandle);
- styleObject->setProperty("_q_stylestate", int(option->state));
+ styleObject->setProperty("_q_stylestate", int(state));
styleObject->setProperty("_q_stylecontrols", int(option->activeSubControls));
styleObject->setProperty("_q_stylerect", option->rect);
if (option->styleObject->property("_q_end_radius").isNull())
option->styleObject->setProperty("_q_end_radius", outerRadius * 0.43);
bool doTransition = (((state & State_Sunken) != (oldState & State_Sunken)
- || ((oldIsInsideHandle) != (isInsideHandle))
- || oldActiveControls != int(option->activeSubControls))
+ || (oldIsInsideHandle != isInsideHandle)
+ || (oldActiveControls != option->activeSubControls))
&& state & State_Enabled);
if (oldRect != option->rect) {
@@ -374,31 +368,29 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt
}
}
if (sub & SC_SliderHandle) {
- if (const auto *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- const QRectF rect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
- const QPointF center = rect.center();
+ const QRectF rect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
+ const QPointF center = rect.center();
- const QNumberStyleAnimation* animation = qobject_cast<QNumberStyleAnimation*>(d->animation(option->styleObject));
+ const QNumberStyleAnimation* animation = qobject_cast<QNumberStyleAnimation*>(d->animation(option->styleObject));
- if (animation != nullptr)
- option->styleObject->setProperty("_q_inner_radius", animation->currentValue());
- else
- option->styleObject->setProperty("_q_inner_radius", option->styleObject->property("_q_end_radius"));
-
- const qreal outerRadius = qMin(8.0,(slider->orientation == Qt::Horizontal ? rect.height() / 2.0 : rect.width() / 2.0) - 1);
- const float innerRadius = option->styleObject->property("_q_inner_radius").toFloat();
- painter->setRenderHint(QPainter::Antialiasing, true);
- painter->setPen(Qt::NoPen);
- painter->setBrush(WINUI3Colors[colorSchemeIndex][controlFillSolid]);
- painter->drawEllipse(center, outerRadius, outerRadius);
- painter->setBrush(option->palette.accent());
- painter->drawEllipse(center, innerRadius, innerRadius);
-
- painter->setPen(WINUI3Colors[colorSchemeIndex][controlStrokeSecondary]);
- painter->setBrush(Qt::NoBrush);
- painter->drawEllipse(center, outerRadius + 0.5, outerRadius + 0.5);
- painter->drawEllipse(center, innerRadius + 0.5, innerRadius + 0.5);
- }
+ float innerRadius = 0;
+ if (animation != nullptr)
+ innerRadius = animation->currentValue();
+ else
+ innerRadius = option->styleObject->property("_q_end_radius").toFloat();
+ option->styleObject->setProperty("_q_inner_radius", innerRadius);
+ const qreal outerRadius = qMin(8.0,(slider->orientation == Qt::Horizontal ? rect.height() / 2.0 : rect.width() / 2.0) - 1);
+
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(winUI3Color(controlFillSolid));
+ painter->drawEllipse(center, outerRadius, outerRadius);
+ painter->setBrush(option->palette.accent());
+ painter->drawEllipse(center, innerRadius, innerRadius);
+
+ painter->setPen(winUI3Color(controlStrokeSecondary));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawEllipse(center, outerRadius + 0.5, outerRadius + 0.5);
+ painter->drawEllipse(center, innerRadius + 0.5, innerRadius + 0.5);
}
if (slider->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
@@ -1684,18 +1676,13 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
}
const bool highlightCurrent = vopt->state.testAnyFlags(State_Selected | State_MouseOver);
if (highlightCurrent) {
- const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
- if (highContrastTheme)
+ if (highContrastTheme) {
painter->setBrush(vopt->palette.highlight());
- else
- painter->setBrush(view->alternatingRowColors() ? vopt->palette.highlight() : WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
- QWidget *editorWidget = view ? view->indexWidget(view->currentIndex()) : nullptr;
- if (editorWidget) {
- QPalette pal = editorWidget->palette();
- QColor editorBgColor = vopt->backgroundBrush == Qt::NoBrush ? vopt->palette.color(widget->backgroundRole()) : vopt->backgroundBrush.color();
- editorBgColor.setAlpha(255);
- pal.setColor(editorWidget->backgroundRole(), editorBgColor);
- editorWidget->setPalette(pal);
+ } else {
+ const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
+ painter->setBrush(view && view->alternatingRowColors()
+ ? vopt->palette.highlight()
+ : winUI3Color(subtleHighlightColor));
}
} else {
painter->setBrush(vopt->backgroundBrush);
@@ -2164,9 +2151,6 @@ void QWindows11Style::polish(QWidget* widget)
widget->setWindowFlag(Qt::NoDropShadowWindowHint);
widget->setAttribute(Qt::WA_RightToLeft, layoutDirection);
widget->setAttribute(Qt::WA_WState_Created, wasCreated);
- auto pal = widget->palette();
- pal.setColor(widget->backgroundRole(), Qt::transparent);
- widget->setPalette(pal);
if (!isScrollBar) {
bool inGraphicsView = widget->graphicsProxyWidget() != nullptr;
if (!inGraphicsView && comboBoxContainer && comboBoxContainer->parentWidget())
@@ -2237,10 +2221,11 @@ static void populateLightSystemBasePalette(QPalette &result)
static QString oldStyleSheet;
const bool styleSheetChanged = oldStyleSheet != qApp->styleSheet();
- const QColor textColor = QColor(0x00,0x00,0x00,0xE4);
- const QColor textDisabled = QColor(0x00,0x00,0x00,0x5C);
- const QColor btnFace = QColor(0xFF,0xFF,0xFF,0xB3);
- const QColor alternateBase = QColor(0x00,0x00,0x00,0x09);
+ constexpr QColor textColor = QColor(0x00,0x00,0x00,0xE4);
+ constexpr QColor textDisabled = QColor(0x00, 0x00, 0x00, 0x5C);
+ constexpr QColor btnFace = QColor(0xFF, 0xFF, 0xFF, 0xB3);
+ constexpr QColor base = QColor(0xFF, 0xFF, 0xFF, 0xFF);
+ constexpr QColor alternateBase = QColor(0x00, 0x00, 0x00, 0x09);
const QColor btnHighlight = result.accent().color();
const QColor btnColor = result.button().color();
@@ -2252,7 +2237,7 @@ static void populateLightSystemBasePalette(QPalette &result)
SET_IF_UNRESOLVED(QPalette::Active, QPalette::Mid, btnColor.darker(150));
SET_IF_UNRESOLVED(QPalette::Active, QPalette::Text, textColor);
SET_IF_UNRESOLVED(QPalette::Active, QPalette::BrightText, btnHighlight);
- SET_IF_UNRESOLVED(QPalette::Active, QPalette::Base, btnFace);
+ SET_IF_UNRESOLVED(QPalette::Active, QPalette::Base, base);
SET_IF_UNRESOLVED(QPalette::Active, QPalette::Window, QColor(0xF3,0xF3,0xF3,0xFF));
SET_IF_UNRESOLVED(QPalette::Active, QPalette::ButtonText, textColor);
SET_IF_UNRESOLVED(QPalette::Active, QPalette::Midlight, btnColor.lighter(125));
@@ -2269,7 +2254,7 @@ static void populateLightSystemBasePalette(QPalette &result)
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Mid, btnColor.darker(150));
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Text, textColor);
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::BrightText, btnHighlight);
- SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Base, btnFace);
+ SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Base, base);
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Window, QColor(0xF3,0xF3,0xF3,0xFF));
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::ButtonText, textColor);
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Midlight, btnColor.lighter(125));
@@ -2290,7 +2275,7 @@ static void populateDarkSystemBasePalette(QPalette &result)
static QString oldStyleSheet;
const bool styleSheetChanged = oldStyleSheet != qApp->styleSheet();
- const QColor alternateBase = QColor(0xFF,0xFF,0xFF,0x0F);
+ constexpr QColor alternateBase = QColor(0xFF, 0xFF, 0xFF, 0x0F);
SET_IF_UNRESOLVED(QPalette::Active, QPalette::AlternateBase, alternateBase);