summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2019-01-26 08:35:40 +0100
committerLiang Qi <liang.qi@qt.io>2019-01-26 08:35:40 +0100
commit980567b3a32b2e2f00c86f2d627cd82b5230dd0f (patch)
treebc8cc4005b2e07cbc5cad8ba30f8c9fa4f236c3d /src/plugins
parente81acde7d0cf5fb44a3fb2cf0bf7aaa2c65f807e (diff)
parent730cbad8824bcfcb7ab60371a6563cfb6dd5658d (diff)
Merge remote-tracking branch 'origin/5.12' into dev
Conflicts: src/android/templates/AndroidManifest.xml tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp Change-Id: I4c9679e3a8ebba118fbf4772301ff8fde60455b9
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerservice.h2
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp38
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsintegration.cpp13
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsintegration_p.h1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp4
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp4
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp4
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp49
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbintegration.h8
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp221
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.h5
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.cpp39
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.h2
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp54
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_basic.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbeventqueue.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbeventqueue.h7
-rw-r--r--src/plugins/platforms/xcb/xcb_qpa_lib.pro4
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm62
24 files changed, 403 insertions, 149 deletions
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
index 65e618d15f..c879083faf 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
@@ -243,7 +243,7 @@ public:
// bool setConnections();
Q_SIGNALS:
- void propertiesChanged(QMap <QString,QVariant>);
+ void propertiesChanged(QMap<QString,QVariant>);
void propertiesReady();
private Q_SLOTS:
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index 7b3546f9bb..cdc52e1cb4 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -99,13 +99,12 @@ static jfieldID m_selectionStartFieldID = 0;
static jfieldID m_startOffsetFieldID = 0;
static jfieldID m_textFieldID = 0;
-Q_DECLARE_METATYPE(std::function<void()>)
-
static void runOnQtThread(const std::function<void()> &func)
{
- const bool block = QGuiApplication::applicationState() >= Qt::ApplicationInactive;
- QMetaObject::invokeMethod(m_androidInputContext, "safeCall",
- block ? Qt::BlockingQueuedConnection : Qt::QueuedConnection, Q_ARG(std::function<void()>, func));
+ AndroidDeadlockProtector protector;
+ if (!protector.acquire())
+ return;
+ QMetaObject::invokeMethod(m_androidInputContext, "safeCall", Qt::BlockingQueuedConnection, Q_ARG(std::function<void()>, func));
}
static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
@@ -116,7 +115,7 @@ static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ BEGINBATCH");
#endif
- jboolean res;
+ jboolean res = JNI_FALSE;
runOnQtThread([&res]{res = m_androidInputContext->beginBatchEdit();});
return res;
}
@@ -130,7 +129,7 @@ static jboolean endBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
qDebug("@@@ ENDBATCH");
#endif
- jboolean res;
+ jboolean res = JNI_FALSE;
runOnQtThread([&res]{res = m_androidInputContext->endBatchEdit();});
return res;
}
@@ -149,7 +148,7 @@ static jboolean commitText(JNIEnv *env, jobject /*thiz*/, jstring text, jint new
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ COMMIT" << str << newCursorPosition;
#endif
- jboolean res;
+ jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->commitText(str, newCursorPosition);});
return res;
}
@@ -162,7 +161,7 @@ static jboolean deleteSurroundingText(JNIEnv */*env*/, jobject /*thiz*/, jint le
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ DELETE" << leftLength << rightLength;
#endif
- jboolean res;
+ jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->deleteSurroundingText(leftLength, rightLength);});
return res;
}
@@ -175,7 +174,7 @@ static jboolean finishComposingText(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ FINISH");
#endif
- jboolean res;
+ jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->finishComposingText();});
return res;
}
@@ -185,7 +184,7 @@ static jint getCursorCapsMode(JNIEnv */*env*/, jobject /*thiz*/, jint reqModes)
if (!m_androidInputContext)
return 0;
- jboolean res;
+ jint res = 0;
runOnQtThread([&]{res = m_androidInputContext->getCursorCapsMode(reqModes);});
return res;
}
@@ -270,7 +269,7 @@ static jboolean setComposingText(JNIEnv *env, jobject /*thiz*/, jstring text, ji
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SET" << str << newCursorPosition;
#endif
- jboolean res;
+ jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->setComposingText(str, newCursorPosition);});
return res;
}
@@ -283,7 +282,7 @@ static jboolean setComposingRegion(JNIEnv */*env*/, jobject /*thiz*/, jint start
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SETR" << start << end;
#endif
- jboolean res;
+ jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->setComposingRegion(start, end);});
return res;
}
@@ -297,7 +296,7 @@ static jboolean setSelection(JNIEnv */*env*/, jobject /*thiz*/, jint start, jint
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SETSEL" << start << end;
#endif
- jboolean res;
+ jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->setSelection(start, end);});
return res;
@@ -311,7 +310,7 @@ static jboolean selectAll(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ SELALL");
#endif
- jboolean res;
+ jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->selectAll();});
return res;
}
@@ -324,7 +323,7 @@ static jboolean cut(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@");
#endif
- jboolean res;
+ jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->cut();});
return res;
}
@@ -337,7 +336,7 @@ static jboolean copy(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@");
#endif
- jboolean res;
+ jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->copy();});
return res;
}
@@ -350,7 +349,7 @@ static jboolean copyURL(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@");
#endif
- jboolean res;
+ jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->copyURL();});
return res;
}
@@ -363,7 +362,7 @@ static jboolean paste(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ PASTE");
#endif
- jboolean res;
+ jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->paste();});
return res;
}
@@ -516,7 +515,6 @@ QAndroidInputContext::QAndroidInputContext()
m_handleMode = Hidden;
updateSelectionHandles();
});
- qRegisterMetaType<std::function<void()>>();
}
QAndroidInputContext::~QAndroidInputContext()
diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
index 72420199e3..8ccb0ef2cd 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
@@ -429,6 +429,8 @@ QFunctionPointer QEglFSIntegration::platformFunction(const QByteArray &function)
#if QT_CONFIG(evdev)
if (function == QEglFSFunctions::loadKeymapTypeIdentifier())
return QFunctionPointer(loadKeymapStatic);
+ else if (function == QEglFSFunctions::switchLangTypeIdentifier())
+ return QFunctionPointer(switchLangStatic);
#endif
return qt_egl_device_integration()->platformFunction(function);
@@ -447,6 +449,17 @@ void QEglFSIntegration::loadKeymapStatic(const QString &filename)
#endif
}
+void QEglFSIntegration::switchLangStatic()
+{
+#if QT_CONFIG(evdev)
+ QEglFSIntegration *self = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ if (self->m_kbdMgr)
+ self->m_kbdMgr->switchLang();
+ else
+ qWarning("QEglFSIntegration: Cannot switch language, no keyboard handler found");
+#endif
+}
+
void QEglFSIntegration::createInputHandlers()
{
#if QT_CONFIG(libinput)
diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h
index c288876678..4b4585d33c 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h
+++ b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h
@@ -110,6 +110,7 @@ private:
EGLNativeDisplayType nativeDisplay() const;
void createInputHandlers();
static void loadKeymapStatic(const QString &filename);
+ static void switchLangStatic();
EGLDisplay m_display;
QPlatformInputContext *m_inputContext;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
index 402338197d..1e4f4e72c8 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
@@ -118,6 +118,8 @@ QPlatformCursor *QEglFSKmsGbmIntegration::createCursor(QPlatformScreen *screen)
qCDebug(qLcEglfsKmsDebug, "Using plain OpenGL mouse cursor");
return new QEglFSCursor(screen);
}
+#else
+ Q_UNUSED(screen);
#endif
return nullptr;
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
index a67457a6a5..ab39af6b80 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
@@ -289,7 +289,9 @@ QPlatformCursor *QEglFSKmsEglDeviceIntegration::createCursor(QPlatformScreen *sc
{
#if QT_CONFIG(opengl)
if (screenConfig()->separateScreens())
- return new QEglFSCursor(screen);
+ return new QEglFSCursor(screen);
+#else
+ Q_UNUSED(screen);
#endif
return nullptr;
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp
index 763a4a462b..2fc076ad0c 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp
@@ -65,7 +65,7 @@ void QEglFSVivIntegration::platformInit()
VivanteInit();
mNativeDisplay = fbGetDisplay();
#else
- mNativeDisplay = fbGetDisplayByIndex(framebufferIndex());
+ mNativeDisplay = static_cast<EGLNativeDisplayType>(fbGetDisplayByIndex(framebufferIndex()));
#endif
fbGetDisplayGeometry(mNativeDisplay, &width, &height);
@@ -88,7 +88,7 @@ EGLNativeWindowType QEglFSVivIntegration::createNativeWindow(QPlatformWindow *wi
Q_UNUSED(window)
Q_UNUSED(format)
- EGLNativeWindowType eglWindow = fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height());
+ EGLNativeWindowType eglWindow = static_cast<EGLNativeWindowType>(fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()));
return eglWindow;
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp
index 61e2f17766..3bdae239cd 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp
@@ -60,7 +60,7 @@ void QEglFSVivWaylandIntegration::platformInit()
}
mWaylandDisplay = wl_display_create();
- mNativeDisplay = fbGetDisplay(mWaylandDisplay);
+ mNativeDisplay = static_cast<EGLNativeDisplayType>(fbGetDisplay(mWaylandDisplay));
fbGetDisplayGeometry(mNativeDisplay, &width, &height);
mScreenSize.setHeight(height);
mScreenSize.setWidth(width);
@@ -81,7 +81,7 @@ EGLNativeWindowType QEglFSVivWaylandIntegration::createNativeWindow(QPlatformWin
Q_UNUSED(window)
Q_UNUSED(format)
- EGLNativeWindowType eglWindow = fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height());
+ EGLNativeWindowType eglWindow = static_cast<EGLNativeWindowType>(fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()));
return eglWindow;
}
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
index f835dbf6d4..9e38900bcd 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
@@ -69,12 +69,15 @@
#include <QtInputSupport/private/qtslib_p.h>
#endif
+#include <QtPlatformHeaders/qlinuxfbfunctions.h>
+
QT_BEGIN_NAMESPACE
QLinuxFbIntegration::QLinuxFbIntegration(const QStringList &paramList)
: m_primaryScreen(nullptr),
m_fontDb(new QGenericUnixFontDatabase),
- m_services(new QGenericUnixServices)
+ m_services(new QGenericUnixServices),
+ m_kbdMgr(0)
{
#if QT_CONFIG(kms)
if (qEnvironmentVariableIntValue("QT_QPA_FB_DRM") != 0)
@@ -98,8 +101,6 @@ void QLinuxFbIntegration::initialize()
m_inputContext = QPlatformInputContextFactory::create();
- m_nativeInterface.reset(new QPlatformNativeInterface);
-
m_vtHandler.reset(new QFbVtHandler);
if (!qEnvironmentVariableIntValue("QT_QPA_FB_DISABLE_INPUT"))
@@ -163,7 +164,7 @@ void QLinuxFbIntegration::createInputHandlers()
#endif
#if QT_CONFIG(evdev)
- new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this);
+ m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this);
new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this);
#if QT_CONFIG(tslib)
if (!useTslib)
@@ -174,7 +175,45 @@ void QLinuxFbIntegration::createInputHandlers()
QPlatformNativeInterface *QLinuxFbIntegration::nativeInterface() const
{
- return m_nativeInterface.data();
+ return const_cast<QLinuxFbIntegration *>(this);
+}
+
+QFunctionPointer QLinuxFbIntegration::platformFunction(const QByteArray &function) const
+{
+#if QT_CONFIG(evdev)
+ if (function == QLinuxFbFunctions::loadKeymapTypeIdentifier())
+ return QFunctionPointer(loadKeymapStatic);
+ else if (function == QLinuxFbFunctions::switchLangTypeIdentifier())
+ return QFunctionPointer(switchLangStatic);
+#else
+ Q_UNUSED(function)
+#endif
+
+ return 0;
+}
+
+void QLinuxFbIntegration::loadKeymapStatic(const QString &filename)
+{
+#if QT_CONFIG(evdev)
+ QLinuxFbIntegration *self = static_cast<QLinuxFbIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ if (self->m_kbdMgr)
+ self->m_kbdMgr->loadKeymap(filename);
+ else
+ qWarning("QLinuxFbIntegration: Cannot load keymap, no keyboard handler found");
+#else
+ Q_UNUSED(filename);
+#endif
+}
+
+void QLinuxFbIntegration::switchLangStatic()
+{
+#if QT_CONFIG(evdev)
+ QLinuxFbIntegration *self = static_cast<QLinuxFbIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ if (self->m_kbdMgr)
+ self->m_kbdMgr->switchLang();
+ else
+ qWarning("QLinuxFbIntegration: Cannot switch language, no keyboard handler found");
+#endif
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h
index 22578bf980..7a871b3812 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h
+++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h
@@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE
class QAbstractEventDispatcher;
class QFbScreen;
class QFbVtHandler;
+class QEvdevKeyboardManager;
class QLinuxFbIntegration : public QPlatformIntegration, public QPlatformNativeInterface
{
@@ -71,15 +72,20 @@ public:
QList<QPlatformScreen *> screens() const;
+ QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE;
+
private:
void createInputHandlers();
+ static void loadKeymapStatic(const QString &filename);
+ static void switchLangStatic();
QFbScreen *m_primaryScreen;
QPlatformInputContext *m_inputContext;
QScopedPointer<QPlatformFontDatabase> m_fontDb;
QScopedPointer<QPlatformServices> m_services;
QScopedPointer<QFbVtHandler> m_vtHandler;
- QScopedPointer<QPlatformNativeInterface> m_nativeInterface;
+
+ QEvdevKeyboardManager *m_kbdMgr;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 1f80ac5872..fee093f675 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -1115,8 +1115,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::DisplayChangedEvent:
if (QWindowsTheme *t = QWindowsTheme::instance())
t->displayChanged();
+ QWindowsWindow::displayChanged();
return d->m_screenManager.handleDisplayChange(wParam, lParam);
case QtWindows::SettingChangedEvent:
+ QWindowsWindow::settingsChanged();
return d->m_screenManager.handleScreenChanges();
default:
break;
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index 851a6c961e..21cb794196 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -1350,10 +1350,10 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
// Set the swap interval
if (m_staticContext->wglSwapInternalExt) {
const int interval = surface->format().swapInterval();
- if (interval >= 0 && m_swapInterval != interval) {
+ if (m_swapInterval != interval)
m_swapInterval = interval;
+ if (interval >= 0)
m_staticContext->wglSwapInternalExt(interval);
- }
}
return success;
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index 7935d0c36f..e428a8cf63 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -54,7 +54,6 @@
# include "qwindowsdrag.h"
#endif
-#include <qpa/qwindowsysteminterface.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qscreen.h>
#include <QtGui/qtouchdevice.h>
@@ -201,6 +200,8 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
return false;
}
+ m_lastPointerType = pointerType;
+
// Handle non-client pen/touch as generic mouse events for compatibility with QDockWindow.
if ((pointerType == QT_PT_TOUCH || pointerType == QT_PT_PEN) && (et & QtWindows::NonClientEventFlag)) {
POINTER_INFO pointerInfo;
@@ -427,6 +428,15 @@ static bool isValidWheelReceiver(QWindow *candidate)
return false;
}
+static bool isMenuWindow(QWindow *window)
+{
+ if (window)
+ if (QObject *fo = window->focusObject())
+ if (fo->inherits("QMenu"))
+ return true;
+ return false;
+}
+
static QTouchDevice *createTouchDevice()
{
const int digitizers = GetSystemMetrics(SM_DIGITIZER);
@@ -455,6 +465,103 @@ QTouchDevice *QWindowsPointerHandler::ensureTouchDevice()
return m_touchDevice;
}
+void QWindowsPointerHandler::handleCaptureRelease(QWindow *window,
+ QWindow *currentWindowUnderPointer,
+ HWND hwnd,
+ QEvent::Type eventType,
+ Qt::MouseButtons mouseButtons)
+{
+ QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
+
+ // Qt expects the platform plugin to capture the mouse on any button press until release.
+ if (!platformWindow->hasMouseCapture() && eventType == QEvent::MouseButtonPress) {
+
+ platformWindow->setMouseGrabEnabled(true);
+ platformWindow->setFlag(QWindowsWindow::AutoMouseCapture);
+ qCDebug(lcQpaEvents) << "Automatic mouse capture " << window;
+
+ // Implement "Click to focus" for native child windows (unless it is a native widget window).
+ if (!window->isTopLevel() && !window->inherits("QWidgetWindow") && QGuiApplication::focusWindow() != window)
+ window->requestActivate();
+
+ } else if (platformWindow->hasMouseCapture()
+ && platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)
+ && eventType == QEvent::MouseButtonRelease
+ && !mouseButtons) {
+
+ platformWindow->setMouseGrabEnabled(false);
+ qCDebug(lcQpaEvents) << "Releasing automatic mouse capture " << window;
+ }
+
+ // Enter new window: track to generate leave event.
+ // If there is an active capture, only track if the current window is capturing,
+ // so we don't get extra leave when cursor leaves the application.
+ if (window != m_currentWindow &&
+ (!platformWindow->hasMouseCapture() || currentWindowUnderPointer == window)) {
+ trackLeave(hwnd);
+ m_currentWindow = window;
+ }
+}
+
+void QWindowsPointerHandler::handleEnterLeave(QWindow *window,
+ QWindow *currentWindowUnderPointer,
+ QPoint globalPos)
+{
+ QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
+ const bool hasCapture = platformWindow->hasMouseCapture();
+
+ // No enter or leave events are sent as long as there is an autocapturing window.
+ if (!hasCapture || !platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)) {
+
+ // Leave is needed if:
+ // 1) There is no capture and we move from a window to another window.
+ // Note: Leaving the application entirely is handled in translateMouseEvent(WM_MOUSELEAVE).
+ // 2) There is capture and we move out of the capturing window.
+ // 3) There is a new capture and we were over another window.
+ if ((m_windowUnderPointer && m_windowUnderPointer != currentWindowUnderPointer
+ && (!hasCapture || window == m_windowUnderPointer))
+ || (hasCapture && m_previousCaptureWindow != window && m_windowUnderPointer
+ && m_windowUnderPointer != window)) {
+
+ qCDebug(lcQpaEvents) << "Leaving window " << m_windowUnderPointer;
+ QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer);
+
+ if (hasCapture && currentWindowUnderPointer != window) {
+ // Clear tracking if capturing and current window is not the capturing window
+ // to avoid leave when mouse actually leaves the application.
+ m_currentWindow = nullptr;
+ // We are not officially in any window, but we need to set some cursor to clear
+ // whatever cursor the left window had, so apply the cursor of the capture window.
+ platformWindow->applyCursor();
+ }
+ }
+
+ // Enter is needed if:
+ // 1) There is no capture and we move to a new window.
+ // 2) There is capture and we move into the capturing window.
+ // 3) The capture just ended and we are over non-capturing window.
+ if ((currentWindowUnderPointer && m_windowUnderPointer != currentWindowUnderPointer
+ && (!hasCapture || currentWindowUnderPointer == window))
+ || (m_previousCaptureWindow && !hasCapture && currentWindowUnderPointer
+ && currentWindowUnderPointer != m_previousCaptureWindow)) {
+
+ QPoint wumLocalPos;
+ if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer)) {
+ wumLocalPos = wumPlatformWindow->mapFromGlobal(globalPos);
+ wumPlatformWindow->applyCursor();
+ }
+ qCDebug(lcQpaEvents) << "Entering window " << currentWindowUnderPointer;
+ QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, wumLocalPos, globalPos);
+ }
+
+ // We need to track m_windowUnderPointer separately from m_currentWindow, as Windows
+ // mouse tracking will not trigger WM_MOUSELEAVE for leaving window when mouse capture is set.
+ m_windowUnderPointer = currentWindowUnderPointer;
+ }
+
+ m_previousCaptureWindow = hasCapture ? window : nullptr;
+}
+
bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND hwnd,
QtWindows::WindowsEventType et,
MSG msg, PVOID vPointerInfo)
@@ -464,9 +571,7 @@ bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND h
const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
const Qt::MouseButtons mouseButtons = mouseButtonsFromPointerFlags(pointerInfo->pointerFlags);
-
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
- QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
switch (msg.message) {
case WM_NCPOINTERDOWN:
@@ -485,38 +590,17 @@ bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND h
keyModifiers, Qt::MouseEventNotSynthesized);
return false; // To allow window dragging, etc.
} else {
- if (eventType == QEvent::MouseButtonPress) {
- // Implement "Click to focus" for native child windows (unless it is a native widget window).
- if (!window->isTopLevel() && !window->inherits("QWidgetWindow") && QGuiApplication::focusWindow() != window)
- window->requestActivate();
- }
- if (currentWindowUnderPointer != m_windowUnderPointer) {
- if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) {
- QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer);
- m_currentWindow = nullptr;
- }
-
- if (currentWindowUnderPointer) {
- if (currentWindowUnderPointer != m_currentWindow) {
- QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, localPos, globalPos);
- m_currentWindow = currentWindowUnderPointer;
- if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer))
- wumPlatformWindow->applyCursor();
- trackLeave(hwnd);
- }
- } else {
- platformWindow->applyCursor();
- }
- m_windowUnderPointer = currentWindowUnderPointer;
- }
+
+ handleCaptureRelease(window, currentWindowUnderPointer, hwnd, eventType, mouseButtons);
+ handleEnterLeave(window, currentWindowUnderPointer, globalPos);
QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType,
keyModifiers, Qt::MouseEventNotSynthesized);
// The initial down click over the QSizeGrip area, which posts a resize WM_SYSCOMMAND
// has go to through DefWindowProc() for resizing to work, so we return false here,
- // unless the mouse is captured, as it would mess with menu processing.
- return msg.message != WM_POINTERDOWN || GetCapture();
+ // unless the click was on a menu, as it would mess with menu processing.
+ return msg.message != WM_POINTERDOWN || isMenuWindow(window);
}
}
case WM_POINTERHWHEEL:
@@ -641,6 +725,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
// Only the primary pointer will generate mouse messages.
enqueueTouchEvent(window, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers());
} else {
+ flushTouchEvents(m_touchDevice);
QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints,
QWindowsKeyMapper::queryKeyboardModifiers());
}
@@ -755,6 +840,16 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
#endif
}
+static inline bool isMouseEventSynthesizedFromPenOrTouch()
+{
+ // For details, see
+ // https://docs.microsoft.com/en-us/windows/desktop/tablet/system-events-and-mouse-messages
+ const LONG_PTR SIGNATURE_MASK = 0xFFFFFF00;
+ const LONG_PTR MI_WP_SIGNATURE = 0xFF515700;
+
+ return ((::GetMessageExtraInfo() & SIGNATURE_MASK) == MI_WP_SIGNATURE);
+}
+
// Process old-style mouse messages here.
bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
{
@@ -763,8 +858,6 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
flushTabletEvents();
*result = 0;
- if (et != QtWindows::MouseWheelEvent && msg.message != WM_MOUSELEAVE && msg.message != WM_MOUSEMOVE)
- return false;
const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
QPoint localPos;
@@ -778,7 +871,26 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
}
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
- QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
+ const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
+
+ // Handle "press and hold for right-clicking".
+ // We have to synthesize it here as it only comes from Windows as a fake RMB.
+ // MS docs say we could use bit 7 from extraInfo to distinguish pen from touch,
+ // but on the Surface it is set for both. So we use the last pointer type.
+ if (isMouseEventSynthesizedFromPenOrTouch()) {
+ if ((msg.message == WM_RBUTTONDOWN || msg.message == WM_RBUTTONUP)
+ && (((m_lastPointerType == QT_PT_PEN)
+ && QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents))
+ || ((m_lastPointerType == QT_PT_TOUCH)
+ && QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)))) {
+ QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::RightButton,
+ (msg.message == WM_RBUTTONDOWN) ? QEvent::MouseButtonPress
+ : QEvent::MouseButtonRelease,
+ keyModifiers, Qt::MouseEventSynthesizedBySystem);
+ }
+ // Messages synthesized from touch/pen are only used for flushing queues and press&hold.
+ return false;
+ }
if (et == QtWindows::MouseWheelEvent) {
@@ -799,50 +911,21 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
}
if (msg.message == WM_MOUSELEAVE) {
+
if (window == m_currentWindow) {
- QWindowSystemInterface::handleLeaveEvent(window);
+ QWindow *leaveTarget = m_windowUnderPointer ? m_windowUnderPointer : m_currentWindow;
+ qCDebug(lcQpaEvents) << "Leaving window " << leaveTarget;
+ QWindowSystemInterface::handleLeaveEvent(leaveTarget);
m_windowUnderPointer = nullptr;
m_currentWindow = nullptr;
- platformWindow->applyCursor();
}
- return false;
- }
-
- // Windows sends a mouse move with no buttons pressed to signal "Enter"
- // when a window is shown over the cursor. Discard the event and only use
- // it for generating QEvent::Enter to be consistent with other platforms -
- // X11 and macOS.
- static QPoint lastMouseMovePos;
- const bool discardEvent = msg.wParam == 0 && (m_windowUnderPointer.isNull() || globalPos == lastMouseMovePos);
- lastMouseMovePos = globalPos;
-
- QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
- if (currentWindowUnderPointer != m_windowUnderPointer) {
- if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) {
- QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer);
- m_currentWindow = nullptr;
- }
+ } else if (msg.message == WM_MOUSEMOVE) {
- if (currentWindowUnderPointer) {
- if (currentWindowUnderPointer != m_currentWindow) {
- QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, localPos, globalPos);
- m_currentWindow = currentWindowUnderPointer;
- if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer))
- wumPlatformWindow->applyCursor();
- trackLeave(hwnd);
- }
- } else {
- platformWindow->applyCursor();
- }
- m_windowUnderPointer = currentWindowUnderPointer;
+ QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
+ handleCaptureRelease(window, currentWindowUnderPointer, hwnd, QEvent::MouseMove, mouseButtons);
+ handleEnterLeave(window, currentWindowUnderPointer, globalPos);
}
-
- const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
-
- if (!discardEvent)
- QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::NoButton, QEvent::MouseMove,
- keyModifiers, Qt::MouseEventNotSynthesized);
return false;
}
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h
index 3861ebf919..ec3179e821 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.h
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.h
@@ -46,6 +46,7 @@
#include <QtCore/qpointer.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qhash.h>
+#include <qpa/qwindowsysteminterface.h>
QT_BEGIN_NAMESPACE
@@ -68,12 +69,16 @@ private:
bool translateMouseTouchPadEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPointerInfo);
bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count);
bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo);
+ void handleCaptureRelease(QWindow *window, QWindow *currentWindowUnderPointer, HWND hwnd, QEvent::Type eventType, Qt::MouseButtons mouseButtons);
+ void handleEnterLeave(QWindow *window, QWindow *currentWindowUnderPointer, QPoint globalPos);
QTouchDevice *m_touchDevice = nullptr;
QHash<int, QPointF> m_lastTouchPositions;
QPointer<QWindow> m_windowUnderPointer;
QPointer<QWindow> m_currentWindow;
+ QWindow *m_previousCaptureWindow = nullptr;
bool m_needsEnterOnPointerUpdate = false;
+ DWORD m_lastPointerType = 0;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
index 3c27f2914d..b738007f0e 100644
--- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
+++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
@@ -103,6 +103,13 @@ static void setIconContents(NOTIFYICONDATA &tnd, const QString &tip, HICON hIcon
qStringToLimitedWCharArray(tip, tnd.szTip, sizeof(tnd.szTip) / sizeof(wchar_t));
}
+static void setIconVisibility(NOTIFYICONDATA &tnd, bool v)
+{
+ tnd.uFlags |= NIF_STATE;
+ tnd.dwStateMask = NIS_HIDDEN;
+ tnd.dwState = v ? 0 : NIS_HIDDEN;
+}
+
// Match the HWND of the dummy window to the instances
struct QWindowsHwndSystemTrayIconEntry
{
@@ -176,12 +183,6 @@ static inline HWND createTrayIconMessageWindow()
QWindowsSystemTrayIcon::QWindowsSystemTrayIcon()
{
- // For restoring the tray icon after explorer crashes
- if (!MYWM_TASKBARCREATED)
- MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");
- // Allow the WM_TASKBARCREATED message through the UIPI filter
- ChangeWindowMessageFilterEx(m_hwnd, MYWM_TASKBARCREATED, MSGFLT_ALLOW, 0);
- qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "MYWM_TASKBARCREATED=" << MYWM_TASKBARCREATED;
}
QWindowsSystemTrayIcon::~QWindowsSystemTrayIcon()
@@ -193,12 +194,15 @@ QWindowsSystemTrayIcon::~QWindowsSystemTrayIcon()
void QWindowsSystemTrayIcon::init()
{
qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this;
- ensureInstalled();
+ m_visible = true;
+ if (!setIconVisible(m_visible))
+ ensureInstalled();
}
void QWindowsSystemTrayIcon::cleanup()
{
qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this;
+ m_visible = false;
ensureCleanup();
}
@@ -310,6 +314,13 @@ bool QWindowsSystemTrayIcon::ensureInstalled()
m_hwnd = createTrayIconMessageWindow();
if (Q_UNLIKELY(m_hwnd == nullptr))
return false;
+ // For restoring the tray icon after explorer crashes
+ if (!MYWM_TASKBARCREATED)
+ MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");
+ // Allow the WM_TASKBARCREATED message through the UIPI filter
+ ChangeWindowMessageFilterEx(m_hwnd, MYWM_TASKBARCREATED, MSGFLT_ALLOW, nullptr);
+ qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "MYWM_TASKBARCREATED=" << MYWM_TASKBARCREATED;
+
QWindowsHwndSystemTrayIconEntry entry{m_hwnd, this};
hwndTrayIconEntries()->append(entry);
sendTrayMessage(NIM_ADD);
@@ -333,6 +344,18 @@ void QWindowsSystemTrayIcon::ensureCleanup()
m_toolTip.clear();
}
+bool QWindowsSystemTrayIcon::setIconVisible(bool visible)
+{
+ if (!isInstalled())
+ return false;
+ NOTIFYICONDATA tnd;
+ initNotifyIconData(tnd);
+ tnd.uID = q_uNOTIFYICONID;
+ tnd.hWnd = m_hwnd;
+ setIconVisibility(tnd, visible);
+ return Shell_NotifyIcon(NIM_MODIFY, &tnd) == TRUE;
+}
+
bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg)
{
NOTIFYICONDATA tnd;
@@ -340,6 +363,8 @@ bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg)
tnd.uID = q_uNOTIFYICONID;
tnd.hWnd = m_hwnd;
tnd.uFlags = NIF_SHOWTIP;
+ if (msg != NIM_DELETE && !m_visible)
+ setIconVisibility(tnd, m_visible);
if (msg == NIM_ADD || msg == NIM_MODIFY)
setIconContents(tnd, m_toolTip, m_hIcon);
if (!Shell_NotifyIcon(msg, &tnd))
diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.h b/src/plugins/platforms/windows/qwindowssystemtrayicon.h
index a8adb9641f..44e1bcc761 100644
--- a/src/plugins/platforms/windows/qwindowssystemtrayicon.h
+++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.h
@@ -84,6 +84,7 @@ private:
bool ensureInstalled();
void ensureCleanup();
bool sendTrayMessage(DWORD msg);
+ bool setIconVisible(bool visible);
HICON createIcon(const QIcon &icon);
QIcon m_icon;
@@ -92,6 +93,7 @@ private:
HICON m_hIcon = nullptr;
mutable QPointer<QWindowsPopupMenu> m_menu;
bool m_ignoreNextMouseRelease = false;
+ bool m_visible = false;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 6201da7b72..8a6466c9cf 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -482,26 +482,22 @@ struct WindowCreationData
typedef QWindowsWindowData WindowData;
enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 };
- WindowCreationData() : parentHandle(0), type(Qt::Widget), style(0), exStyle(0),
- topLevel(false), popup(false), dialog(false),
- tool(false), embedded(false), hasAlpha(false) {}
-
void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0);
inline WindowData create(const QWindow *w, const WindowData &data, QString title) const;
inline void applyWindowFlags(HWND hwnd) const;
void initialize(const QWindow *w, HWND h, bool frameChange, qreal opacityLevel) const;
Qt::WindowFlags flags;
- HWND parentHandle;
- Qt::WindowType type;
- unsigned style;
- unsigned exStyle;
- bool topLevel;
- bool popup;
- bool dialog;
- bool tool;
- bool embedded;
- bool hasAlpha;
+ HWND parentHandle = nullptr;
+ Qt::WindowType type = Qt::Widget;
+ unsigned style = 0;
+ unsigned exStyle = 0;
+ bool topLevel = false;
+ bool popup = false;
+ bool dialog = false;
+ bool tool = false;
+ bool embedded = false;
+ bool hasAlpha = false;
};
QDebug operator<<(QDebug debug, const WindowCreationData &d)
@@ -555,12 +551,6 @@ static QScreen *screenForName(const QWindow *w, const QString &name)
return winScreen;
}
-static QScreen *forcedScreenForGLWindow(const QWindow *w)
-{
- const QString forceToScreen = GpuDescription::detect().gpuSuitableScreen;
- return forceToScreen.isEmpty() ? nullptr : screenForName(w, forceToScreen);
-}
-
static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &context, const QMargins &invMargins)
{
const QPoint orgPos(context->frameX - invMargins.left(), context->frameY - invMargins.top());
@@ -569,7 +559,7 @@ static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &co
return orgPos;
// Workaround for QTBUG-50371
- const QScreen *screenForGL = forcedScreenForGLWindow(w);
+ const QScreen *screenForGL = QWindowsWindow::forcedScreenForGLWindow(w);
if (!screenForGL)
return orgPos;
@@ -1364,6 +1354,28 @@ void QWindowsWindow::setDropSiteEnabled(bool dropEnabled)
#endif // QT_CONFIG(clipboard) && QT_CONFIG(draganddrop)
}
+bool QWindowsWindow::m_screenForGLInitialized = false;
+
+void QWindowsWindow::displayChanged()
+{
+ m_screenForGLInitialized = false;
+}
+
+void QWindowsWindow::settingsChanged()
+{
+ m_screenForGLInitialized = false;
+}
+
+QScreen *QWindowsWindow::forcedScreenForGLWindow(const QWindow *w)
+{
+ static QString forceToScreen;
+ if (!m_screenForGLInitialized) {
+ forceToScreen = GpuDescription::detect().gpuSuitableScreen;
+ m_screenForGLInitialized = true;
+ }
+ return forceToScreen.isEmpty() ? nullptr : screenForName(w, forceToScreen);
+}
+
// Returns topmost QWindowsWindow ancestor even if there are embedded windows in the chain.
// Returns this window if it is the topmost ancestor.
QWindow *QWindowsWindow::topLevelOf(QWindow *w)
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 4d136151fe..b07bd15d2a 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -297,6 +297,9 @@ public:
void handleHidden();
void handleCompositionSettingsChanged();
+ static void displayChanged();
+ static void settingsChanged();
+ static QScreen *forcedScreenForGLWindow(const QWindow *w);
static QWindowsWindow *windowsWindowOf(const QWindow *w);
static QWindow *topLevelOf(QWindow *w);
static inline void *userDataOf(HWND hwnd);
@@ -378,6 +381,8 @@ private:
HICON m_iconBig = 0;
void *m_surface = nullptr;
+ static bool m_screenForGLInitialized;
+
#if QT_CONFIG(vulkan)
// note: intentionally not using void * in order to avoid breaking x86
VkSurfaceKHR m_vkSurface = 0;
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index bc92f82d5f..ac8b029916 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -810,8 +810,9 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, i
connection()->flush();
- // sleep 50 ms, so we don't use up CPU cycles all the time.
- QThread::msleep(50);
+ const auto elapsed = timer.elapsed();
+ if (elapsed < clipboard_timeout)
+ queue->waitForNewEvents(clipboard_timeout - elapsed);
} while (timer.elapsed() < clipboard_timeout);
return nullptr;
diff --git a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
index c69912c361..af72285135 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
@@ -287,7 +287,7 @@ void QXcbBasicConnection::initializeShm()
logging->setEnabled(QtMsgType::QtWarningMsg, true);
}
-void QXcbBasicConnection::initializeXRandr()
+void QXcbBasicConnection::initializeXRender()
{
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_render_id);
if (!reply || !reply->present) {
@@ -303,7 +303,7 @@ void QXcbBasicConnection::initializeXRandr()
return;
}
- m_hasXRandr = true;
+ m_hasXRender = true;
m_xrenderVersion.first = xrenderQuery->major_version;
m_xrenderVersion.second = xrenderQuery->minor_version;
}
@@ -337,7 +337,7 @@ void QXcbBasicConnection::initializeXFixes()
m_xfixesFirstEvent = reply->first_event;
}
-void QXcbBasicConnection::initializeXRender()
+void QXcbBasicConnection::initializeXRandr()
{
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_randr_id);
if (!reply || !reply->present)
@@ -352,7 +352,7 @@ void QXcbBasicConnection::initializeXRender()
return;
}
- m_hasXRender = true;
+ m_hasXRandr = true;
m_xrandrFirstEvent = reply->first_event;
}
diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.cpp b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
index 527bca26a8..82a36c0727 100644
--- a/src/plugins/platforms/xcb/qxcbeventqueue.cpp
+++ b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
@@ -229,6 +229,8 @@ void QXcbEventQueue::run()
enqueueEvent(event);
while (!m_closeConnectionDetected && (event = xcb_poll_for_queued_event(connection)))
enqueueEvent(event);
+
+ m_newEventsCondition.wakeOne();
wakeUpDispatcher();
}
@@ -346,6 +348,13 @@ bool QXcbEventQueue::peekEventQueue(PeekerCallback peeker, void *peekerData,
return result;
}
+void QXcbEventQueue::waitForNewEvents(unsigned long time)
+{
+ m_newEventsMutex.lock();
+ m_newEventsCondition.wait(&m_newEventsMutex, time);
+ m_newEventsMutex.unlock();
+}
+
void QXcbEventQueue::sendCloseConnectionEvent() const
{
// A hack to close XCB connection. Apparently XCB does not have any APIs for this?
diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.h b/src/plugins/platforms/xcb/qxcbeventqueue.h
index 235f2824be..11d0b8e963 100644
--- a/src/plugins/platforms/xcb/qxcbeventqueue.h
+++ b/src/plugins/platforms/xcb/qxcbeventqueue.h
@@ -43,6 +43,8 @@
#include <QtCore/QHash>
#include <QtCore/QEventLoop>
#include <QtCore/QVector>
+#include <QtCore/QMutex>
+#include <QtCore/QWaitCondition>
#include <xcb/xcb.h>
@@ -104,6 +106,8 @@ public:
bool peekEventQueue(PeekerCallback peeker, void *peekerData = nullptr,
PeekOptions option = PeekDefault, qint32 peekerId = -1);
+ void waitForNewEvents(unsigned long time = ULONG_MAX);
+
private:
QXcbEventNode *qXcbEventNodeFactory(xcb_generic_event_t *event);
void dequeueNode();
@@ -131,6 +135,9 @@ private:
// debug stats
quint64 m_nodesOnHeap = 0;
+
+ QMutex m_newEventsMutex;
+ QWaitCondition m_newEventsCondition;
};
template<typename Peeker>
diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
index 647058167b..db3d6629b3 100644
--- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro
+++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
@@ -112,4 +112,8 @@ qtConfig(xkb) {
qtConfig(dlopen): QMAKE_USE += libdl
+# qxcbkeyboard.cpp's KeyTbl has more than 256 levels of expansion and older
+# Clang uses that as a limit (it's 1024 in current versions).
+clang:!intel_icc: QMAKE_CXXFLAGS += -ftemplate-depth=1024
+
load(qt_module)
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index 04fa280f39..a52871d302 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -3217,6 +3217,29 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
static_cast<NSTextFieldCell *>(tf.cell).bezelStyle = isRounded ? NSTextFieldRoundedBezel : NSTextFieldSquareBezel;
tf.frame = opt->rect.toCGRect();
d->drawNSViewInRect(tf, opt->rect, p, ^(CGContextRef, const CGRect &rect) {
+ if (!qt_mac_applicationIsInDarkMode()) {
+ // In 'Dark' mode controls are transparent, so we do not
+ // over-paint the (potentially custom) color in the background.
+ // In 'Light' mode we have to care about the correct
+ // background color. See the comments below for PE_PanelLineEdit.
+ CGContextRef cgContext = NSGraphicsContext.currentContext.CGContext;
+ // See QMacCGContext, here we expect bitmap context created with
+ // color space 'kCGColorSpaceSRGB', if it's something else - we
+ // give up.
+ if (cgContext ? bool(CGBitmapContextGetColorSpace(cgContext)) : false) {
+ tf.drawsBackground = YES;
+ const QColor bgColor = frame->palette.brush(QPalette::Base).color();
+ tf.backgroundColor = [NSColor colorWithSRGBRed:bgColor.redF()
+ green:bgColor.greenF()
+ blue:bgColor.blueF()
+ alpha:bgColor.alphaF()];
+ if (bgColor.alpha() != 255) {
+ // No way we can have it bezeled and transparent ...
+ tf.bordered = YES;
+ }
+ }
+ }
+
[tf.cell drawWithFrame:rect inView:tf];
});
} else {
@@ -3225,21 +3248,36 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
}
break;
case PE_PanelLineEdit:
- QCommonStyle::drawPrimitive(pe, opt, p, w);
- // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit).
- // Focus frame is drawn outside the rectangle passed in the option-rect.
- if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
-#if QT_CONFIG(lineedit)
- if ((opt->state & State_HasFocus) && !qobject_cast<const QLineEdit*>(w)) {
- int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin);
- int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin);
- QStyleOptionFrame focusFrame = *panel;
- focusFrame.rect = panel->rect.adjusted(-hmargin, -vmargin, hmargin, vmargin);
- drawControl(CE_FocusFrame, &focusFrame, p, w);
+ {
+ const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(opt);
+ if (qt_mac_applicationIsInDarkMode() || (panel && panel->lineWidth <= 0)) {
+ // QCommonStyle::drawPrimitive(PE_PanelLineEdit) fill the background with
+ // a proper color, defined in opt->palette and then, if lineWidth > 0, it
+ // calls QMacStyle::drawPrimitive(PE_FrameLineEdit). We use NSTextFieldCell
+ // to handle PE_FrameLineEdit, which will use system-default background.
+ // In 'Dark' mode it's transparent and thus it's not over-painted.
+ QCommonStyle::drawPrimitive(pe, opt, p, w);
+ } else {
+ // In 'Light' mode, if panel->lineWidth > 0, we have to use the correct
+ // background color when drawing PE_FrameLineEdit, so let's call it
+ // directly and set the proper color there.
+ drawPrimitive(PE_FrameLineEdit, opt, p, w);
}
+
+ // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit).
+ // Focus frame is drawn outside the rectangle passed in the option-rect.
+ if (panel) {
+#if QT_CONFIG(lineedit)
+ if ((opt->state & State_HasFocus) && !qobject_cast<const QLineEdit*>(w)) {
+ int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin);
+ int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin);
+ QStyleOptionFrame focusFrame = *panel;
+ focusFrame.rect = panel->rect.adjusted(-hmargin, -vmargin, hmargin, vmargin);
+ drawControl(CE_FocusFrame, &focusFrame, p, w);
+ }
#endif
+ }
}
-
break;
case PE_PanelScrollAreaCorner: {
const QBrush brush(opt->palette.brush(QPalette::Base));