summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r--src/plugins/platforms/xcb/CMakeLists.txt48
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/CMakeLists.txt8
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h1
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp161
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h6
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp36
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h3
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/CMakeLists.txt4
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp11
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp11
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp2
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp14
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qtessellator.cpp1
-rw-r--r--src/plugins/platforms/xcb/qt_xlib_wrapper.c7
-rw-r--r--src/plugins/platforms/xcb/qt_xlib_wrapper.h17
-rw-r--r--src/plugins/platforms/xcb/qxcbatom.cpp33
-rw-r--r--src/plugins/platforms/xcb/qxcbatom.h343
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp52
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp93
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h8
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_basic.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_screens.cpp48
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp231
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp167
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.h12
-rw-r--r--src/plugins/platforms/xcb/qxcbcursorfont.h88
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp122
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbeventqueue.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp97
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h9
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp18
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h8
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.cpp35
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp62
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbsessionmanager.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp570
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h14
-rw-r--r--src/plugins/platforms/xcb/qxcbwmsupport.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.cpp6
48 files changed, 1450 insertions, 950 deletions
diff --git a/src/plugins/platforms/xcb/CMakeLists.txt b/src/plugins/platforms/xcb/CMakeLists.txt
index c73b2de73f..e8fb442dd4 100644
--- a/src/plugins/platforms/xcb/CMakeLists.txt
+++ b/src/plugins/platforms/xcb/CMakeLists.txt
@@ -1,9 +1,15 @@
-# Generated from xcb.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## XcbQpaPrivate Module:
#####################################################################
+if(GCC)
+ # Work around GCC ABI issues
+ add_compile_options(-Wno-psabi)
+endif()
+
qt_internal_add_module(XcbQpaPrivate
CONFIG_MODULE_NAME xcb_qpa_lib
INTERNAL_MODULE
@@ -44,6 +50,7 @@ qt_internal_add_module(XcbQpaPrivate
PkgConfig::XKB_COMMON_X11
Qt::CorePrivate
Qt::GuiPrivate
+ XCB::CURSOR
XCB::ICCCM
XCB::IMAGE
XCB::KEYSYMS
@@ -55,23 +62,16 @@ qt_internal_add_module(XcbQpaPrivate
XCB::SYNC
XCB::XCB
XCB::XFIXES
- # XCB::XINPUT # special case remove handled below
XCB::XKB
XKB::XKB
+ NO_UNITY_BUILD # X11 define clashes
)
-# special case begin
qt_disable_apple_app_extension_api_only(XcbQpaPrivate)
-# special case end
## Scopes:
#####################################################################
-qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_opengl
- PUBLIC_LIBRARIES
- Qt::OpenGLPrivate
-)
-
qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_glib
LIBRARIES
GLIB2::GLIB2
@@ -83,21 +83,24 @@ qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_draganddrop
)
qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_xcb_xlib
+ SOURCES
+ qt_xlib_wrapper.c qt_xlib_wrapper.h
PUBLIC_LIBRARIES
X11::XCB
- # special case begin
- # 'QMAKE_USE += xcb_xlib' in qmake implies also += xlib (aka X11)
- # due to "use": "xcb xlib" in src/gui/configure.json.
- # That's not yet handled by the conversion scripts unfortunately.
X11::X11
- # special case end
+)
+
+qt_internal_extend_target(XcbQpaPrivate CONDITION NOT QT_FEATURE_xcb_xlib
+ SOURCES
+ qxcbcursorfont.h
)
qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_xcb_sm
SOURCES
qxcbsessionmanager.cpp qxcbsessionmanager.h
PUBLIC_LIBRARIES
- ${X11_SM_LIB} ${X11_ICE_LIB}
+ X11::SM
+ X11::ICE
)
qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_vulkan
@@ -140,7 +143,6 @@ qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_fontconfig AND QT_F
WrapFreetype::WrapFreetype
)
-# special case begin
if(QT_FEATURE_system_xcb_xinput)
qt_internal_extend_target(XcbQpaPrivate LIBRARIES XCB::XINPUT)
else()
@@ -154,7 +156,6 @@ else()
"${PROJECT_SOURCE_DIR}/src/3rdparty/xcb/include"
)
endif()
-# special case end
#####################################################################
## QXcbIntegrationPlugin Plugin:
@@ -163,7 +164,7 @@ endif()
qt_internal_add_plugin(QXcbIntegrationPlugin
OUTPUT_NAME qxcb
PLUGIN_TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES xcb # special case
+ DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES xcb
SOURCES
qxcbmain.cpp
DEFINES
@@ -174,16 +175,7 @@ qt_internal_add_plugin(QXcbIntegrationPlugin
Qt::XcbQpaPrivate
)
-#### Keys ignored in scope 18:.:.:xcb-plugin.pro:<TRUE>:
-# OTHER_FILES = "xcb.json" "README"
-
-## Scopes:
-#####################################################################
-
-#### Keys ignored in scope 20:.:.:xcb-plugin.pro:NOT TARGET___equals____ss_QT_DEFAULT_QPA_PLUGIN:
-# PLUGIN_EXTENDS = "-"
add_subdirectory(gl_integrations)
if(OFF)
- add_subdirectory(xcb-static) # special case TODO: xcb-static sub folder
+ add_subdirectory(xcb-static)
endif()
-
diff --git a/src/plugins/platforms/xcb/gl_integrations/CMakeLists.txt b/src/plugins/platforms/xcb/gl_integrations/CMakeLists.txt
index 210a924550..957beb9ed4 100644
--- a/src/plugins/platforms/xcb/gl_integrations/CMakeLists.txt
+++ b/src/plugins/platforms/xcb/gl_integrations/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from gl_integrations.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
if(QT_FEATURE_xcb_egl_plugin)
add_subdirectory(xcb_egl)
diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h
index 6e841370d8..c6492f02ae 100644
--- a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h
+++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h
@@ -14,7 +14,7 @@ class QPlatformOffscreenSurface;
class QOffscreenSurface;
class QXcbNativeInterfaceHandler;
-Q_XCB_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcQpaGl)
+Q_DECLARE_EXPORTED_LOGGING_CATEGORY(lcQpaGl, Q_XCB_EXPORT)
class Q_XCB_EXPORT QXcbGlIntegration
{
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/CMakeLists.txt b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/CMakeLists.txt
index 4a62c8ad46..12938c159a 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/CMakeLists.txt
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/CMakeLists.txt
@@ -1,10 +1,11 @@
-# Generated from xcb_egl.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## QXcbEglIntegrationPlugin Plugin:
#####################################################################
-qt_find_package(EGL) # special case
+qt_find_package(EGL)
qt_internal_add_plugin(QXcbEglIntegrationPlugin
OUTPUT_NAME qxcb-egl-integration
@@ -26,5 +27,6 @@ qt_internal_add_plugin(QXcbEglIntegrationPlugin
Qt::Gui
Qt::GuiPrivate
Qt::XcbQpaPrivate
- EGL::EGL # special case
+ EGL::EGL
+ NO_UNITY_BUILD # X11 define clashes
)
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h
index 17428f778f..d12501bd90 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h
@@ -7,7 +7,6 @@
#include <QtGui/QPalette>
#include <QtCore/QTextStream>
#include <QtGui/private/qmath_p.h>
-#include <QtGui/private/qcssparser_p.h>
#include <QtGui/private/qtextengine_p.h>
#include <QtGui/private/qt_egl_p.h>
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
index 2ab89f07d6..133b992cd9 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
@@ -6,15 +6,59 @@
#include "qxcbeglcontext.h"
#include <QtGui/QOffscreenSurface>
+#include <QtGui/private/qeglconvenience_p.h>
#include <QtGui/private/qeglstreamconvenience_p.h>
+#include <optional>
#include "qxcbeglnativeinterfacehandler.h"
QT_BEGIN_NAMESPACE
+namespace {
+
+struct VisualInfo
+{
+ xcb_visualtype_t visualType;
+ uint8_t depth;
+};
+
+std::optional<VisualInfo> getVisualInfo(xcb_screen_t *screen,
+ std::optional<xcb_visualid_t> requestedVisualId,
+ std::optional<uint8_t> requestedDepth = std::nullopt)
+{
+ xcb_depth_iterator_t depthIterator = xcb_screen_allowed_depths_iterator(screen);
+
+ while (depthIterator.rem) {
+ xcb_depth_t *depth = depthIterator.data;
+ xcb_visualtype_iterator_t visualTypeIterator = xcb_depth_visuals_iterator(depth);
+
+ while (visualTypeIterator.rem) {
+ xcb_visualtype_t *visualType = visualTypeIterator.data;
+ if (requestedVisualId && visualType->visual_id != *requestedVisualId) {
+ xcb_visualtype_next(&visualTypeIterator);
+ continue;
+ }
+
+ if (requestedDepth && depth->depth != *requestedDepth) {
+ xcb_visualtype_next(&visualTypeIterator);
+ continue;
+ }
+
+ return VisualInfo{ *visualType, depth->depth };
+ }
+
+ xcb_depth_next(&depthIterator);
+ }
+
+ return std::nullopt;
+}
+
+} // namespace
+
QXcbEglIntegration::QXcbEglIntegration()
: m_connection(nullptr)
, m_egl_display(EGL_NO_DISPLAY)
+ , m_using_platform_display(false)
{
qCDebug(lcQpaGl) << "Xcb EGL gl-integration created";
}
@@ -31,23 +75,38 @@ bool QXcbEglIntegration::initialize(QXcbConnection *connection)
const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+#if QT_CONFIG(xcb_xlib)
if (extensions && strstr(extensions, "EGL_EXT_platform_x11")) {
QEGLStreamConvenience streamFuncs;
m_egl_display = streamFuncs.get_platform_display(EGL_PLATFORM_X11_KHR,
- xlib_display(),
+ m_connection->xlib_display(),
nullptr);
+ m_using_platform_display = true;
}
+#if QT_CONFIG(egl_x11)
if (!m_egl_display)
- m_egl_display = eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(xlib_display()));
+ m_egl_display = eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(m_connection->xlib_display()));
+#endif
+#else
+ if (extensions && (strstr(extensions, "EGL_EXT_platform_xcb") || strstr(extensions, "EGL_MESA_platform_xcb"))) {
+ QEGLStreamConvenience streamFuncs;
+ m_egl_display = streamFuncs.get_platform_display(EGL_PLATFORM_XCB_KHR,
+ reinterpret_cast<void *>(connection->xcb_connection()),
+ nullptr);
+ m_using_platform_display = true;
+ }
+#endif
EGLint major, minor;
bool success = eglInitialize(m_egl_display, &major, &minor);
+#if QT_CONFIG(egl_x11)
if (!success) {
m_egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
qCDebug(lcQpaGl) << "Xcb EGL gl-integration retrying with display" << m_egl_display;
success = eglInitialize(m_egl_display, &major, &minor);
}
+#endif
m_native_interface_handler.reset(new QXcbEglNativeInterfaceHandler(connection->nativeInterface()));
@@ -84,13 +143,99 @@ QPlatformOffscreenSurface *QXcbEglIntegration::createPlatformOffscreenSurface(QO
return new QEGLPbuffer(eglDisplay(), screen->surfaceFormatFor(surface->requestedFormat()), surface);
}
-void *QXcbEglIntegration::xlib_display() const
+xcb_visualid_t QXcbEglIntegration::getCompatibleVisualId(xcb_screen_t *screen, EGLConfig config) const
{
-#if QT_CONFIG(xcb_xlib)
- return m_connection->xlib_display();
-#else
- return EGL_DEFAULT_DISPLAY;
-#endif
+ xcb_visualid_t visualId = 0;
+ EGLint eglValue = 0;
+
+ EGLint configRedSize = 0;
+ eglGetConfigAttrib(eglDisplay(), config, EGL_RED_SIZE, &configRedSize);
+
+ EGLint configGreenSize = 0;
+ eglGetConfigAttrib(eglDisplay(), config, EGL_GREEN_SIZE, &configGreenSize);
+
+ EGLint configBlueSize = 0;
+ eglGetConfigAttrib(eglDisplay(), config, EGL_BLUE_SIZE, &configBlueSize);
+
+ EGLint configAlphaSize = 0;
+ eglGetConfigAttrib(eglDisplay(), config, EGL_ALPHA_SIZE, &configAlphaSize);
+
+ eglGetConfigAttrib(eglDisplay(), config, EGL_CONFIG_ID, &eglValue);
+ int configId = eglValue;
+
+ // See if EGL provided a valid VisualID:
+ eglGetConfigAttrib(eglDisplay(), config, EGL_NATIVE_VISUAL_ID, &eglValue);
+ visualId = eglValue;
+ if (visualId) {
+ // EGL has suggested a visual id, so get the rest of the visual info for that id:
+ std::optional<VisualInfo> chosenVisualInfo = getVisualInfo(screen, visualId);
+ if (chosenVisualInfo) {
+ // Skip size checks if implementation supports non-matching visual
+ // and config (QTBUG-9444).
+ if (q_hasEglExtension(eglDisplay(), "EGL_NV_post_convert_rounding"))
+ return visualId;
+ // Skip also for i.MX6 where 565 visuals are suggested for the default 444 configs and it works just fine.
+ const char *vendor = eglQueryString(eglDisplay(), EGL_VENDOR);
+ if (vendor && strstr(vendor, "Vivante"))
+ return visualId;
+
+ int visualRedSize = qPopulationCount(chosenVisualInfo->visualType.red_mask);
+ int visualGreenSize = qPopulationCount(chosenVisualInfo->visualType.green_mask);
+ int visualBlueSize = qPopulationCount(chosenVisualInfo->visualType.blue_mask);
+ int visualAlphaSize = chosenVisualInfo->depth - visualRedSize - visualBlueSize - visualGreenSize;
+
+ const bool visualMatchesConfig = visualRedSize >= configRedSize
+ && visualGreenSize >= configGreenSize
+ && visualBlueSize >= configBlueSize
+ && visualAlphaSize >= configAlphaSize;
+
+ // In some cases EGL tends to suggest a 24-bit visual for 8888
+ // configs. In such a case we have to fall back to getVisualInfo.
+ if (!visualMatchesConfig) {
+ visualId = 0;
+ qCDebug(lcQpaGl,
+ "EGL suggested using X Visual ID %d (%d %d %d %d depth %d) for EGL config %d"
+ "(%d %d %d %d), but this is incompatible",
+ visualId, visualRedSize, visualGreenSize, visualBlueSize, visualAlphaSize, chosenVisualInfo->depth,
+ configId, configRedSize, configGreenSize, configBlueSize, configAlphaSize);
+ }
+ } else {
+ qCDebug(lcQpaGl, "EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID",
+ visualId, configId);
+ visualId = 0;
+ }
+ }
+ else
+ qCDebug(lcQpaGl, "EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId);
+
+ if (visualId) {
+ qCDebug(lcQpaGl, configAlphaSize > 0
+ ? "Using ARGB Visual ID %d provided by EGL for config %d"
+ : "Using Opaque Visual ID %d provided by EGL for config %d", visualId, configId);
+ return visualId;
+ }
+
+ // Finally, try to use getVisualInfo and only use the bit depths to match on:
+ if (!visualId) {
+ uint8_t depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize;
+ std::optional<VisualInfo> matchingVisual = getVisualInfo(screen, std::nullopt, depth);
+ if (!matchingVisual) {
+ // Try again without taking the alpha channel into account:
+ depth = configRedSize + configGreenSize + configBlueSize;
+ matchingVisual = getVisualInfo(screen, std::nullopt, depth);
+ }
+
+ if (matchingVisual)
+ visualId = matchingVisual->visualType.visual_id;
+ }
+
+ if (visualId) {
+ qCDebug(lcQpaGl, "Using Visual ID %d provided by getVisualInfo for EGL config %d", visualId, configId);
+ return visualId;
+ }
+
+ qWarning("Unable to find an X11 visual which matches EGL config %d", configId);
+ return 0;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h
index 5ea37c0924..7caf4304bc 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h
@@ -38,10 +38,14 @@ public:
bool supportsThreadedOpenGL() const override { return true; }
EGLDisplay eglDisplay() const { return m_egl_display; }
- void *xlib_display() const;
+
+ bool usingPlatformDisplay() const { return m_using_platform_display; }
+
+ xcb_visualid_t getCompatibleVisualId(xcb_screen_t *screen, EGLConfig config) const;
private:
QXcbConnection *m_connection;
EGLDisplay m_egl_display;
+ bool m_using_platform_display;
QScopedPointer<QXcbEglNativeInterfaceHandler> m_native_interface_handler;
};
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp
index e5ca2b4864..bf2ceb96f4 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp
@@ -6,7 +6,10 @@
#include "qxcbeglintegration.h"
#include <QtGui/private/qeglconvenience_p.h>
-#include <QtGui/private/qxlibeglintegration_p.h>
+
+#ifndef EGL_EXT_platform_base
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+#endif
QT_BEGIN_NAMESPACE
@@ -29,35 +32,34 @@ void QXcbEglWindow::resolveFormat(const QSurfaceFormat &format)
m_format = q_glFormatFromConfig(m_glIntegration->eglDisplay(), m_config, format);
}
-#if QT_CONFIG(xcb_xlib)
const xcb_visualtype_t *QXcbEglWindow::createVisual()
{
QXcbScreen *scr = xcbScreen();
if (!scr)
return QXcbWindow::createVisual();
- Display *xdpy = static_cast<Display *>(m_glIntegration->xlib_display());
- VisualID id = QXlibEglIntegration::getCompatibleVisualId(xdpy, m_glIntegration->eglDisplay(), m_config);
-
- XVisualInfo visualInfoTemplate;
- memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
- visualInfoTemplate.visualid = id;
-
- XVisualInfo *visualInfo;
- int matchingCount = 0;
- visualInfo = XGetVisualInfo(xdpy, VisualIDMask, &visualInfoTemplate, &matchingCount);
- const xcb_visualtype_t *xcb_visualtype = scr->visualForId(visualInfo->visualid);
- XFree(visualInfo);
-
- return xcb_visualtype;
+ xcb_visualid_t id = m_glIntegration->getCompatibleVisualId(scr->screen(), m_config);
+ return scr->visualForId(id);
}
-#endif
void QXcbEglWindow::create()
{
QXcbWindow::create();
+ // this is always true without egl_x11
+ if (m_glIntegration->usingPlatformDisplay()) {
+ auto createPlatformWindowSurface = reinterpret_cast<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>(
+ eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"));
+ m_surface = createPlatformWindowSurface(m_glIntegration->eglDisplay(),
+ m_config,
+ reinterpret_cast<void *>(&m_window),
+ nullptr);
+ return;
+ }
+
+#if QT_CONFIG(egl_x11)
m_surface = eglCreateWindowSurface(m_glIntegration->eglDisplay(), m_config, m_window, nullptr);
+#endif
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h
index 79f1df0493..935a0c6d43 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h
@@ -25,10 +25,7 @@ public:
protected:
void create() override;
void resolveFormat(const QSurfaceFormat &format) override;
-
-#if QT_CONFIG(xcb_xlib)
const xcb_visualtype_t *createVisual() override;
-#endif
private:
QXcbEglIntegration *m_glIntegration;
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/CMakeLists.txt b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/CMakeLists.txt
index ae81eba545..f9f78ad1eb 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/CMakeLists.txt
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from xcb_glx.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## QXcbGlxIntegrationPlugin Plugin:
@@ -24,6 +25,7 @@ qt_internal_add_plugin(QXcbGlxIntegrationPlugin
Qt::Gui
Qt::GuiPrivate
Qt::XcbQpaPrivate
+ NO_UNITY_BUILD # X11 define clashes
)
## Scopes:
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
index 5992ebd74e..04eac027cd 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
@@ -242,9 +242,9 @@ QGLXContext::QGLXContext(Display *display, QXcbScreen *screen, const QSurfaceFor
// Robustness must match that of the shared context.
if (share && share->format().testOption(QSurfaceFormat::ResetNotification))
m_format.setOption(QSurfaceFormat::ResetNotification);
- Q_ASSERT(glVersions.count() > 0);
+ Q_ASSERT(glVersions.size() > 0);
- for (int i = 0; !m_context && i < glVersions.count(); i++) {
+ for (int i = 0; !m_context && i < glVersions.size(); i++) {
const int version = glVersions[i];
if (version > requestedVersion)
continue;
@@ -395,14 +395,19 @@ QGLXContext::QGLXContext(Display *display, GLXContext context, void *visualInfo,
int numConfigs = 0;
static const int attribs[] = { GLX_FBCONFIG_ID, configId, None };
configs = glXChooseFBConfig(m_display, screenNumber, attribs, &numConfigs);
- if (!configs || numConfigs < 1) {
+ if (!configs) {
+ qWarning("QGLXContext: Failed to find config(invalid arguments for glXChooseFBConfig)");
+ return;
+ } else if (numConfigs < 1) {
qWarning("QGLXContext: Failed to find config");
+ XFree(configs);
return;
}
if (configs && numConfigs > 1) // this is suspicious so warn but let it continue
qWarning("QGLXContext: Multiple configs for FBConfig ID %d", configId);
m_config = configs[0];
+ XFree(configs);
}
Q_ASSERT(vinfo || m_config);
diff --git a/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp
index 96a19552a5..d523eecc5a 100644
--- a/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp
+++ b/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp
@@ -16,10 +16,6 @@
#include <X11/Xlib.h>
#undef register
-#ifndef None
-#define None 0L
-#endif
-
QT_BEGIN_NAMESPACE
QXcbNativeBackingStore::QXcbNativeBackingStore(QWindow *window)
@@ -78,11 +74,8 @@ void QXcbNativeBackingStore::flush(QWindow *window, const QRegion &region, const
XRenderSetPictureClipRectangles(display(), dstPic, 0, 0, clipRects.constData(), clipRects.size());
- XRenderComposite(display(), PictOpSrc, srcPic, None, dstPic,
- br.x() + offset.x(), br.y() + offset.y(),
- 0, 0,
- br.x(), br.y(),
- br.width(), br.height());
+ XRenderComposite(display(), PictOpSrc, srcPic, 0L /*None*/, dstPic, br.x() + offset.x(),
+ br.y() + offset.y(), 0, 0, br.x(), br.y(), br.width(), br.height());
XRenderFreePicture(display(), dstPic);
}
diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
index f630f538aa..743ff92654 100644
--- a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
+++ b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
@@ -2134,7 +2134,7 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect
XFillRectangle(d->dpy, d->hd, d->gc, x, y, sw, sh);
restore_clip = true;
} else if (mono_dst && !mono_src) {
- QBitmap bitmap(pixmap);
+ QBitmap bitmap = QBitmap::fromPixmap(pixmap);
XCopyArea(d->dpy, qt_x11PixmapHandle(bitmap), d->hd, d->gc, sx, sy, sw, sh, x, y);
} else {
XCopyArea(d->dpy, qt_x11PixmapHandle(pixmap), d->hd, d->gc, sx, sy, sw, sh, x, y);
diff --git a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp
index 2a84431cde..a4e820ea92 100644
--- a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp
+++ b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp
@@ -1314,7 +1314,7 @@ QBitmap QX11PlatformPixmap::mask() const
#endif
if (d == 1) {
QX11PlatformPixmap *that = const_cast<QX11PlatformPixmap*>(this);
- mask = QPixmap(that);
+ mask = QBitmap::fromPixmap(QPixmap(that));
} else {
mask = mask_to_bitmap(xinfo.screen());
}
@@ -1437,22 +1437,16 @@ QPixmap QX11PlatformPixmap::transformed(const QTransform &transform, Qt::Transfo
transform.m21(), transform.m22(), transform.m23(),
0., 0., 1);
bool complex_xform = false;
- qreal scaledWidth;
- qreal scaledHeight;
if (mat.type() <= QTransform::TxScale) {
- scaledHeight = qAbs(mat.m22()) * hs + 0.9999;
- scaledWidth = qAbs(mat.m11()) * ws + 0.9999;
- h = qAbs(int(scaledHeight));
- w = qAbs(int(scaledWidth));
+ h = qRound(qAbs(mat.m22()) * hs);
+ w = qRound(qAbs(mat.m11()) * ws);
} else { // rotation or shearing
QPolygonF a(QRectF(0, 0, ws, hs));
a = mat.map(a);
QRect r = a.boundingRect().toAlignedRect();
w = r.width();
h = r.height();
- scaledWidth = w;
- scaledHeight = h;
complex_xform = true;
}
mat = QPixmap::trueMatrix(mat, ws, hs); // true matrix
@@ -1461,7 +1455,7 @@ QPixmap QX11PlatformPixmap::transformed(const QTransform &transform, Qt::Transfo
mat = mat.inverted(&invertible); // invert matrix
if (h == 0 || w == 0 || !invertible
- || qAbs(scaledWidth) >= 32768 || qAbs(scaledHeight) >= 32768 )
+ || qAbs(h) >= 32768 || qAbs(w) >= 32768 )
// error, return null pixmap
return QPixmap();
diff --git a/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp b/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp
index ecc21eb1f5..7b0094044b 100644
--- a/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp
+++ b/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp
@@ -5,6 +5,7 @@
#include <QRect>
#include <QList>
+#include <QMap>
#include <QDebug>
#include <qmath.h>
diff --git a/src/plugins/platforms/xcb/qt_xlib_wrapper.c b/src/plugins/platforms/xcb/qt_xlib_wrapper.c
new file mode 100644
index 0000000000..f4614e5504
--- /dev/null
+++ b/src/plugins/platforms/xcb/qt_xlib_wrapper.c
@@ -0,0 +1,7 @@
+// 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
+#include "qt_xlib_wrapper.h"
+
+#include <X11/Xlib.h>
+
+void qt_XFlush(Display *dpy) { XFlush(dpy); }
diff --git a/src/plugins/platforms/xcb/qt_xlib_wrapper.h b/src/plugins/platforms/xcb/qt_xlib_wrapper.h
new file mode 100644
index 0000000000..642dbdeadd
--- /dev/null
+++ b/src/plugins/platforms/xcb/qt_xlib_wrapper.h
@@ -0,0 +1,17 @@
+// 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
+#ifndef QT_XLIB_WRAPPER_H
+#define QT_XLIB_WRAPPER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef struct _XDisplay Display;
+ void qt_XFlush(Display *dpy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // QT_XLIB_WRAPPER_H
diff --git a/src/plugins/platforms/xcb/qxcbatom.cpp b/src/plugins/platforms/xcb/qxcbatom.cpp
index 8f984c7280..dd5596653c 100644
--- a/src/plugins/platforms/xcb/qxcbatom.cpp
+++ b/src/plugins/platforms/xcb/qxcbatom.cpp
@@ -54,6 +54,8 @@ static const char *xcb_atomnames = {
"_QT_CLOSE_CONNECTION\0"
+ "_QT_GET_TIMESTAMP\0"
+
"_MOTIF_WM_HINTS\0"
"DTWM_IS_RUNNING\0"
@@ -109,11 +111,13 @@ static const char *xcb_atomnames = {
"_NET_WM_WINDOW_TYPE_NORMAL\0"
"_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"
+ "_KDE_NET_WM_DESKTOP_FILE\0"
"_KDE_NET_WM_FRAME_STRUT\0"
"_NET_FRAME_EXTENTS\0"
"_NET_STARTUP_INFO\0"
"_NET_STARTUP_INFO_BEGIN\0"
+ "_NET_STARTUP_ID\0"
"_NET_SUPPORTING_WM_CHECK\0"
@@ -193,6 +197,7 @@ static const char *xcb_atomnames = {
"_COMPIZ_DECOR_REQUEST\0"
"_COMPIZ_DECOR_DELETE_PIXMAP\0"
"_COMPIZ_TOOLKIT_ACTION\0"
+ "_GTK_APPLICATION_ID\0"
"_GTK_LOAD_ICONTHEMES\0"
"AT_SPI_BUS\0"
"EDID\0"
@@ -212,29 +217,25 @@ void QXcbAtom::initialize(xcb_connection_t *connection)
}
void QXcbAtom::initializeAllAtoms(xcb_connection_t *connection) {
- const char *names[QXcbAtom::NAtoms];
- const char *ptr = xcb_atomnames;
-
+ const char *name = xcb_atomnames;
+ size_t name_len;
int i = 0;
- while (*ptr) {
- names[i++] = ptr;
- while (*ptr)
- ++ptr;
- ++ptr;
- }
-
- Q_ASSERT(i == QXcbAtom::NAtoms);
-
xcb_intern_atom_cookie_t cookies[QXcbAtom::NAtoms];
+ while ((name_len = strlen(name)) != 0) {
+ cookies[i] = xcb_intern_atom(connection, false, name_len, name);
+ ++i;
+ name += name_len + 1; // jump over the \0
+ }
+
Q_ASSERT(i == QXcbAtom::NAtoms);
- for (i = 0; i < QXcbAtom::NAtoms; ++i)
- cookies[i] = xcb_intern_atom(connection, false, strlen(names[i]), names[i]);
for (i = 0; i < QXcbAtom::NAtoms; ++i) {
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, cookies[i], nullptr);
- m_allAtoms[i] = reply->atom;
- free(reply);
+ if (reply) {
+ m_allAtoms[i] = reply->atom;
+ free(reply);
+ }
}
}
diff --git a/src/plugins/platforms/xcb/qxcbatom.h b/src/plugins/platforms/xcb/qxcbatom.h
index 48924dd626..bc677eaf3e 100644
--- a/src/plugins/platforms/xcb/qxcbatom.h
+++ b/src/plugins/platforms/xcb/qxcbatom.h
@@ -10,201 +10,206 @@ class QXcbAtom
public:
enum Atom {
// window-manager <-> client protocols
- WM_PROTOCOLS,
- WM_DELETE_WINDOW,
- WM_TAKE_FOCUS,
- _NET_WM_PING,
- _NET_WM_CONTEXT_HELP,
- _NET_WM_SYNC_REQUEST,
- _NET_WM_SYNC_REQUEST_COUNTER,
- MANAGER, // System tray notification
- _NET_SYSTEM_TRAY_OPCODE, // System tray operation
+ AtomWM_PROTOCOLS,
+ AtomWM_DELETE_WINDOW,
+ AtomWM_TAKE_FOCUS,
+ Atom_NET_WM_PING,
+ Atom_NET_WM_CONTEXT_HELP,
+ Atom_NET_WM_SYNC_REQUEST,
+ Atom_NET_WM_SYNC_REQUEST_COUNTER,
+ AtomMANAGER, // System tray notification
+ Atom_NET_SYSTEM_TRAY_OPCODE, // System tray operation
// ICCCM window state
- WM_STATE,
- WM_CHANGE_STATE,
- WM_CLASS,
- WM_NAME,
+ AtomWM_STATE,
+ AtomWM_CHANGE_STATE,
+ AtomWM_CLASS,
+ AtomWM_NAME,
// Session management
- WM_CLIENT_LEADER,
- WM_WINDOW_ROLE,
- SM_CLIENT_ID,
- WM_CLIENT_MACHINE,
+ AtomWM_CLIENT_LEADER,
+ AtomWM_WINDOW_ROLE,
+ AtomSM_CLIENT_ID,
+ AtomWM_CLIENT_MACHINE,
// Clipboard
- CLIPBOARD,
- INCR,
- TARGETS,
- MULTIPLE,
- TIMESTAMP,
- SAVE_TARGETS,
- CLIP_TEMPORARY,
- _QT_SELECTION,
- _QT_CLIPBOARD_SENTINEL,
- _QT_SELECTION_SENTINEL,
- CLIPBOARD_MANAGER,
+ AtomCLIPBOARD,
+ AtomINCR,
+ AtomTARGETS,
+ AtomMULTIPLE,
+ AtomTIMESTAMP,
+ AtomSAVE_TARGETS,
+ AtomCLIP_TEMPORARY,
+ Atom_QT_SELECTION,
+ Atom_QT_CLIPBOARD_SENTINEL,
+ Atom_QT_SELECTION_SENTINEL,
+ AtomCLIPBOARD_MANAGER,
- RESOURCE_MANAGER,
+ AtomRESOURCE_MANAGER,
- _XSETROOT_ID,
+ Atom_XSETROOT_ID,
- _QT_SCROLL_DONE,
- _QT_INPUT_ENCODING,
+ Atom_QT_SCROLL_DONE,
+ Atom_QT_INPUT_ENCODING,
// Qt/XCB specific
- _QT_CLOSE_CONNECTION,
+ Atom_QT_CLOSE_CONNECTION,
- _MOTIF_WM_HINTS,
+ Atom_QT_GET_TIMESTAMP,
- DTWM_IS_RUNNING,
- ENLIGHTENMENT_DESKTOP,
- _DT_SAVE_MODE,
- _SGI_DESKS_MANAGER,
+ Atom_MOTIF_WM_HINTS,
+
+ AtomDTWM_IS_RUNNING,
+ AtomENLIGHTENMENT_DESKTOP,
+ Atom_DT_SAVE_MODE,
+ Atom_SGI_DESKS_MANAGER,
// EWMH (aka NETWM)
- _NET_SUPPORTED,
- _NET_VIRTUAL_ROOTS,
- _NET_WORKAREA,
-
- _NET_MOVERESIZE_WINDOW,
- _NET_WM_MOVERESIZE,
-
- _NET_WM_NAME,
- _NET_WM_ICON_NAME,
- _NET_WM_ICON,
-
- _NET_WM_PID,
-
- _NET_WM_WINDOW_OPACITY,
-
- _NET_WM_STATE,
- _NET_WM_STATE_ABOVE,
- _NET_WM_STATE_BELOW,
- _NET_WM_STATE_FULLSCREEN,
- _NET_WM_STATE_MAXIMIZED_HORZ,
- _NET_WM_STATE_MAXIMIZED_VERT,
- _NET_WM_STATE_MODAL,
- _NET_WM_STATE_STAYS_ON_TOP,
- _NET_WM_STATE_DEMANDS_ATTENTION,
- _NET_WM_STATE_HIDDEN,
-
- _NET_WM_USER_TIME,
- _NET_WM_USER_TIME_WINDOW,
- _NET_WM_FULL_PLACEMENT,
-
- _NET_WM_WINDOW_TYPE,
- _NET_WM_WINDOW_TYPE_DESKTOP,
- _NET_WM_WINDOW_TYPE_DOCK,
- _NET_WM_WINDOW_TYPE_TOOLBAR,
- _NET_WM_WINDOW_TYPE_MENU,
- _NET_WM_WINDOW_TYPE_UTILITY,
- _NET_WM_WINDOW_TYPE_SPLASH,
- _NET_WM_WINDOW_TYPE_DIALOG,
- _NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
- _NET_WM_WINDOW_TYPE_POPUP_MENU,
- _NET_WM_WINDOW_TYPE_TOOLTIP,
- _NET_WM_WINDOW_TYPE_NOTIFICATION,
- _NET_WM_WINDOW_TYPE_COMBO,
- _NET_WM_WINDOW_TYPE_DND,
- _NET_WM_WINDOW_TYPE_NORMAL,
- _KDE_NET_WM_WINDOW_TYPE_OVERRIDE,
-
- _KDE_NET_WM_FRAME_STRUT,
- _NET_FRAME_EXTENTS,
-
- _NET_STARTUP_INFO,
- _NET_STARTUP_INFO_BEGIN,
-
- _NET_SUPPORTING_WM_CHECK,
-
- _NET_WM_CM_S0,
-
- _NET_SYSTEM_TRAY_VISUAL,
-
- _NET_ACTIVE_WINDOW,
+ Atom_NET_SUPPORTED,
+ Atom_NET_VIRTUAL_ROOTS,
+ Atom_NET_WORKAREA,
+
+ Atom_NET_MOVERESIZE_WINDOW,
+ Atom_NET_WM_MOVERESIZE,
+
+ Atom_NET_WM_NAME,
+ Atom_NET_WM_ICON_NAME,
+ Atom_NET_WM_ICON,
+
+ Atom_NET_WM_PID,
+
+ Atom_NET_WM_WINDOW_OPACITY,
+
+ Atom_NET_WM_STATE,
+ Atom_NET_WM_STATE_ABOVE,
+ Atom_NET_WM_STATE_BELOW,
+ Atom_NET_WM_STATE_FULLSCREEN,
+ Atom_NET_WM_STATE_MAXIMIZED_HORZ,
+ Atom_NET_WM_STATE_MAXIMIZED_VERT,
+ Atom_NET_WM_STATE_MODAL,
+ Atom_NET_WM_STATE_STAYS_ON_TOP,
+ Atom_NET_WM_STATE_DEMANDS_ATTENTION,
+ Atom_NET_WM_STATE_HIDDEN,
+
+ Atom_NET_WM_USER_TIME,
+ Atom_NET_WM_USER_TIME_WINDOW,
+ Atom_NET_WM_FULL_PLACEMENT,
+
+ Atom_NET_WM_WINDOW_TYPE,
+ Atom_NET_WM_WINDOW_TYPE_DESKTOP,
+ Atom_NET_WM_WINDOW_TYPE_DOCK,
+ Atom_NET_WM_WINDOW_TYPE_TOOLBAR,
+ Atom_NET_WM_WINDOW_TYPE_MENU,
+ Atom_NET_WM_WINDOW_TYPE_UTILITY,
+ Atom_NET_WM_WINDOW_TYPE_SPLASH,
+ Atom_NET_WM_WINDOW_TYPE_DIALOG,
+ Atom_NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
+ Atom_NET_WM_WINDOW_TYPE_POPUP_MENU,
+ Atom_NET_WM_WINDOW_TYPE_TOOLTIP,
+ Atom_NET_WM_WINDOW_TYPE_NOTIFICATION,
+ Atom_NET_WM_WINDOW_TYPE_COMBO,
+ Atom_NET_WM_WINDOW_TYPE_DND,
+ Atom_NET_WM_WINDOW_TYPE_NORMAL,
+ Atom_KDE_NET_WM_WINDOW_TYPE_OVERRIDE,
+
+ Atom_KDE_NET_WM_DESKTOP_FILE,
+ Atom_KDE_NET_WM_FRAME_STRUT,
+ Atom_NET_FRAME_EXTENTS,
+
+ Atom_NET_STARTUP_INFO,
+ Atom_NET_STARTUP_INFO_BEGIN,
+ Atom_NET_STARTUP_ID,
+
+ Atom_NET_SUPPORTING_WM_CHECK,
+
+ Atom_NET_WM_CM_S0,
+
+ Atom_NET_SYSTEM_TRAY_VISUAL,
+
+ Atom_NET_ACTIVE_WINDOW,
// Property formats
- TEXT,
- UTF8_STRING,
- CARDINAL,
+ AtomTEXT,
+ AtomUTF8_STRING,
+ AtomCARDINAL,
// Xdnd
- XdndEnter,
- XdndPosition,
- XdndStatus,
- XdndLeave,
- XdndDrop,
- XdndFinished,
- XdndTypelist,
- XdndActionList,
-
- XdndSelection,
-
- XdndAware,
- XdndProxy,
-
- XdndActionCopy,
- XdndActionLink,
- XdndActionMove,
- XdndActionAsk,
- XdndActionPrivate,
+ AtomXdndEnter,
+ AtomXdndPosition,
+ AtomXdndStatus,
+ AtomXdndLeave,
+ AtomXdndDrop,
+ AtomXdndFinished,
+ AtomXdndTypelist,
+ AtomXdndActionList,
+
+ AtomXdndSelection,
+
+ AtomXdndAware,
+ AtomXdndProxy,
+
+ AtomXdndActionCopy,
+ AtomXdndActionLink,
+ AtomXdndActionMove,
+ AtomXdndActionAsk,
+ AtomXdndActionPrivate,
// Xkb
- _XKB_RULES_NAMES,
+ Atom_XKB_RULES_NAMES,
// XEMBED
- _XEMBED,
- _XEMBED_INFO,
+ Atom_XEMBED,
+ Atom_XEMBED_INFO,
// XInput2
- ButtonLeft,
- ButtonMiddle,
- ButtonRight,
- ButtonWheelUp,
- ButtonWheelDown,
- ButtonHorizWheelLeft,
- ButtonHorizWheelRight,
- AbsMTPositionX,
- AbsMTPositionY,
- AbsMTTouchMajor,
- AbsMTTouchMinor,
- AbsMTOrientation,
- AbsMTPressure,
- AbsMTTrackingID,
- MaxContacts,
- RelX,
- RelY,
+ AtomButtonLeft,
+ AtomButtonMiddle,
+ AtomButtonRight,
+ AtomButtonWheelUp,
+ AtomButtonWheelDown,
+ AtomButtonHorizWheelLeft,
+ AtomButtonHorizWheelRight,
+ AtomAbsMTPositionX,
+ AtomAbsMTPositionY,
+ AtomAbsMTTouchMajor,
+ AtomAbsMTTouchMinor,
+ AtomAbsMTOrientation,
+ AtomAbsMTPressure,
+ AtomAbsMTTrackingID,
+ AtomMaxContacts,
+ AtomRelX,
+ AtomRelY,
// XInput2 tablet
- AbsX,
- AbsY,
- AbsPressure,
- AbsTiltX,
- AbsTiltY,
- AbsWheel,
- AbsDistance,
- WacomSerialIDs,
- INTEGER,
- RelHorizWheel,
- RelVertWheel,
- RelHorizScroll,
- RelVertScroll,
-
- _XSETTINGS_SETTINGS,
-
- _COMPIZ_DECOR_PENDING,
- _COMPIZ_DECOR_REQUEST,
- _COMPIZ_DECOR_DELETE_PIXMAP,
- _COMPIZ_TOOLKIT_ACTION,
- _GTK_LOAD_ICONTHEMES,
-
- AT_SPI_BUS,
-
- EDID,
- EDID_DATA,
- XFree86_DDC_EDID1_RAWDATA,
-
- _ICC_PROFILE,
+ AtomAbsX,
+ AtomAbsY,
+ AtomAbsPressure,
+ AtomAbsTiltX,
+ AtomAbsTiltY,
+ AtomAbsWheel,
+ AtomAbsDistance,
+ AtomWacomSerialIDs,
+ AtomINTEGER,
+ AtomRelHorizWheel,
+ AtomRelVertWheel,
+ AtomRelHorizScroll,
+ AtomRelVertScroll,
+
+ Atom_XSETTINGS_SETTINGS,
+
+ Atom_COMPIZ_DECOR_PENDING,
+ Atom_COMPIZ_DECOR_REQUEST,
+ Atom_COMPIZ_DECOR_DELETE_PIXMAP,
+ Atom_COMPIZ_TOOLKIT_ACTION,
+ Atom_GTK_APPLICATION_ID,
+ Atom_GTK_LOAD_ICONTHEMES,
+
+ AtomAT_SPI_BUS,
+
+ AtomEDID,
+ AtomEDID_DATA,
+ AtomXFree86_DDC_EDID1_RAWDATA,
+
+ Atom_ICC_PROFILE,
NAtoms
};
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index d6cc0bc2af..8353fac6a9 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -173,7 +173,7 @@ void QXcbBackingStoreImage::init(const QSize &size, uint depth, QImage::Format f
m_qimage_format = format;
m_hasAlpha = QImage::toPixelFormat(m_qimage_format).alphaUsage() == QPixelFormat::UsesAlpha;
if (!m_hasAlpha)
- m_qimage_format = qt_maybeAlphaVersionWithSameDepth(m_qimage_format);
+ m_qimage_format = qt_maybeDataCompatibleAlphaVersion(m_qimage_format);
memset(&m_shm_info, 0, sizeof m_shm_info);
@@ -866,6 +866,7 @@ void QXcbBackingStore::render(xcb_window_t window, const QRegion &region, const
}
QPlatformBackingStore::FlushResult QXcbBackingStore::rhiFlush(QWindow *window,
+ qreal sourceDevicePixelRatio,
const QRegion &region,
const QPoint &offset,
QPlatformTextureList *textures,
@@ -876,8 +877,10 @@ QPlatformBackingStore::FlushResult QXcbBackingStore::rhiFlush(QWindow *window,
m_image->flushScrolledRegion(true);
- QPlatformBackingStore::rhiFlush(window, region, offset, textures, translucentBackground);
-
+ auto result = QPlatformBackingStore::rhiFlush(window, sourceDevicePixelRatio, region, offset,
+ textures, translucentBackground);
+ if (result != FlushSuccess)
+ return result;
QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle());
if (platformWindow->needsSync()) {
platformWindow->updateSyncRequestCounter();
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h
index c3ee4a9e31..979b254326 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.h
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.h
@@ -24,6 +24,7 @@ public:
QPaintDevice *paintDevice() override;
void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
FlushResult rhiFlush(QWindow *window,
+ qreal sourceDevicePixelRatio,
const QRegion &region,
const QPoint &offset,
QPlatformTextureList *textures,
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index 6c15d7c142..40e2f47354 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -31,7 +31,7 @@ public:
break;
case QClipboard::Clipboard:
- modeAtom = m_clipboard->atom(QXcbAtom::CLIPBOARD);
+ modeAtom = m_clipboard->atom(QXcbAtom::AtomCLIPBOARD);
break;
default:
@@ -56,12 +56,12 @@ protected:
if (isEmpty())
return QStringList();
- if (!formatList.count()) {
+ if (!formatList.size()) {
QXcbClipboardMime *that = const_cast<QXcbClipboardMime *>(this);
// get the list of targets from the current clipboard owner - we do this
// once so that multiple calls to this function don't require multiple
// server round trips...
- that->format_atoms = m_clipboard->getDataInFormat(modeAtom, m_clipboard->atom(QXcbAtom::TARGETS));
+ that->format_atoms = m_clipboard->getDataInFormat(modeAtom, m_clipboard->atom(QXcbAtom::AtomTARGETS));
if (format_atoms.size() > 0) {
const xcb_atom_t *targets = (const xcb_atom_t *) format_atoms.data();
@@ -126,7 +126,7 @@ QXcbClipboardTransaction::QXcbClipboardTransaction(QXcbClipboard *clipboard, xcb
xcb_change_window_attributes(m_clipboard->xcb_connection(), m_window,
XCB_CW_EVENT_MASK, values);
- m_abortTimerId = startTimer(m_clipboard->clipboardTimeout());
+ m_abortTimerId = startTimer(std::chrono::milliseconds{m_clipboard->clipboardTimeout()});
}
QXcbClipboardTransaction::~QXcbClipboardTransaction()
@@ -145,7 +145,7 @@ bool QXcbClipboardTransaction::updateIncrementalProperty(const xcb_property_noti
// restart the timer
if (m_abortTimerId)
killTimer(m_abortTimerId);
- m_abortTimerId = startTimer(m_clipboard->clipboardTimeout());
+ m_abortTimerId = startTimer(std::chrono::milliseconds{m_clipboard->clipboardTimeout()});
uint bytes_left = uint(m_data.size()) - m_offset;
if (bytes_left > 0) {
@@ -203,7 +203,7 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c)
xcb_xfixes_select_selection_input_checked(xcb_connection(), connection()->qtSelectionOwner(),
XCB_ATOM_PRIMARY, mask);
xcb_xfixes_select_selection_input_checked(xcb_connection(), connection()->qtSelectionOwner(),
- atom(QXcbAtom::CLIPBOARD), mask);
+ atom(QXcbAtom::AtomCLIPBOARD), mask);
}
// xcb_change_property_request_t and xcb_get_property_request_t are the same size
@@ -218,13 +218,13 @@ QXcbClipboard::~QXcbClipboard()
m_timestamp[QClipboard::Selection] != XCB_CURRENT_TIME) {
// First we check if there is a clipboard manager.
- if (connection()->selectionOwner(atom(QXcbAtom::CLIPBOARD_MANAGER)) != XCB_NONE) {
+ if (connection()->selectionOwner(atom(QXcbAtom::AtomCLIPBOARD_MANAGER)) != XCB_NONE) {
// we delete the property so the manager saves all TARGETS.
xcb_delete_property(xcb_connection(), connection()->qtSelectionOwner(),
- atom(QXcbAtom::_QT_SELECTION));
+ atom(QXcbAtom::Atom_QT_SELECTION));
xcb_convert_selection(xcb_connection(), connection()->qtSelectionOwner(),
- atom(QXcbAtom::CLIPBOARD_MANAGER), atom(QXcbAtom::SAVE_TARGETS),
- atom(QXcbAtom::_QT_SELECTION), connection()->time());
+ atom(QXcbAtom::AtomCLIPBOARD_MANAGER), atom(QXcbAtom::AtomSAVE_TARGETS),
+ atom(QXcbAtom::Atom_QT_SELECTION), connection()->time());
connection()->sync();
// waiting until the clipboard manager fetches the content.
@@ -259,7 +259,7 @@ bool QXcbClipboard::handlePropertyNotify(const xcb_generic_event_t *event)
xcb_atom_t QXcbClipboard::atomForMode(QClipboard::Mode mode) const
{
if (mode == QClipboard::Clipboard)
- return atom(QXcbAtom::CLIPBOARD);
+ return atom(QXcbAtom::AtomCLIPBOARD);
if (mode == QClipboard::Selection)
return XCB_ATOM_PRIMARY;
return XCB_NONE;
@@ -269,7 +269,7 @@ QClipboard::Mode QXcbClipboard::modeForAtom(xcb_atom_t a) const
{
if (a == XCB_ATOM_PRIMARY)
return QClipboard::Selection;
- if (a == atom(QXcbAtom::CLIPBOARD))
+ if (a == atom(QXcbAtom::AtomCLIPBOARD))
return QClipboard::Clipboard;
// not supported enum value, used to detect errors
return QClipboard::FindBuffer;
@@ -412,10 +412,10 @@ xcb_atom_t QXcbClipboard::sendTargetsSelection(QMimeData *d, xcb_window_t window
types.append(atoms.at(j));
}
}
- types.append(atom(QXcbAtom::TARGETS));
- types.append(atom(QXcbAtom::MULTIPLE));
- types.append(atom(QXcbAtom::TIMESTAMP));
- types.append(atom(QXcbAtom::SAVE_TARGETS));
+ types.append(atom(QXcbAtom::AtomTARGETS));
+ types.append(atom(QXcbAtom::AtomMULTIPLE));
+ types.append(atom(QXcbAtom::AtomTIMESTAMP));
+ types.append(atom(QXcbAtom::AtomSAVE_TARGETS));
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, window, property, XCB_ATOM_ATOM,
32, types.size(), (const void *)types.constData());
@@ -439,7 +439,7 @@ xcb_atom_t QXcbClipboard::sendSelection(QMimeData *d, xcb_atom_t target, xcb_win
// don't allow INCR transfers when using MULTIPLE or to
// Motif clients (since Motif doesn't support INCR)
- static xcb_atom_t motif_clip_temporary = atom(QXcbAtom::CLIP_TEMPORARY);
+ static xcb_atom_t motif_clip_temporary = atom(QXcbAtom::AtomCLIP_TEMPORARY);
bool allow_incr = property != motif_clip_temporary;
// This 'bool' can be removed once there is a proper fix for QTBUG-32853
if (m_clipboard_closing)
@@ -448,7 +448,7 @@ xcb_atom_t QXcbClipboard::sendSelection(QMimeData *d, xcb_atom_t target, xcb_win
if (data.size() > m_maxPropertyRequestDataBytes && allow_incr) {
long bytes = data.size();
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, window, property,
- atom(QXcbAtom::INCR), 32, 1, (const void *)&bytes);
+ atom(QXcbAtom::AtomINCR), 32, 1, (const void *)&bytes);
auto transaction = new QXcbClipboardTransaction(this, window, property, data, atomFormat, dataFormat);
m_transactions.insert(window, transaction);
return property;
@@ -532,9 +532,9 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req)
return;
}
- xcb_atom_t targetsAtom = atom(QXcbAtom::TARGETS);
- xcb_atom_t multipleAtom = atom(QXcbAtom::MULTIPLE);
- xcb_atom_t timestampAtom = atom(QXcbAtom::TIMESTAMP);
+ xcb_atom_t targetsAtom = atom(QXcbAtom::AtomTARGETS);
+ xcb_atom_t multipleAtom = atom(QXcbAtom::AtomMULTIPLE);
+ xcb_atom_t timestampAtom = atom(QXcbAtom::AtomTIMESTAMP);
struct AtomPair { xcb_atom_t target; xcb_atom_t property; } *multi = nullptr;
xcb_atom_t multi_type = XCB_NONE;
@@ -708,7 +708,7 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
// correct size, not 0-term.
if (size)
*size = buffer_offset;
- if (*type == atom(QXcbAtom::INCR))
+ if (*type == atom(QXcbAtom::AtomINCR))
m_incr_receive_time = connection()->getTimestamp();
if (deleteProperty)
xcb_delete_property(xcb_connection(), win, property);
@@ -747,12 +747,12 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, i
const QXcbEventNode *flushedTailNode = queue->flushedTail();
if (checkManager) {
- if (connection()->selectionOwner(atom(QXcbAtom::CLIPBOARD_MANAGER)) == XCB_NONE)
+ if (connection()->selectionOwner(atom(QXcbAtom::AtomCLIPBOARD_MANAGER)) == XCB_NONE)
return nullptr;
}
// process other clipboard events, since someone is probably requesting data from us
- auto clipboardAtom = atom(QXcbAtom::CLIPBOARD);
+ auto clipboardAtom = atom(QXcbAtom::AtomCLIPBOARD);
e = queue->peek([clipboardAtom](xcb_generic_event_t *event, int type) {
xcb_atom_t selection = XCB_ATOM_NONE;
if (type == XCB_SELECTION_REQUEST)
@@ -846,7 +846,7 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb
QByteArray QXcbClipboard::getDataInFormat(xcb_atom_t modeAtom, xcb_atom_t fmtAtom)
{
- return getSelection(modeAtom, fmtAtom, atom(QXcbAtom::_QT_SELECTION));
+ return getSelection(modeAtom, fmtAtom, atom(QXcbAtom::Atom_QT_SELECTION));
}
QByteArray QXcbClipboard::getSelection(xcb_atom_t selection, xcb_atom_t target, xcb_atom_t property, xcb_timestamp_t time)
@@ -870,7 +870,7 @@ QByteArray QXcbClipboard::getSelection(xcb_atom_t selection, xcb_atom_t target,
xcb_atom_t type;
if (clipboardReadProperty(win, property, true, &buf, nullptr, &type, nullptr)) {
- if (type == atom(QXcbAtom::INCR)) {
+ if (type == atom(QXcbAtom::AtomINCR)) {
int nbytes = buf.size() >= 4 ? *((int*)buf.data()) : 0;
buf = clipboardReadIncrementalProperty(win, property, nbytes, false);
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index cf2a2af457..1056c6408f 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -35,6 +35,10 @@
#undef explicit
#include <xcb/xinput.h>
+#if QT_CONFIG(xcb_xlib)
+#include "qt_xlib_wrapper.h"
+#endif
+
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
@@ -81,16 +85,16 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
m_drag = new QXcbDrag(this);
#endif
- m_startupId = qgetenv("DESKTOP_STARTUP_ID");
- if (!m_startupId.isNull())
+ setStartupId(qgetenv("DESKTOP_STARTUP_ID"));
+ if (!startupId().isNull())
qunsetenv("DESKTOP_STARTUP_ID");
const int focusInDelay = 100;
m_focusInTimer.setSingleShot(true);
m_focusInTimer.setInterval(focusInDelay);
- m_focusInTimer.callOnTimeout([]() {
+ m_focusInTimer.callOnTimeout(this, []() {
// No FocusIn events for us, proceed with FocusOut normally.
- QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason);
+ QWindowSystemInterface::handleFocusWindowChanged(nullptr, Qt::ActiveWindowFocusReason);
});
sync();
@@ -141,12 +145,12 @@ void QXcbConnection::removeWindowEventListener(xcb_window_t id)
QXcbWindowEventListener *QXcbConnection::windowEventListenerFromId(xcb_window_t id)
{
- return m_mapper.value(id, 0);
+ return m_mapper.value(id, nullptr);
}
QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id)
{
- QXcbWindowEventListener *listener = m_mapper.value(id, 0);
+ QXcbWindowEventListener *listener = m_mapper.value(id, nullptr);
if (listener)
return listener->toWindow();
return nullptr;
@@ -449,12 +453,12 @@ void QXcbConnection::printXcbError(const char *message, xcb_generic_error_t *err
uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1);
uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1);
- qCWarning(lcQpaXcb, "%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
- message,
- int(error->error_code), xcb_errors[clamped_error_code],
- int(error->sequence), int(error->resource_id),
- int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
- int(error->minor_code));
+ qCDebug(lcQpaXcb, "%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
+ message,
+ int(error->error_code), xcb_errors[clamped_error_code],
+ int(error->sequence), int(error->resource_id),
+ int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
+ int(error->minor_code));
}
static Qt::MouseButtons translateMouseButtons(int s)
@@ -598,12 +602,12 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
if (clientMessage->format != 32)
return;
#if QT_CONFIG(draganddrop)
- if (clientMessage->type == atom(QXcbAtom::XdndStatus))
+ if (clientMessage->type == atom(QXcbAtom::AtomXdndStatus))
drag()->handleStatus(clientMessage);
- else if (clientMessage->type == atom(QXcbAtom::XdndFinished))
+ else if (clientMessage->type == atom(QXcbAtom::AtomXdndFinished))
drag()->handleFinished(clientMessage);
#endif
- if (m_systemTrayTracker && clientMessage->type == atom(QXcbAtom::MANAGER))
+ if (m_systemTrayTracker && clientMessage->type == atom(QXcbAtom::AtomMANAGER))
m_systemTrayTracker->notifyManagerClientMessageEvent(clientMessage);
HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent);
}
@@ -654,7 +658,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
setTime(selectionRequest->time);
#endif
#if QT_CONFIG(draganddrop)
- if (selectionRequest->selection == atom(QXcbAtom::XdndSelection))
+ if (selectionRequest->selection == atom(QXcbAtom::AtomXdndSelection))
m_drag->handleSelectionRequest(selectionRequest);
else
#endif
@@ -682,11 +686,11 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
if (m_clipboard->handlePropertyNotify(event))
break;
#endif
- if (propertyNotify->atom == atom(QXcbAtom::_NET_WORKAREA)) {
+ if (propertyNotify->atom == atom(QXcbAtom::Atom_NET_WORKAREA)) {
QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(propertyNotify->window);
if (virtualDesktop)
virtualDesktop->updateWorkArea();
- } else if (propertyNotify->atom == atom(QXcbAtom::_NET_SUPPORTED)) {
+ } else if (propertyNotify->atom == atom(QXcbAtom::Atom_NET_SUPPORTED)) {
m_wmSupport->updateNetWMAtoms();
} else {
HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
@@ -713,7 +717,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
#ifndef QT_NO_CLIPBOARD
m_clipboard->handleXFixesSelectionRequest(notify_event);
#endif
- for (QXcbVirtualDesktop *virtualDesktop : qAsConst(m_virtualDesktops))
+ for (QXcbVirtualDesktop *virtualDesktop : std::as_const(m_virtualDesktops))
virtualDesktop->handleXFixesSelectionNotify(notify_event);
} else if (isXRandrType(response_type, XCB_RANDR_NOTIFY)) {
if (!isAtLeastXRandR15())
@@ -771,6 +775,28 @@ void QXcbConnection::setMousePressWindow(QXcbWindow *w)
m_mousePressWindow = w;
}
+QByteArray QXcbConnection::startupId() const
+{
+ return m_startupId;
+}
+void QXcbConnection::setStartupId(const QByteArray &nextId)
+{
+ m_startupId = nextId;
+ if (m_clientLeader) {
+ if (!nextId.isEmpty())
+ xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ clientLeader(),
+ atom(QXcbAtom::Atom_NET_STARTUP_ID),
+ atom(QXcbAtom::AtomUTF8_STRING),
+ 8,
+ nextId.size(),
+ nextId.constData());
+ else
+ xcb_delete_property(xcb_connection(), clientLeader(), atom(QXcbAtom::Atom_NET_STARTUP_ID));
+ }
+}
+
void QXcbConnection::grabServer()
{
if (m_canGrabServer)
@@ -796,8 +822,8 @@ xcb_timestamp_t QXcbConnection::getTimestamp()
{
// send a dummy event to myself to get the timestamp from X server.
xcb_window_t window = rootWindow();
- xcb_atom_t dummyAtom = atom(QXcbAtom::CLIP_TEMPORARY);
- xcb_change_property(xcb_connection(), XCB_PROP_MODE_APPEND, window, dummyAtom,
+ xcb_atom_t dummyAtom = atom(QXcbAtom::Atom_QT_GET_TIMESTAMP);
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, window, dummyAtom,
XCB_ATOM_INTEGER, 32, 0, nullptr);
connection()->flush();
@@ -829,8 +855,6 @@ xcb_timestamp_t QXcbConnection::getTimestamp()
xcb_timestamp_t timestamp = pn->time;
free(event);
- xcb_delete_property(xcb_connection(), window, dummyAtom);
-
return timestamp;
}
@@ -897,7 +921,7 @@ xcb_window_t QXcbConnection::clientLeader()
xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_clientLeader,
- atom(QXcbAtom::WM_CLIENT_LEADER),
+ atom(QXcbAtom::AtomWM_CLIENT_LEADER),
XCB_ATOM_WINDOW,
32,
1,
@@ -910,13 +934,15 @@ xcb_window_t QXcbConnection::clientLeader()
xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_clientLeader,
- atom(QXcbAtom::SM_CLIENT_ID),
+ atom(QXcbAtom::AtomSM_CLIENT_ID),
XCB_ATOM_STRING,
8,
- session.length(),
+ session.size(),
session.constData());
}
#endif
+
+ setStartupId(startupId());
}
return m_clientLeader;
}
@@ -1029,8 +1055,8 @@ bool QXcbConnection::isUserInputEvent(xcb_generic_event_t *event) const
if (eventType == XCB_CLIENT_MESSAGE) {
auto clientMessage = reinterpret_cast<const xcb_client_message_event_t *>(event);
- if (clientMessage->format == 32 && clientMessage->type == atom(QXcbAtom::WM_PROTOCOLS))
- if (clientMessage->data.data32[0] == atom(QXcbAtom::WM_DELETE_WINDOW))
+ if (clientMessage->format == 32 && clientMessage->type == atom(QXcbAtom::AtomWM_PROTOCOLS))
+ if (clientMessage->data.data32[0] == atom(QXcbAtom::AtomWM_DELETE_WINDOW))
isInputEvent = true;
}
@@ -1066,6 +1092,10 @@ void QXcbConnection::processXcbEvents(QEventLoop::ProcessEventsFlags flags)
m_eventQueue->flushBufferedEvents();
}
+#if QT_CONFIG(xcb_xlib)
+ qt_XFlush(static_cast<Display *>(xlib_display()));
+#endif
+
xcb_flush(xcb_connection());
}
@@ -1111,13 +1141,6 @@ Qt::MouseButtons QXcbConnection::queryMouseButtons() const
return translateMouseButtons(stateMask);
}
-Qt::KeyboardModifiers QXcbConnection::queryKeyboardModifiers() const
-{
- int stateMask = 0;
- QXcbCursor::queryPointer(connection(), nullptr, nullptr, &stateMask);
- return keyboard()->translateModifiers(stateMask);
-}
-
QXcbGlIntegration *QXcbConnection::glIntegration() const
{
if (m_glIntegrationInitialized)
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 2d55524f6f..527744fe81 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -170,9 +170,8 @@ public:
QXcbWindow *mousePressWindow() const { return m_mousePressWindow; }
void setMousePressWindow(QXcbWindow *);
- QByteArray startupId() const { return m_startupId; }
- void setStartupId(const QByteArray &nextId) { m_startupId = nextId; }
- void clearStartupId() { m_startupId.clear(); }
+ QByteArray startupId() const;
+ void setStartupId(const QByteArray &nextId);
void grabServer();
void ungrabServer();
@@ -184,7 +183,6 @@ public:
QXcbSystemTrayTracker *systemTrayTracker() const;
Qt::MouseButtons queryMouseButtons() const;
- Qt::KeyboardModifiers queryKeyboardModifiers() const;
bool isUserInputEvent(xcb_generic_event_t *event) const;
@@ -368,7 +366,7 @@ Q_DECLARE_TYPEINFO(QXcbConnection::TabletData, Q_RELOCATABLE_TYPE);
class QXcbConnectionGrabber
{
public:
- QXcbConnectionGrabber(QXcbConnection *connection);
+ Q_NODISCARD_CTOR QXcbConnectionGrabber(QXcbConnection *connection);
~QXcbConnectionGrabber();
void release();
private:
diff --git a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
index 5f1b964afa..6416003bea 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qxcbconnection_basic.h"
#include "qxcbbackingstore.h" // for createSystemVShmSegment()
+#include "private/qoffsetstringarray_p.h"
#include <xcb/randr.h>
#include <xcb/shm.h>
@@ -27,7 +28,7 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaXcb, "qt.qpa.xcb")
#if QT_CONFIG(xcb_xlib)
-static const char * const xcbConnectionErrors[] = {
+static constexpr auto xcbConnectionErrors = qOffsetStringArray(
"No error", /* Error 0 */
"I/O error", /* XCB_CONN_ERROR */
"Unsupported extension used", /* XCB_CONN_CLOSED_EXT_NOTSUPPORTED */
@@ -36,7 +37,7 @@ static const char * const xcbConnectionErrors[] = {
"Failed to parse display string", /* XCB_CONN_CLOSED_PARSE_ERR */
"No such screen on display", /* XCB_CONN_CLOSED_INVALID_SCREEN */
"Error during FD passing" /* XCB_CONN_CLOSED_FDPASSING_FAILED */
-};
+);
static int nullErrorHandler(Display *dpy, XErrorEvent *err)
{
@@ -60,8 +61,7 @@ static int ioErrorHandler(Display *dpy)
/* Print a message with a textual description of the error */
int code = xcb_connection_has_error(conn);
const char *str = "Unknown error";
- int arrayLength = sizeof(xcbConnectionErrors) / sizeof(xcbConnectionErrors[0]);
- if (code >= 0 && code < arrayLength)
+ if (code >= 0 && code < xcbConnectionErrors.count())
str = xcbConnectionErrors[code];
qWarning("The X11 connection broke: %s (code %d)", str, code);
diff --git a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
index aa0f2fef65..c31e9b1039 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
@@ -155,7 +155,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
}
}
- qCDebug(lcQpaScreen) << "updateScreens: primary output is" << qAsConst(m_screens).first()->name();
+ qCDebug(lcQpaScreen) << "updateScreens: primary output is" << std::as_const(m_screens).first()->name();
}
}
@@ -184,7 +184,7 @@ void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_cha
// If the screen became primary, reshuffle the order in QGuiApplicationPrivate
const int idx = m_screens.indexOf(screen);
if (idx > 0) {
- qAsConst(m_screens).first()->setPrimary(false);
+ std::as_const(m_screens).first()->setPrimary(false);
m_screens.swapItemsAt(0, idx);
}
screen->virtualDesktop()->setPrimaryScreen(screen);
@@ -204,7 +204,7 @@ QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop,
if (screen->isPrimary()) {
if (!m_screens.isEmpty())
- qAsConst(m_screens).first()->setPrimary(false);
+ std::as_const(m_screens).first()->setPrimary(false);
m_screens.prepend(screen);
} else {
@@ -219,7 +219,7 @@ QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop,
void QXcbConnection::destroyScreen(QXcbScreen *screen)
{
QXcbVirtualDesktop *virtualDesktop = screen->virtualDesktop();
- if (virtualDesktop->screens().count() == 1) {
+ if (virtualDesktop->screens().size() == 1) {
// If there are no other screens on the same virtual desktop,
// then transform the physical screen into a fake screen.
const QString nameWas = screen->name();
@@ -253,7 +253,7 @@ void QXcbConnection::updateScreen_monitor(QXcbScreen *screen, xcb_randr_monitor_
if (screen->isPrimary()) {
const int idx = m_screens.indexOf(screen);
if (idx > 0) {
- qAsConst(m_screens).first()->setPrimary(false);
+ std::as_const(m_screens).first()->setPrimary(false);
m_screens.swapItemsAt(0, idx);
}
screen->virtualDesktop()->setPrimaryScreen(screen);
@@ -268,7 +268,7 @@ QXcbScreen *QXcbConnection::createScreen_monitor(QXcbVirtualDesktop *virtualDesk
if (screen->isPrimary()) {
if (!m_screens.isEmpty())
- qAsConst(m_screens).first()->setPrimary(false);
+ std::as_const(m_screens).first()->setPrimary(false);
m_screens.prepend(screen);
} else {
@@ -326,7 +326,7 @@ void QXcbConnection::initializeScreens(bool initialized)
++xcbScreenNumber;
}
- for (QXcbVirtualDesktop *virtualDesktop : qAsConst(m_virtualDesktops))
+ for (QXcbVirtualDesktop *virtualDesktop : std::as_const(m_virtualDesktops))
virtualDesktop->subscribeToXFixesSelectionNotify();
if (m_virtualDesktops.isEmpty()) {
@@ -334,7 +334,7 @@ void QXcbConnection::initializeScreens(bool initialized)
} else {
// Ensure the primary screen is first on the list
if (primaryScreen) {
- if (qAsConst(m_screens).first() != primaryScreen) {
+ if (std::as_const(m_screens).first() != primaryScreen) {
m_screens.removeOne(primaryScreen);
m_screens.prepend(primaryScreen);
}
@@ -342,14 +342,14 @@ void QXcbConnection::initializeScreens(bool initialized)
// Push the screens to QGuiApplication
if (!initialized) {
- for (QXcbScreen *screen : qAsConst(m_screens)) {
+ for (QXcbScreen *screen : std::as_const(m_screens)) {
qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
QWindowSystemInterface::handleScreenAdded(screen, screen->isPrimary());
}
}
if (!m_screens.isEmpty())
- qCDebug(lcQpaScreen) << "initializeScreens: primary output is" << qAsConst(m_screens).first()->name();
+ qCDebug(lcQpaScreen) << "initializeScreens: primary output is" << std::as_const(m_screens).first()->name();
}
}
@@ -489,6 +489,10 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int
virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
m_virtualDesktops.append(virtualDesktop);
}
+
+ if (xcbScreenNumber != primaryScreenNumber())
+ return;
+
QList<QPlatformScreen*> old = virtualDesktop->m_screens;
QList<QPlatformScreen *> siblings;
@@ -511,24 +515,22 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int
screen = findScreenForMonitorInfo(old, monitor_info);
if (!screen) {
screen = createScreen_monitor(virtualDesktop, monitor_info, monitors_r->timestamp);
- QHighDpiScaling::updateHighDpiScaling();
} else {
updateScreen_monitor(screen, monitor_info, monitors_r->timestamp);
old.removeAll(screen);
}
}
- m_screens << screen;
+ if (!m_screens.contains(screen))
+ m_screens << screen;
siblings << screen;
// similar logic with QXcbConnection::initializeScreensFromOutput()
- if (primaryScreenNumber() == xcbScreenNumber) {
- if (!(*primaryScreen) || monitor_info->primary) {
- if (*primaryScreen)
- (*primaryScreen)->setPrimary(false);
- *primaryScreen = screen;
- (*primaryScreen)->setPrimary(true);
- siblings.prepend(siblings.takeLast());
- }
+ if (!(*primaryScreen) || monitor_info->primary) {
+ if (*primaryScreen)
+ (*primaryScreen)->setPrimary(false);
+ *primaryScreen = screen;
+ (*primaryScreen)->setPrimary(true);
+ siblings.prepend(siblings.takeLast());
}
xcb_randr_monitor_info_next(&monitor_iter);
@@ -551,10 +553,8 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int
qCDebug(lcQpaScreen) << "create a fake screen: " << screen;
}
- if (primaryScreenNumber() == xcbScreenNumber) {
- *primaryScreen = screen;
- (*primaryScreen)->setPrimary(true);
- }
+ *primaryScreen = screen;
+ (*primaryScreen)->setPrimary(true);
siblings << screen;
m_screens << screen;
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 8cb4e5d603..4f62a1880b 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -15,7 +15,9 @@
#include <xcb/xinput.h>
+#if QT_CONFIG(gestures)
#define QT_XCB_HAS_TOUCHPAD_GESTURES (XCB_INPUT_MINOR_VERSION >= 4)
+#endif
using namespace Qt::StringLiterals;
@@ -226,7 +228,7 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
auto *deviceInfo = reinterpret_cast<xcb_input_xi_device_info_t *>(info);
if (removeExisting) {
#if QT_CONFIG(tabletevent)
- for (int i = 0; i < m_tabletData.count(); ++i) {
+ for (int i = 0; i < m_tabletData.size(); ++i) {
if (m_tabletData.at(i).deviceId == deviceInfo->deviceid) {
m_tabletData.remove(i);
break;
@@ -239,6 +241,7 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
const QByteArray nameRaw = QByteArray(xcb_input_xi_device_info_name(deviceInfo),
xcb_input_xi_device_info_name_length(deviceInfo));
const QString name = QString::fromUtf8(nameRaw);
+ m_xiSlavePointerIds.append(deviceInfo->deviceid);
qCDebug(lcQpaXInputDevices) << "input device " << name << "ID" << deviceInfo->deviceid;
#if QT_CONFIG(tabletevent)
TabletData tabletData;
@@ -270,9 +273,9 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
tabletData.valuatorInfo[valuatorAtom] = info;
}
#endif // QT_CONFIG(tabletevent)
- if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
+ if (valuatorAtom == QXcbAtom::AtomRelHorizScroll || valuatorAtom == QXcbAtom::AtomRelHorizWheel)
scrollingDevice()->lastScrollPosition.setX(fixed3232ToReal(vci->value));
- else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
+ else if (valuatorAtom == QXcbAtom::AtomRelVertScroll || valuatorAtom == QXcbAtom::AtomRelVertWheel)
scrollingDevice()->lastScrollPosition.setY(fixed3232ToReal(vci->value));
break;
}
@@ -300,14 +303,14 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
xcb_atom_t label5 = labels[4];
// Some drivers have no labels on the wheel buttons, some have no label on just one and some have no label on
// button 4 and the wrong one on button 5. So we just check that they are not labelled with unrelated buttons.
- if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp || qatom(label4) == QXcbAtom::ButtonWheelDown) &&
- (!label5 || qatom(label5) == QXcbAtom::ButtonWheelUp || qatom(label5) == QXcbAtom::ButtonWheelDown))
+ if ((!label4 || qatom(label4) == QXcbAtom::AtomButtonWheelUp || qatom(label4) == QXcbAtom::AtomButtonWheelDown) &&
+ (!label5 || qatom(label5) == QXcbAtom::AtomButtonWheelUp || qatom(label5) == QXcbAtom::AtomButtonWheelDown))
scrollingDevice()->legacyOrientations |= Qt::Vertical;
}
if (bci->num_buttons >= 7) {
xcb_atom_t label6 = labels[5];
xcb_atom_t label7 = labels[6];
- if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight))
+ if ((!label6 || qatom(label6) == QXcbAtom::AtomButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::AtomButtonHorizWheelRight))
scrollingDevice()->legacyOrientations |= Qt::Horizontal;
}
buttonCount = bci->num_buttons;
@@ -331,9 +334,9 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
bool isTablet = false;
#if QT_CONFIG(tabletevent)
// If we have found the valuators which we expect a tablet to have, it might be a tablet.
- if (tabletData.valuatorInfo.contains(QXcbAtom::AbsX) &&
- tabletData.valuatorInfo.contains(QXcbAtom::AbsY) &&
- tabletData.valuatorInfo.contains(QXcbAtom::AbsPressure))
+ if (tabletData.valuatorInfo.contains(QXcbAtom::AtomAbsX) &&
+ tabletData.valuatorInfo.contains(QXcbAtom::AtomAbsY) &&
+ tabletData.valuatorInfo.contains(QXcbAtom::AtomAbsPressure))
isTablet = true;
// But we need to be careful not to take the touch and tablet-button devices as tablets.
@@ -356,7 +359,7 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
// combined device (evdev) rather than separate pen/eraser (wacom driver)
tabletData.pointerType = QPointingDevice::PointerType::Pen;
dbgType = "pen"_L1;
- } else if (nameLower.contains("aiptek") /* && device == QXcbAtom::KEYBOARD */) {
+ } else if (nameLower.contains("aiptek") /* && device == QXcbAtom::AtomKEYBOARD */) {
// some "Genius" tablets
isTablet = true;
tabletData.pointerType = QPointingDevice::PointerType::Pen;
@@ -384,9 +387,9 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
m_tabletData.append(tabletData);
qCDebug(lcQpaXInputDevices) << " it's a tablet with pointer type" << dbgType;
QPointingDevice::Capabilities capsOverride = QInputDevice::Capability::None;
- if (tabletData.valuatorInfo.contains(QXcbAtom::AbsTiltX))
+ if (tabletData.valuatorInfo.contains(QXcbAtom::AtomAbsTiltX))
capsOverride.setFlag(QInputDevice::Capability::XTilt);
- if (tabletData.valuatorInfo.contains(QXcbAtom::AbsTiltY))
+ if (tabletData.valuatorInfo.contains(QXcbAtom::AtomAbsTiltY))
capsOverride.setFlag(QInputDevice::Capability::YTilt);
// TODO can we get USB ID?
Q_ASSERT(deviceInfo->deviceid == tabletData.deviceId);
@@ -442,12 +445,15 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting,
}
}
+/*!
+ Find all X11 input devices at startup, or react to a device hierarchy event,
+ and create/delete the corresponding QInputDevice instances as necessary.
+ Afterwards, we expect QInputDevice::devices() to contain only the
+ Qt-relevant devices that \c {xinput list} reports. The parent of each master
+ device is this QXcbConnection object; the parent of each slave is its master.
+*/
void QXcbConnection::xi2SetupDevices()
{
-#if QT_CONFIG(tabletevent)
- m_tabletData.clear();
-#endif
- m_touchDevices.clear();
m_xiMasterPointerIds.clear();
auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, xcb_connection(), XCB_INPUT_DEVICE_ALL);
@@ -456,6 +462,18 @@ void QXcbConnection::xi2SetupDevices()
return;
}
+ // Start with all known devices; remove the ones that still exist.
+ // Afterwards, previousDevices will be the list of those that we should delete.
+ QList<const QInputDevice *> previousDevices = QInputDevice::devices();
+ // Return true if the device with the given systemId is new;
+ // otherwise remove it from previousDevices and return false.
+ auto newOrKeep = [&previousDevices](qint64 systemId) {
+ // if nothing is removed from previousDevices, it's a new device
+ return !previousDevices.removeIf([systemId](const QInputDevice *dev) {
+ return dev->systemId() == systemId;
+ });
+ };
+
// XInput doesn't provide a way to identify "seats"; but each device has an attachment to another device.
// So we make up a seatId: master-keyboard-id << 16 | master-pointer-id.
@@ -464,17 +482,21 @@ void QXcbConnection::xi2SetupDevices()
xcb_input_xi_device_info_t *deviceInfo = it.data;
switch (deviceInfo->type) {
case XCB_INPUT_DEVICE_TYPE_MASTER_KEYBOARD: {
- auto dev = new QInputDevice(QString::fromUtf8(xcb_input_xi_device_info_name(deviceInfo)),
- deviceInfo->deviceid, QInputDevice::DeviceType::Keyboard,
- QString::number(deviceInfo->deviceid << 16 | deviceInfo->attachment, 16), this);
- QWindowSystemInterface::registerInputDevice(dev);
+ if (newOrKeep(deviceInfo->deviceid)) {
+ auto dev = new QInputDevice(QString::fromUtf8(xcb_input_xi_device_info_name(deviceInfo)),
+ deviceInfo->deviceid, QInputDevice::DeviceType::Keyboard,
+ QString::number(deviceInfo->deviceid << 16 | deviceInfo->attachment, 16), this);
+ QWindowSystemInterface::registerInputDevice(dev);
+ }
} break;
case XCB_INPUT_DEVICE_TYPE_MASTER_POINTER: {
m_xiMasterPointerIds.append(deviceInfo->deviceid);
- auto dev = new QXcbScrollingDevice(QString::fromUtf8(xcb_input_xi_device_info_name(deviceInfo)), deviceInfo->deviceid,
- QInputDevice::Capability::Position | QInputDevice::Capability::Scroll | QInputDevice::Capability::Hover,
- 32, QString::number(deviceInfo->attachment << 16 | deviceInfo->deviceid, 16), this);
- QWindowSystemInterface::registerInputDevice(dev);
+ if (newOrKeep(deviceInfo->deviceid)) {
+ auto dev = new QXcbScrollingDevice(QString::fromUtf8(xcb_input_xi_device_info_name(deviceInfo)), deviceInfo->deviceid,
+ QInputDevice::Capability::Position | QInputDevice::Capability::Scroll | QInputDevice::Capability::Hover,
+ 32, QString::number(deviceInfo->attachment << 16 | deviceInfo->deviceid, 16), this);
+ QWindowSystemInterface::registerInputDevice(dev);
+ }
continue;
} break;
default:
@@ -491,23 +513,36 @@ void QXcbConnection::xi2SetupDevices()
// already registered
break;
case XCB_INPUT_DEVICE_TYPE_SLAVE_POINTER: {
- m_xiSlavePointerIds.append(deviceInfo->deviceid);
- QInputDevice *master = const_cast<QInputDevice *>(QInputDevicePrivate::fromId(deviceInfo->attachment));
- Q_ASSERT(master);
- xi2SetupSlavePointerDevice(deviceInfo, false, qobject_cast<QPointingDevice *>(master));
+ if (newOrKeep(deviceInfo->deviceid)) {
+ m_xiSlavePointerIds.append(deviceInfo->deviceid);
+ QInputDevice *master = const_cast<QInputDevice *>(QInputDevicePrivate::fromId(deviceInfo->attachment));
+ Q_ASSERT(master);
+ xi2SetupSlavePointerDevice(deviceInfo, false, qobject_cast<QPointingDevice *>(master));
+ }
} break;
case XCB_INPUT_DEVICE_TYPE_SLAVE_KEYBOARD: {
- QInputDevice *master = const_cast<QInputDevice *>(QInputDevicePrivate::fromId(deviceInfo->attachment));
- Q_ASSERT(master);
- QWindowSystemInterface::registerInputDevice(new QInputDevice(
- QString::fromUtf8(xcb_input_xi_device_info_name(deviceInfo)), deviceInfo->deviceid,
- QInputDevice::DeviceType::Keyboard, master->seatName(), master));
+ if (newOrKeep(deviceInfo->deviceid)) {
+ QInputDevice *master = const_cast<QInputDevice *>(QInputDevicePrivate::fromId(deviceInfo->attachment));
+ Q_ASSERT(master);
+ QWindowSystemInterface::registerInputDevice(new QInputDevice(
+ QString::fromUtf8(xcb_input_xi_device_info_name(deviceInfo)), deviceInfo->deviceid,
+ QInputDevice::DeviceType::Keyboard, master->seatName(), master));
+ }
} break;
case XCB_INPUT_DEVICE_TYPE_FLOATING_SLAVE:
break;
}
}
+ // previousDevices is now the list of those that are no longer found
+ qCDebug(lcQpaXInputDevices) << "removed" << previousDevices;
+ for (auto it = previousDevices.constBegin(); it != previousDevices.constEnd(); ++it) {
+ const auto id = (*it)->systemId();
+ m_xiSlavePointerIds.removeAll(id);
+ m_touchDevices.remove(id);
+ }
+ qDeleteAll(previousDevices);
+
if (m_xiMasterPointerIds.size() > 1)
qCDebug(lcQpaXInputDevices) << "multi-pointer X detected";
}
@@ -573,27 +608,27 @@ QXcbConnection::TouchDeviceData *QXcbConnection::populateTouchDevices(void *info
// Some devices (mice) report a resolution of 0; they will be excluded later,
// for now just prevent a division by zero
const int vciResolution = vci->resolution ? vci->resolution : 1;
- if (valuatorAtom == QXcbAtom::AbsMTPositionX)
+ if (valuatorAtom == QXcbAtom::AtomAbsMTPositionX)
caps |= QInputDevice::Capability::Position | QInputDevice::Capability::NormalizedPosition;
- else if (valuatorAtom == QXcbAtom::AbsMTTouchMajor)
+ else if (valuatorAtom == QXcbAtom::AtomAbsMTTouchMajor)
caps |= QInputDevice::Capability::Area;
- else if (valuatorAtom == QXcbAtom::AbsMTOrientation)
+ else if (valuatorAtom == QXcbAtom::AtomAbsMTOrientation)
dev.providesTouchOrientation = true;
- else if (valuatorAtom == QXcbAtom::AbsMTPressure || valuatorAtom == QXcbAtom::AbsPressure)
+ else if (valuatorAtom == QXcbAtom::AtomAbsMTPressure || valuatorAtom == QXcbAtom::AtomAbsPressure)
caps |= QInputDevice::Capability::Pressure;
- else if (valuatorAtom == QXcbAtom::RelX) {
+ else if (valuatorAtom == QXcbAtom::AtomRelX) {
hasRelativeCoords = true;
dev.size.setWidth((fixed3232ToReal(vci->max) - fixed3232ToReal(vci->min)) * 1000.0 / vciResolution);
- } else if (valuatorAtom == QXcbAtom::RelY) {
+ } else if (valuatorAtom == QXcbAtom::AtomRelY) {
hasRelativeCoords = true;
dev.size.setHeight((fixed3232ToReal(vci->max) - fixed3232ToReal(vci->min)) * 1000.0 / vciResolution);
- } else if (valuatorAtom == QXcbAtom::AbsX) {
+ } else if (valuatorAtom == QXcbAtom::AtomAbsX) {
caps |= QInputDevice::Capability::Position;
dev.size.setWidth((fixed3232ToReal(vci->max) - fixed3232ToReal(vci->min)) * 1000.0 / vciResolution);
- } else if (valuatorAtom == QXcbAtom::AbsY) {
+ } else if (valuatorAtom == QXcbAtom::AtomAbsY) {
caps |= QInputDevice::Capability::Position;
dev.size.setHeight((fixed3232ToReal(vci->max) - fixed3232ToReal(vci->min)) * 1000.0 / vciResolution);
- } else if (valuatorAtom == QXcbAtom::RelVertWheel || valuatorAtom == QXcbAtom::RelHorizWheel) {
+ } else if (valuatorAtom == QXcbAtom::AtomRelVertWheel || valuatorAtom == QXcbAtom::AtomRelHorizWheel) {
caps |= QInputDevice::Capability::Scroll;
}
break;
@@ -651,7 +686,7 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
{
auto *xiEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event);
setTime(xiEvent->time);
- if (m_xiSlavePointerIds.contains(xiEvent->deviceid)) {
+ if (m_xiSlavePointerIds.contains(xiEvent->deviceid) && xiEvent->event_type != XCB_INPUT_PROPERTY) {
if (!m_duringSystemMoveResize)
return;
if (xiEvent->event == XCB_NONE)
@@ -730,6 +765,8 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
if (auto device = QPointingDevicePrivate::pointingDeviceById(sourceDeviceId))
xi2HandleScrollEvent(event, device);
+ else
+ qCDebug(lcQpaXInputEvents) << "scroll event from unregistered device" << sourceDeviceId;
if (xiDeviceEvent) {
switch (xiDeviceEvent->event_type) {
@@ -776,7 +813,16 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
{
auto *xiDeviceEvent = reinterpret_cast<xcb_input_touch_begin_event_t *>(xiDevEvent);
TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid);
- Q_ASSERT(dev);
+ if (!dev) {
+ qCDebug(lcQpaXInputEvents) << "didn't find the dev for given sourceid - " << xiDeviceEvent->sourceid
+ << ", try to repopulate xi2 devices";
+ xi2SetupDevices();
+ dev = touchDeviceForId(xiDeviceEvent->sourceid);
+ if (!dev) {
+ qCDebug(lcQpaXInputEvents) << "still can't find the dev for it, give up.";
+ return;
+ }
+ }
const bool firstTouch = dev->touchPoints.isEmpty();
if (xiDeviceEvent->event_type == XCB_INPUT_TOUCH_BEGIN) {
QWindowSystemInterface::TouchPoint tp;
@@ -792,7 +838,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
qreal nx = -1.0, ny = -1.0;
qreal w = 0.0, h = 0.0;
bool majorAxisIsY = touchPoint.area.height() > touchPoint.area.width();
- for (const TouchDeviceData::ValuatorClassInfo &vci : qAsConst(dev->valuatorInfo)) {
+ for (const TouchDeviceData::ValuatorClassInfo &vci : std::as_const(dev->valuatorInfo)) {
double value;
if (!xi2GetValuatorValueIfSet(xiDeviceEvent, vci.number, &value))
continue;
@@ -804,27 +850,27 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
if (value < vci.min)
value = vci.min;
qreal valuatorNormalized = (value - vci.min) / (vci.max - vci.min);
- if (vci.label == QXcbAtom::RelX) {
+ if (vci.label == QXcbAtom::AtomRelX) {
nx = valuatorNormalized;
- } else if (vci.label == QXcbAtom::RelY) {
+ } else if (vci.label == QXcbAtom::AtomRelY) {
ny = valuatorNormalized;
- } else if (vci.label == QXcbAtom::AbsX) {
+ } else if (vci.label == QXcbAtom::AtomAbsX) {
nx = valuatorNormalized;
- } else if (vci.label == QXcbAtom::AbsY) {
+ } else if (vci.label == QXcbAtom::AtomAbsY) {
ny = valuatorNormalized;
- } else if (vci.label == QXcbAtom::AbsMTPositionX) {
+ } else if (vci.label == QXcbAtom::AtomAbsMTPositionX) {
nx = valuatorNormalized;
- } else if (vci.label == QXcbAtom::AbsMTPositionY) {
+ } else if (vci.label == QXcbAtom::AtomAbsMTPositionY) {
ny = valuatorNormalized;
- } else if (vci.label == QXcbAtom::AbsMTTouchMajor) {
+ } else if (vci.label == QXcbAtom::AtomAbsMTTouchMajor) {
const qreal sw = screen->geometry().width();
const qreal sh = screen->geometry().height();
w = valuatorNormalized * qHypot(sw, sh);
- } else if (vci.label == QXcbAtom::AbsMTTouchMinor) {
+ } else if (vci.label == QXcbAtom::AtomAbsMTTouchMinor) {
const qreal sw = screen->geometry().width();
const qreal sh = screen->geometry().height();
h = valuatorNormalized * qHypot(sw, sh);
- } else if (vci.label == QXcbAtom::AbsMTOrientation) {
+ } else if (vci.label == QXcbAtom::AtomAbsMTOrientation) {
// Find the closest axis.
// 0 corresponds to the Y axis, vci.max to the X axis.
// Flipping over the Y axis and rotating by 180 degrees
@@ -835,7 +881,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
value -= 2 * vci.max;
value = qAbs(value);
majorAxisIsY = value < vci.max - value;
- } else if (vci.label == QXcbAtom::AbsMTPressure || vci.label == QXcbAtom::AbsPressure) {
+ } else if (vci.label == QXcbAtom::AtomAbsMTPressure || vci.label == QXcbAtom::AtomAbsPressure) {
touchPoint.pressure = valuatorNormalized;
}
@@ -967,7 +1013,7 @@ void QXcbConnection::abortSystemMoveResize(xcb_window_t window)
qCDebug(lcQpaXInputDevices) << "sending client message NET_WM_MOVERESIZE_CANCEL to window: " << window;
m_startSystemMoveResizeInfo.window = XCB_NONE;
- const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
+ const xcb_atom_t moveResize = connection()->atom(QXcbAtom::Atom_NET_WM_MOVERESIZE);
xcb_client_message_event_t xev;
xev.response_type = XCB_CLIENT_MESSAGE;
xev.type = moveResize;
@@ -1023,7 +1069,7 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
}
#endif // QT_CONFIG(gestures) && QT_XCB_HAS_TOUCHPAD_GESTURES
- for (int id : qAsConst(m_xiMasterPointerIds)) {
+ for (int id : std::as_const(m_xiMasterPointerIds)) {
xcb_generic_error_t *error = nullptr;
auto cookie = xcb_input_xi_grab_device(xcb_connection(), w, XCB_CURRENT_TIME, XCB_CURSOR_NONE, id,
XCB_INPUT_GRAB_MODE_22_ASYNC, XCB_INPUT_GRAB_MODE_22_ASYNC,
@@ -1041,7 +1087,7 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
free(reply);
}
} else { // ungrab
- for (int id : qAsConst(m_xiMasterPointerIds)) {
+ for (int id : std::as_const(m_xiMasterPointerIds)) {
auto cookie = xcb_input_xi_ungrab_device_checked(xcb_connection(), XCB_CURRENT_TIME, id);
xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie);
if (error) {
@@ -1065,11 +1111,15 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
void QXcbConnection::xi2HandleHierarchyEvent(void *event)
{
auto *xiEvent = reinterpret_cast<xcb_input_hierarchy_event_t *>(event);
- // We only care about hotplugged devices
- if (!(xiEvent->flags & (XCB_INPUT_HIERARCHY_MASK_SLAVE_REMOVED | XCB_INPUT_HIERARCHY_MASK_SLAVE_ADDED)))
- return;
-
- xi2SetupDevices();
+ // We care about hotplugged devices (slaves) and master devices.
+ // We don't report anything for DEVICE_ENABLED or DEVICE_DISABLED
+ // (but often that goes with adding or removal anyway).
+ // We don't react to SLAVE_ATTACHED or SLAVE_DETACHED either.
+ if (xiEvent->flags & (XCB_INPUT_HIERARCHY_MASK_MASTER_ADDED |
+ XCB_INPUT_HIERARCHY_MASK_MASTER_REMOVED |
+ XCB_INPUT_HIERARCHY_MASK_SLAVE_REMOVED |
+ XCB_INPUT_HIERARCHY_MASK_SLAVE_ADDED))
+ xi2SetupDevices();
}
#if QT_XCB_HAS_TOUCHPAD_GESTURES
@@ -1234,6 +1284,9 @@ void QXcbConnection::xi2HandleDeviceChangedEvent(void *event)
auto *xiEvent = reinterpret_cast<xcb_input_device_changed_event_t *>(event);
switch (xiEvent->reason) {
case XCB_INPUT_CHANGE_REASON_DEVICE_CHANGE: {
+ // Don't call xi2SetupSlavePointerDevice() again for an already-known device, and never for a master.
+ if (m_xiMasterPointerIds.contains(xiEvent->deviceid) || m_xiSlavePointerIds.contains(xiEvent->deviceid))
+ return;
auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, xcb_connection(), xiEvent->sourceid);
if (!reply || reply->num_infos <= 0)
return;
@@ -1275,9 +1328,9 @@ void QXcbConnection::xi2UpdateScrollingDevice(QInputDevice *dev)
if (classInfo->type == XCB_INPUT_DEVICE_CLASS_TYPE_VALUATOR) {
auto *vci = reinterpret_cast<xcb_input_valuator_class_t *>(classInfo);
const int valuatorAtom = qatom(vci->label);
- if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
+ if (valuatorAtom == QXcbAtom::AtomRelHorizScroll || valuatorAtom == QXcbAtom::AtomRelHorizWheel)
scrollingDevice->lastScrollPosition.setX(fixed3232ToReal(vci->value));
- else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
+ else if (valuatorAtom == QXcbAtom::AtomRelVertScroll || valuatorAtom == QXcbAtom::AtomRelVertWheel)
scrollingDevice->lastScrollPosition.setY(fixed3232ToReal(vci->value));
}
}
@@ -1464,7 +1517,7 @@ bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletD
// The evdev driver doesn't do it this way.
const auto *ev = reinterpret_cast<const xcb_input_property_event_t *>(event);
if (ev->what == XCB_INPUT_PROPERTY_FLAG_MODIFIED) {
- if (ev->property == atom(QXcbAtom::WacomSerialIDs)) {
+ if (ev->property == atom(QXcbAtom::AtomWacomSerialIDs)) {
enum WacomSerialIndex {
_WACSER_USB_ID = 0,
_WACSER_LAST_TOOL_SERIAL,
@@ -1477,7 +1530,7 @@ bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletD
auto reply = Q_XCB_REPLY(xcb_input_xi_get_property, xcb_connection(), tabletData->deviceId, 0,
ev->property, XCB_GET_PROPERTY_TYPE_ANY, 0, 100);
if (reply) {
- if (reply->type == atom(QXcbAtom::INTEGER) && reply->format == 32 && reply->num_items == _WACSER_COUNT) {
+ if (reply->type == atom(QXcbAtom::AtomINTEGER) && reply->format == 32 && reply->num_items == _WACSER_COUNT) {
quint32 *ptr = reinterpret_cast<quint32 *>(xcb_input_xi_get_property_items(reply.get()));
quint32 tool = ptr[_WACSER_TOOL_ID];
// Workaround for http://sourceforge.net/p/linuxwacom/bugs/246/
@@ -1485,6 +1538,7 @@ bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletD
if (!tool && ptr[_WACSER_TOOL_SERIAL])
tool = ptr[_WACSER_TOOL_SERIAL];
+ QWindow *win = nullptr; // TODO QTBUG-111400 get the position somehow, then the window
// The property change event informs us which tool is in proximity or which one left proximity.
if (tool) {
const QPointingDevice *dev = tabletToolInstance(nullptr, tabletData->name,
@@ -1493,30 +1547,26 @@ bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletD
tabletData->inProximity = true;
tabletData->tool = dev->type();
tabletData->serialId = qint64(ptr[_WACSER_TOOL_SERIAL]);
- QWindowSystemInterface::handleTabletEnterProximityEvent(ev->time,
- int(tabletData->tool), int(tabletData->pointerType), tabletData->serialId);
+ QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(win, ev->time, dev, true); // enter
} else {
tool = ptr[_WACSER_LAST_TOOL_ID];
// Workaround for http://sourceforge.net/p/linuxwacom/bugs/246/
// e.g. on Thinkpad Helix, tool ID will be 0 and serial will be 1
if (!tool)
tool = ptr[_WACSER_LAST_TOOL_SERIAL];
- const QInputDevice *dev = QInputDevicePrivate::fromId(tabletData->deviceId);
+ auto *dev = qobject_cast<const QPointingDevice *>(QInputDevicePrivate::fromId(tabletData->deviceId));
Q_ASSERT(dev);
tabletData->tool = dev->type();
tabletData->inProximity = false;
tabletData->serialId = qint64(ptr[_WACSER_LAST_TOOL_SERIAL]);
- // TODO why doesn't it just take QPointingDevice*
- QWindowSystemInterface::handleTabletLeaveProximityEvent(ev->time,
- int(tabletData->tool), int(tabletData->pointerType), tabletData->serialId);
+ QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(win, ev->time, dev, false); // leave
}
// TODO maybe have a hash of tabletData->deviceId to device data so we can
// look up the tablet name here, and distinguish multiple tablets
- if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
- qCDebug(lcQpaXInputDevices, "XI2 proximity change on tablet %d %s (USB %x): last tool: %x id %x current tool: %x id %x %s",
- tabletData->deviceId, qPrintable(tabletData->name), ptr[_WACSER_USB_ID],
- ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID],
- ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], toolName(tabletData->tool));
+ qCDebug(lcQpaXInputDevices, "XI2 proximity change on tablet %d %s (USB %x): last tool: %x id %x current tool: %x id %x %s",
+ tabletData->deviceId, qPrintable(tabletData->name), ptr[_WACSER_USB_ID],
+ ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID],
+ ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], toolName(tabletData->tool));
}
}
}
@@ -1550,6 +1600,9 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD
double pressure = 0, rotation = 0, tangentialPressure = 0;
int xTilt = 0, yTilt = 0;
static const bool useValuators = !qEnvironmentVariableIsSet("QT_XCB_TABLET_LEGACY_COORDINATES");
+ const QPointingDevice *dev = QPointingDevicePrivate::tabletDevice(QInputDevice::DeviceType(tabletData->tool),
+ QPointingDevice::PointerType(tabletData->pointerType),
+ QPointingDeviceUniqueId::fromNumericId(tabletData->serialId));
// Valuators' values are relative to the physical size of the current virtual
// screen. Therefore we cannot use QScreen/QWindow geometry and should use
@@ -1568,36 +1621,37 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD
xi2GetValuatorValueIfSet(event, classInfo.number, &classInfo.curVal);
double normalizedValue = (classInfo.curVal - classInfo.minVal) / (classInfo.maxVal - classInfo.minVal);
switch (valuator) {
- case QXcbAtom::AbsX:
+ case QXcbAtom::AtomAbsX:
if (Q_LIKELY(useValuators)) {
const qreal value = scaleOneValuator(normalizedValue, physicalScreenArea.x(), physicalScreenArea.width());
global.setX(value);
local.setX(xcbWindow->mapFromGlobalF(global).x());
}
break;
- case QXcbAtom::AbsY:
+ case QXcbAtom::AtomAbsY:
if (Q_LIKELY(useValuators)) {
qreal value = scaleOneValuator(normalizedValue, physicalScreenArea.y(), physicalScreenArea.height());
global.setY(value);
local.setY(xcbWindow->mapFromGlobalF(global).y());
}
break;
- case QXcbAtom::AbsPressure:
+ case QXcbAtom::AtomAbsPressure:
pressure = normalizedValue;
break;
- case QXcbAtom::AbsTiltX:
+ case QXcbAtom::AtomAbsTiltX:
xTilt = classInfo.curVal;
break;
- case QXcbAtom::AbsTiltY:
+ case QXcbAtom::AtomAbsTiltY:
yTilt = classInfo.curVal;
break;
- case QXcbAtom::AbsWheel:
+ case QXcbAtom::AtomAbsWheel:
switch (tabletData->tool) {
case QInputDevice::DeviceType::Airbrush:
tangentialPressure = normalizedValue * 2.0 - 1.0; // Convert 0..1 range to -1..+1 range
break;
case QInputDevice::DeviceType::Stylus:
- rotation = normalizedValue * 360.0 - 180.0; // Convert 0..1 range to -180..+180 degrees
+ if (dev->capabilities().testFlag(QInputDevice::Capability::Rotation))
+ rotation = normalizedValue * 360.0 - 180.0; // Convert 0..1 range to -180..+180 degrees
break;
default: // Other types of styli do not use this valuator
break;
@@ -1616,16 +1670,15 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD
local.x(), local.y(), global.x(), global.y(),
(int)tabletData->buttons, pressure, xTilt, yTilt, rotation, (int)modifiers);
- QWindowSystemInterface::handleTabletEvent(window, ev->time, local, global,
- int(tabletData->tool), int(tabletData->pointerType),
+ QWindowSystemInterface::handleTabletEvent(window, ev->time, dev, local, global,
tabletData->buttons, pressure,
xTilt, yTilt, tangentialPressure,
- rotation, 0, tabletData->serialId, modifiers);
+ rotation, 0, modifiers);
}
QXcbConnection::TabletData *QXcbConnection::tabletDataForDevice(int id)
{
- for (int i = 0; i < m_tabletData.count(); ++i) {
+ for (int i = 0; i < m_tabletData.size(); ++i) {
if (m_tabletData.at(i).deviceId == id)
return &m_tabletData[i];
}
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index abda9c9d0a..dc9ed46956 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// 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
#include "qxcbcursor.h"
@@ -7,13 +7,17 @@
#include "qxcbimage.h"
#include "qxcbxsettings.h"
-#if QT_CONFIG(library)
-#include <QtCore/QLibrary>
-#endif
#include <QtGui/QWindow>
#include <QtGui/QBitmap>
#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformtheme.h>
+
+#if QT_CONFIG(xcb_xlib)
#include <X11/cursorfont.h>
+#else
+#include "qxcbcursorfont.h"
+#endif
+
#include <xcb/xfixes.h>
#include <xcb/xcb_image.h>
@@ -21,24 +25,6 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
-typedef int (*PtrXcursorLibraryLoadCursor)(void *, const char *);
-typedef char *(*PtrXcursorLibraryGetTheme)(void *);
-typedef int (*PtrXcursorLibrarySetTheme)(void *, const char *);
-typedef int (*PtrXcursorLibraryGetDefaultSize)(void *);
-
-#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
-#include <X11/Xlib.h>
-enum {
- XCursorShape = CursorShape
-};
-#undef CursorShape
-
-static PtrXcursorLibraryLoadCursor ptrXcursorLibraryLoadCursor = nullptr;
-static PtrXcursorLibraryGetTheme ptrXcursorLibraryGetTheme = nullptr;
-static PtrXcursorLibrarySetTheme ptrXcursorLibrarySetTheme = nullptr;
-static PtrXcursorLibraryGetDefaultSize ptrXcursorLibraryGetDefaultSize = nullptr;
-#endif
-
static xcb_font_t cursorFont = 0;
static int cursorCount = 0;
@@ -255,10 +241,10 @@ QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c)
if (pixmapCacheKey) {
bitmapCacheKey = pixmapCacheKey;
} else {
- Q_ASSERT(!c.bitmap(Qt::ReturnByValue).isNull());
- Q_ASSERT(!c.mask(Qt::ReturnByValue).isNull());
- bitmapCacheKey = c.bitmap(Qt::ReturnByValue).cacheKey();
- maskCacheKey = c.mask(Qt::ReturnByValue).cacheKey();
+ Q_ASSERT(!c.bitmap().isNull());
+ Q_ASSERT(!c.mask().isNull());
+ bitmapCacheKey = c.bitmap().cacheKey();
+ maskCacheKey = c.mask().cacheKey();
}
}
}
@@ -266,50 +252,28 @@ QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c)
#endif // !QT_NO_CURSOR
QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
- : QXcbObject(conn), m_screen(screen), m_gtkCursorThemeInitialized(false)
+ : QXcbObject(conn), m_screen(screen), m_cursorContext(nullptr), m_callbackForPropertyRegistered(false)
{
#if QT_CONFIG(cursor)
// see NUM_BITMAPS in libXcursor/src/xcursorint.h
m_bitmapCache.setMaxCost(8);
#endif
+ updateContext();
+
if (cursorCount++)
return;
cursorFont = xcb_generate_id(xcb_connection());
const char *cursorStr = "cursor";
xcb_open_font(xcb_connection(), cursorFont, strlen(cursorStr), cursorStr);
-
-#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
- static bool function_ptrs_not_initialized = true;
- if (function_ptrs_not_initialized) {
- QLibrary xcursorLib("Xcursor"_L1, 1);
- bool xcursorFound = xcursorLib.load();
- if (!xcursorFound) { // try without the version number
- xcursorLib.setFileName("Xcursor"_L1);
- xcursorFound = xcursorLib.load();
- }
- if (xcursorFound) {
- ptrXcursorLibraryLoadCursor =
- (PtrXcursorLibraryLoadCursor) xcursorLib.resolve("XcursorLibraryLoadCursor");
- ptrXcursorLibraryGetTheme =
- (PtrXcursorLibraryGetTheme) xcursorLib.resolve("XcursorGetTheme");
- ptrXcursorLibrarySetTheme =
- (PtrXcursorLibrarySetTheme) xcursorLib.resolve("XcursorSetTheme");
- ptrXcursorLibraryGetDefaultSize =
- (PtrXcursorLibraryGetDefaultSize) xcursorLib.resolve("XcursorGetDefaultSize");
- }
- function_ptrs_not_initialized = false;
- }
-
-#endif
}
QXcbCursor::~QXcbCursor()
{
xcb_connection_t *conn = xcb_connection();
- if (m_gtkCursorThemeInitialized) {
+ if (m_callbackForPropertyRegistered) {
m_screen->xSettings()->removeCallbackForHandle(this);
}
@@ -317,9 +281,33 @@ QXcbCursor::~QXcbCursor()
xcb_close_font(conn, cursorFont);
#ifndef QT_NO_CURSOR
- for (xcb_cursor_t cursor : qAsConst(m_cursorHash))
+ for (xcb_cursor_t cursor : std::as_const(m_cursorHash))
xcb_free_cursor(conn, cursor);
#endif
+
+ if (m_cursorContext)
+ xcb_cursor_context_free(m_cursorContext);
+}
+
+QSize QXcbCursor::size() const
+{
+ if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
+ return theme->themeHint(QPlatformTheme::MouseCursorSize).toSize();
+ return QSize(24, 24);
+}
+
+void QXcbCursor::updateContext()
+{
+ if (m_cursorContext)
+ xcb_cursor_context_free(m_cursorContext);
+
+ m_cursorContext = nullptr;
+
+ xcb_connection_t *conn = xcb_connection();
+ if (xcb_cursor_context_new(conn, m_screen->screen(), &m_cursorContext) < 0) {
+ qWarning() << "xcb: Could not initialize xcb-cursor";
+ m_cursorContext = nullptr;
+ }
}
#ifndef QT_NO_CURSOR
@@ -482,76 +470,39 @@ xcb_cursor_t QXcbCursor::createNonStandardCursor(int cshape)
return cursor;
}
-#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
-bool updateCursorTheme(void *dpy, const QByteArray &theme) {
- if (!ptrXcursorLibraryGetTheme
- || !ptrXcursorLibrarySetTheme)
- return false;
- QByteArray oldTheme = ptrXcursorLibraryGetTheme(dpy);
- if (oldTheme == theme)
- return false;
-
- int setTheme = ptrXcursorLibrarySetTheme(dpy,theme.constData());
- return setTheme;
-}
-
- void QXcbCursor::cursorThemePropertyChanged(QXcbVirtualDesktop *screen, const QByteArray &name, const QVariant &property, void *handle)
+void QXcbCursor::cursorThemePropertyChanged(QXcbVirtualDesktop *screen, const QByteArray &name, const QVariant &property, void *handle)
{
Q_UNUSED(screen);
Q_UNUSED(name);
+ Q_UNUSED(property);
QXcbCursor *self = static_cast<QXcbCursor *>(handle);
self->m_cursorHash.clear();
-
- updateCursorTheme(self->connection()->xlib_display(),property.toByteArray());
+ self->updateContext();
}
-static xcb_cursor_t loadCursor(void *dpy, int cshape)
-{
- xcb_cursor_t cursor = XCB_NONE;
- if (!ptrXcursorLibraryLoadCursor || !dpy)
- return cursor;
-
- for (const char *cursorName: cursorNames[cshape]) {
- cursor = ptrXcursorLibraryLoadCursor(dpy, cursorName);
- if (cursor != XCB_NONE)
- break;
- }
-
- return cursor;
-}
-#endif // QT_CONFIG(xcb_xlib) / QT_CONFIG(library)
-
xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
{
+ if (!m_cursorContext)
+ return XCB_NONE;
+
xcb_connection_t *conn = xcb_connection();
int cursorId = cursorIdForShape(cshape);
xcb_cursor_t cursor = XCB_NONE;
-#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
- if (m_screen->xSettings()->initialized())
- m_screen->xSettings()->registerCallbackForProperty("Gtk/CursorThemeName",cursorThemePropertyChanged,this);
+ if (!m_callbackForPropertyRegistered && m_screen->xSettings()->initialized()) {
+ m_screen->xSettings()->registerCallbackForProperty("Gtk/CursorThemeName", cursorThemePropertyChanged, this);
+
+ m_callbackForPropertyRegistered = true;
+ }
- // Try Xcursor first
+ // Try xcb-cursor first
if (cshape >= 0 && cshape <= Qt::LastCursor) {
- void *dpy = connection()->xlib_display();
- cursor = loadCursor(dpy, cshape);
- if (!cursor && !m_gtkCursorThemeInitialized && m_screen->xSettings()->initialized()) {
- QByteArray gtkCursorTheme = m_screen->xSettings()->setting("Gtk/CursorThemeName").toByteArray();
- if (updateCursorTheme(dpy,gtkCursorTheme)) {
- cursor = loadCursor(dpy, cshape);
- }
- m_gtkCursorThemeInitialized = true;
+ for (const char *cursorName : cursorNames[cshape]) {
+ cursor = xcb_cursor_load_cursor(m_cursorContext, cursorName);
+ if (cursor != XCB_NONE)
+ return cursor;
}
}
- if (cursor)
- return cursor;
- if (!cursor && cursorId) {
- cursor = XCreateFontCursor(static_cast<Display *>(connection()->xlib_display()), cursorId);
- if (cursor)
- return cursor;
- }
-
-#endif
// Non-standard X11 cursors are created from bitmaps
cursor = createNonStandardCursor(cshape);
@@ -583,8 +534,8 @@ xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor)
qCWarning(lcQpaXcb, "xrender >= 0.5 required to create pixmap cursors");
} else {
xcb_connection_t *conn = xcb_connection();
- xcb_pixmap_t cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap(Qt::ReturnByValue).toImage());
- xcb_pixmap_t mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask(Qt::ReturnByValue).toImage());
+ xcb_pixmap_t cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap().toImage());
+ xcb_pixmap_t mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask().toImage());
c = xcb_generate_id(conn);
xcb_create_cursor(conn, c, cp, mp, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF,
spot.x(), spot.y());
diff --git a/src/plugins/platforms/xcb/qxcbcursor.h b/src/plugins/platforms/xcb/qxcbcursor.h
index 83438321ef..bf26861e8f 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.h
+++ b/src/plugins/platforms/xcb/qxcbcursor.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// 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
#ifndef QXCBCURSOR_H
@@ -6,6 +6,7 @@
#include <qpa/qplatformcursor.h>
#include "qxcbscreen.h"
+#include <xcb/xcb_cursor.h>
#include <QtCore/QCache>
@@ -47,6 +48,10 @@ public:
QPoint pos() const override;
void setPos(const QPoint &pos) override;
+ QSize size() const override;
+
+ void updateContext();
+
static void queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDesktop, QPoint *pos, int *keybMask = nullptr);
#ifndef QT_NO_CURSOR
@@ -75,17 +80,16 @@ private:
#endif
QXcbScreen *m_screen;
+ xcb_cursor_context_t *m_cursorContext;
#ifndef QT_NO_CURSOR
CursorHash m_cursorHash;
BitmapCursorCache m_bitmapCache;
#endif
-#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
static void cursorThemePropertyChanged(QXcbVirtualDesktop *screen,
const QByteArray &name,
const QVariant &property,
void *handle);
-#endif
- bool m_gtkCursorThemeInitialized;
+ bool m_callbackForPropertyRegistered;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbcursorfont.h b/src/plugins/platforms/xcb/qxcbcursorfont.h
new file mode 100644
index 0000000000..fe74e27691
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbcursorfont.h
@@ -0,0 +1,88 @@
+// 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
+
+// copied from <X11/cursorfont.h>
+
+#ifndef QXCBCURSORFONT_H
+#define QXCBCURSORFONT_H
+
+#define XC_num_glyphs 154
+#define XC_X_cursor 0
+#define XC_arrow 2
+#define XC_based_arrow_down 4
+#define XC_based_arrow_up 6
+#define XC_boat 8
+#define XC_bogosity 10
+#define XC_bottom_left_corner 12
+#define XC_bottom_right_corner 14
+#define XC_bottom_side 16
+#define XC_bottom_tee 18
+#define XC_box_spiral 20
+#define XC_center_ptr 22
+#define XC_circle 24
+#define XC_clock 26
+#define XC_coffee_mug 28
+#define XC_cross 30
+#define XC_cross_reverse 32
+#define XC_crosshair 34
+#define XC_diamond_cross 36
+#define XC_dot 38
+#define XC_dotbox 40
+#define XC_double_arrow 42
+#define XC_draft_large 44
+#define XC_draft_small 46
+#define XC_draped_box 48
+#define XC_exchange 50
+#define XC_fleur 52
+#define XC_gobbler 54
+#define XC_gumby 56
+#define XC_hand1 58
+#define XC_hand2 60
+#define XC_heart 62
+#define XC_icon 64
+#define XC_iron_cross 66
+#define XC_left_ptr 68
+#define XC_left_side 70
+#define XC_left_tee 72
+#define XC_leftbutton 74
+#define XC_ll_angle 76
+#define XC_lr_angle 78
+#define XC_man 80
+#define XC_middlebutton 82
+#define XC_mouse 84
+#define XC_pencil 86
+#define XC_pirate 88
+#define XC_plus 90
+#define XC_question_arrow 92
+#define XC_right_ptr 94
+#define XC_right_side 96
+#define XC_right_tee 98
+#define XC_rightbutton 100
+#define XC_rtl_logo 102
+#define XC_sailboat 104
+#define XC_sb_down_arrow 106
+#define XC_sb_h_double_arrow 108
+#define XC_sb_left_arrow 110
+#define XC_sb_right_arrow 112
+#define XC_sb_up_arrow 114
+#define XC_sb_v_double_arrow 116
+#define XC_shuttle 118
+#define XC_sizing 120
+#define XC_spider 122
+#define XC_spraycan 124
+#define XC_star 126
+#define XC_target 128
+#define XC_tcross 130
+#define XC_top_left_arrow 132
+#define XC_top_left_corner 134
+#define XC_top_right_corner 136
+#define XC_top_side 138
+#define XC_top_tee 140
+#define XC_trek 142
+#define XC_ul_angle 144
+#define XC_umbrella 146
+#define XC_ur_angle 148
+#define XC_watch 150
+#define XC_xterm 152
+
+#endif /* QXCBCURSORFONT_H */
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index f5cb50d9c6..6e5dd770b9 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -5,6 +5,7 @@
#include <xcb/xcb.h>
#include "qxcbconnection.h"
#include "qxcbclipboard.h"
+#include "qxcbkeyboard.h"
#include "qxcbmime.h"
#include "qxcbwindow.h"
#include "qxcbscreen.h"
@@ -27,6 +28,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::Literals::StringLiterals;
+
const int xdnd_version = 5;
static inline xcb_window_t xcb_window(QPlatformWindow *w)
@@ -44,7 +47,7 @@ static xcb_window_t xdndProxy(QXcbConnection *c, xcb_window_t w)
xcb_window_t proxy = XCB_NONE;
auto reply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(),
- false, w, c->atom(QXcbAtom::XdndProxy), XCB_ATOM_WINDOW, 0, 1);
+ false, w, c->atom(QXcbAtom::AtomXdndProxy), XCB_ATOM_WINDOW, 0, 1);
if (reply && reply->type == XCB_ATOM_WINDOW)
proxy = *((xcb_window_t *)xcb_get_property_value(reply.get()));
@@ -54,7 +57,7 @@ static xcb_window_t xdndProxy(QXcbConnection *c, xcb_window_t w)
// exists and is real?
reply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(),
- false, proxy, c->atom(QXcbAtom::XdndProxy), XCB_ATOM_WINDOW, 0, 1);
+ false, proxy, c->atom(QXcbAtom::AtomXdndProxy), XCB_ATOM_WINDOW, 0, 1);
if (reply && reply->type == XCB_ATOM_WINDOW) {
xcb_window_t p = *((xcb_window_t *)xcb_get_property_value(reply.get()));
@@ -140,7 +143,7 @@ void QXcbDrag::startDrag()
qCDebug(lcQpaXDnd) << "starting drag where source:" << connection()->qtSelectionOwner();
xcb_set_selection_owner(xcb_connection(), connection()->qtSelectionOwner(),
- atom(QXcbAtom::XdndSelection), connection()->time());
+ atom(QXcbAtom::AtomXdndSelection), connection()->time());
QStringList fmts = QXcbMime::formatsHelper(drag()->mimeData());
for (int i = 0; i < fmts.size(); ++i) {
@@ -153,7 +156,7 @@ void QXcbDrag::startDrag()
if (drag_types.size() > 3)
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, connection()->qtSelectionOwner(),
- atom(QXcbAtom::XdndTypelist),
+ atom(QXcbAtom::AtomXdndTypelist),
XCB_ATOM_ATOM, 32, drag_types.size(), (const void *)drag_types.constData());
setUseCompositing(current_virtual_desktop->compositingActive());
@@ -187,7 +190,7 @@ Qt::DropAction QXcbDrag::defaultAction(Qt::DropActions possibleActions, Qt::Keyb
void QXcbDrag::handlePropertyNotifyEvent(const xcb_property_notify_event_t *event)
{
- if (event->window != xdnd_dragsource || event->atom != atom(QXcbAtom::XdndActionList))
+ if (event->window != xdnd_dragsource || event->atom != atom(QXcbAtom::AtomXdndActionList))
return;
readActionList();
@@ -233,7 +236,7 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
bool windowContainsMouse = !ignoreNonXdndAwareWindows;
{
auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
- false, w, connection()->atom(QXcbAtom::XdndAware),
+ false, w, connection()->atom(QXcbAtom::AtomXdndAware),
XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
bool isAware = reply && reply->type != XCB_NONE;
if (isAware) {
@@ -306,7 +309,7 @@ bool QXcbDrag::findXdndAwareTarget(const QPoint &globalPos, xcb_window_t *target
xcb_window_t child = translate->child;
auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, target,
- atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
+ atom(QXcbAtom::AtomXdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
bool aware = reply && reply->type != XCB_NONE;
if (aware) {
qCDebug(lcQpaXDnd) << "found XdndAware on" << target;
@@ -379,7 +382,7 @@ void QXcbDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardMod
if (proxy_target) {
auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
false, proxy_target,
- atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1);
+ atom(QXcbAtom::AtomXdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1);
if (!reply || reply->type == XCB_NONE) {
target = 0;
} else {
@@ -404,7 +407,7 @@ void QXcbDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardMod
enter.sequence = 0;
enter.window = target;
enter.format = 32;
- enter.type = atom(QXcbAtom::XdndEnter);
+ enter.type = atom(QXcbAtom::AtomXdndEnter);
enter.data.data32[0] = connection()->qtSelectionOwner();
enter.data.data32[1] = flags;
enter.data.data32[2] = drag_types.size() > 0 ? drag_types.at(0) : 0;
@@ -435,7 +438,7 @@ void QXcbDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardMod
move.sequence = 0;
move.window = target;
move.format = 32;
- move.type = atom(QXcbAtom::XdndPosition);
+ move.type = atom(QXcbAtom::AtomXdndPosition);
move.data.data32[0] = connection()->qtSelectionOwner();
move.data.data32[1] = 0; // flags
move.data.data32[2] = (globalPos.x() << 16) + globalPos.y();
@@ -459,7 +462,7 @@ void QXcbDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardMod
static const bool isUnity = qgetenv("XDG_CURRENT_DESKTOP").toLower() == "unity";
if (isUnity && xdndCollectionWindow == XCB_NONE) {
QString name = QXcbWindow::windowTitle(connection(), target);
- if (name == QStringLiteral("XdndCollectionWindowImp"))
+ if (name == "XdndCollectionWindowImp"_L1)
xdndCollectionWindow = target;
}
if (target == xdndCollectionWindow) {
@@ -481,7 +484,7 @@ void QXcbDrag::drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardMod
drop.sequence = 0;
drop.window = current_target;
drop.format = 32;
- drop.type = atom(QXcbAtom::XdndDrop);
+ drop.type = atom(QXcbAtom::AtomXdndDrop);
drop.data.data32[0] = connection()->qtSelectionOwner();
drop.data.data32[1] = 0; // flags
drop.data.data32[2] = connection()->time();
@@ -521,11 +524,11 @@ void QXcbDrag::drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardMod
Qt::DropAction QXcbDrag::toDropAction(xcb_atom_t a) const
{
- if (a == atom(QXcbAtom::XdndActionCopy) || a == 0)
+ if (a == atom(QXcbAtom::AtomXdndActionCopy) || a == 0)
return Qt::CopyAction;
- if (a == atom(QXcbAtom::XdndActionLink))
+ if (a == atom(QXcbAtom::AtomXdndActionLink))
return Qt::LinkAction;
- if (a == atom(QXcbAtom::XdndActionMove))
+ if (a == atom(QXcbAtom::AtomXdndActionMove))
return Qt::MoveAction;
return Qt::CopyAction;
}
@@ -534,7 +537,7 @@ Qt::DropActions QXcbDrag::toDropActions(const QList<xcb_atom_t> &atoms) const
{
Qt::DropActions actions;
for (const auto actionAtom : atoms) {
- if (actionAtom != atom(QXcbAtom::XdndActionAsk))
+ if (actionAtom != atom(QXcbAtom::AtomXdndActionAsk))
actions |= toDropAction(actionAtom);
}
return actions;
@@ -544,16 +547,16 @@ xcb_atom_t QXcbDrag::toXdndAction(Qt::DropAction a) const
{
switch (a) {
case Qt::CopyAction:
- return atom(QXcbAtom::XdndActionCopy);
+ return atom(QXcbAtom::AtomXdndActionCopy);
case Qt::LinkAction:
- return atom(QXcbAtom::XdndActionLink);
+ return atom(QXcbAtom::AtomXdndActionLink);
case Qt::MoveAction:
case Qt::TargetMoveAction:
- return atom(QXcbAtom::XdndActionMove);
+ return atom(QXcbAtom::AtomXdndActionMove);
case Qt::IgnoreAction:
return XCB_NONE;
default:
- return atom(QXcbAtom::XdndActionCopy);
+ return atom(QXcbAtom::AtomXdndActionCopy);
}
}
@@ -561,7 +564,7 @@ void QXcbDrag::readActionList()
{
drop_actions.clear();
auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, xdnd_dragsource,
- atom(QXcbAtom::XdndActionList), XCB_ATOM_ATOM,
+ atom(QXcbAtom::AtomXdndActionList), XCB_ATOM_ATOM,
0, 1024);
if (reply && reply->type != XCB_NONE && reply->format == 32) {
int length = xcb_get_property_value_length(reply.get()) / 4;
@@ -590,7 +593,7 @@ void QXcbDrag::setActionList(Qt::DropAction requestedAction, Qt::DropActions sup
if (current_actions != actions) {
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, connection()->qtSelectionOwner(),
- atom(QXcbAtom::XdndActionList),
+ atom(QXcbAtom::AtomXdndActionList),
XCB_ATOM_ATOM, 32, actions.size(), actions.constData());
current_actions = actions;
}
@@ -614,7 +617,7 @@ void QXcbDrag::stopListeningForActionListChanges()
int QXcbDrag::findTransactionByWindow(xcb_window_t window)
{
int at = -1;
- for (int i = 0; i < transactions.count(); ++i) {
+ for (int i = 0; i < transactions.size(); ++i) {
const Transaction &t = transactions.at(i);
if (t.target == window || t.proxy_target == window) {
at = i;
@@ -627,7 +630,7 @@ int QXcbDrag::findTransactionByWindow(xcb_window_t window)
int QXcbDrag::findTransactionByTime(xcb_timestamp_t timestamp)
{
int at = -1;
- for (int i = 0; i < transactions.count(); ++i) {
+ for (int i = 0; i < transactions.size(); ++i) {
const Transaction &t = transactions.at(i);
if (t.timestamp == timestamp) {
at = i;
@@ -701,7 +704,7 @@ void QXcbDrag::handleEnter(QPlatformWindow *, const xcb_client_message_event_t *
if (event->data.data32[1] & 1) {
// get the types from XdndTypeList
auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, xdnd_dragsource,
- atom(QXcbAtom::XdndTypelist), XCB_ATOM_ATOM,
+ atom(QXcbAtom::AtomXdndTypelist), XCB_ATOM_ATOM,
0, xdnd_max_type);
if (reply && reply->type != XCB_NONE && reply->format == 32) {
int length = xcb_get_property_value_length(reply.get()) / 4;
@@ -720,7 +723,7 @@ void QXcbDrag::handleEnter(QPlatformWindow *, const xcb_client_message_event_t *
xdnd_types.append(event->data.data32[i]);
}
}
- for(int i = 0; i < xdnd_types.length(); ++i)
+ for(int i = 0; i < xdnd_types.size(); ++i)
qCDebug(lcQpaXDnd) << " " << connection()->atomName(xdnd_types.at(i));
}
@@ -734,7 +737,7 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message
QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff);
Q_ASSERT(w);
QRect geometry = w->geometry();
- p -= geometry.topLeft();
+ p -= w->isEmbedded() ? w->mapToGlobal(geometry.topLeft()) : geometry.topLeft();
if (!w || !w->window() || (w->window()->type() == Qt::Desktop))
return;
@@ -761,12 +764,12 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message
} else {
dropData = m_dropData;
supported_actions = toDropActions(drop_actions);
- if (e->data.data32[4] != atom(QXcbAtom::XdndActionAsk))
+ if (e->data.data32[4] != atom(QXcbAtom::AtomXdndActionAsk))
supported_actions |= Qt::DropActions(toDropAction(e->data.data32[4]));
}
auto buttons = currentDrag() ? b : connection()->queryMouseButtons();
- auto modifiers = currentDrag() ? mods : connection()->queryKeyboardModifiers();
+ auto modifiers = currentDrag() ? mods : connection()->keyboard()->queryKeyboardModifiers();
QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(
w->window(), dropData, p, supported_actions, buttons, modifiers);
@@ -783,7 +786,7 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message
response.sequence = 0;
response.window = xdnd_dragsource;
response.format = 32;
- response.type = atom(QXcbAtom::XdndStatus);
+ response.type = atom(QXcbAtom::AtomXdndStatus);
response.data.data32[0] = xcb_window(w);
response.data.data32[1] = qt_response.isAccepted(); // flags
response.data.data32[2] = 0; // x, y
@@ -835,7 +838,7 @@ namespace
void QXcbDrag::handlePosition(QPlatformWindow * w, const xcb_client_message_event_t *event)
{
xcb_client_message_event_t *lastEvent = const_cast<xcb_client_message_event_t *>(event);
- ClientMessageScanner scanner(atom(QXcbAtom::XdndPosition));
+ ClientMessageScanner scanner(atom(QXcbAtom::AtomXdndPosition));
while (auto nextEvent = connection()->eventQueue()->peek(scanner)) {
if (lastEvent != event)
free(lastEvent);
@@ -883,7 +886,7 @@ void QXcbDrag::handleStatus(const xcb_client_message_event_t *event)
xcb_client_message_event_t *lastEvent = const_cast<xcb_client_message_event_t *>(event);
xcb_generic_event_t *nextEvent;
- ClientMessageScanner scanner(atom(QXcbAtom::XdndStatus));
+ ClientMessageScanner scanner(atom(QXcbAtom::AtomXdndStatus));
while ((nextEvent = connection()->eventQueue()->peek(scanner))) {
if (lastEvent != event)
free(lastEvent);
@@ -934,7 +937,7 @@ void QXcbDrag::send_leave()
leave.sequence = 0;
leave.window = current_target;
leave.format = 32;
- leave.type = atom(QXcbAtom::XdndLeave);
+ leave.type = atom(QXcbAtom::AtomXdndLeave);
leave.data.data32[0] = connection()->qtSelectionOwner();
leave.data.data32[1] = 0; // flags
leave.data.data32[2] = 0; // x, y
@@ -980,40 +983,54 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e
Qt::DropActions supported_drop_actions;
QMimeData *dropData = nullptr;
+ // this could be a same-application drop, just proxied due to
+ // some XEMBEDding, so try to find the real QMimeData used
+ // based on the timestamp for this drop.
+ int at = findTransactionByTime(target_time);
+ if (at != -1) {
+ qCDebug(lcQpaXDnd) << "found one transaction via findTransactionByTime()";
+ dropData = transactions.at(at).drag->mimeData();
+ // Can't use the source QMimeData if we need the image conversion code from xdndObtainData
+ if (dropData && dropData->hasImage())
+ dropData = 0;
+ }
+ // if we can't find it, then use the data in the drag manager
if (currentDrag()) {
- dropData = currentDrag()->mimeData();
+ if (!dropData)
+ dropData = currentDrag()->mimeData();
supported_drop_actions = Qt::DropActions(l[4]);
} else {
- dropData = m_dropData;
+ if (!dropData)
+ dropData = m_dropData;
supported_drop_actions = accepted_drop_action | toDropActions(drop_actions);
}
if (!dropData)
return;
- // ###
- // int at = findXdndDropTransactionByTime(target_time);
- // if (at != -1)
- // dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data;
- // if we can't find it, then use the data in the drag manager
auto buttons = currentDrag() ? b : connection()->queryMouseButtons();
- auto modifiers = currentDrag() ? mods : connection()->queryKeyboardModifiers();
+ auto modifiers = currentDrag() ? mods : connection()->keyboard()->queryKeyboardModifiers();
QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(
currentWindow.data(), dropData, currentPosition, supported_drop_actions,
buttons, modifiers);
- setExecutedDropAction(response.acceptedAction());
+ Qt::DropAction acceptedAaction = response.acceptedAction();
+ if (!response.isAccepted()) {
+ // Ignore a failed drag
+ acceptedAaction = Qt::IgnoreAction;
+ }
+ setExecutedDropAction(acceptedAaction);
xcb_client_message_event_t finished = {};
finished.response_type = XCB_CLIENT_MESSAGE;
finished.sequence = 0;
finished.window = xdnd_dragsource;
finished.format = 32;
- finished.type = atom(QXcbAtom::XdndFinished);
+ finished.type = atom(QXcbAtom::AtomXdndFinished);
finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE;
finished.data.data32[1] = response.isAccepted(); // flags
- finished.data.data32[2] = toXdndAction(response.acceptedAction());
+ finished.data.data32[2] = toXdndAction(acceptedAaction);
qCDebug(lcQpaXDnd) << "sending XdndFinished to source:" << xdnd_dragsource;
@@ -1075,7 +1092,7 @@ void QXcbDrag::timerEvent(QTimerEvent* e)
{
if (e->timerId() == cleanup_timer) {
bool stopTimer = true;
- for (int i = 0; i < transactions.count(); ++i) {
+ for (int i = 0; i < transactions.size(); ++i) {
const Transaction &t = transactions.at(i);
if (t.targetWindow) {
// dnd within the same process, don't delete, these are taken care of
@@ -1083,7 +1100,7 @@ void QXcbDrag::timerEvent(QTimerEvent* e)
continue;
}
QTime currentTime = QTime::currentTime();
- int delta = t.time.msecsTo(currentTime);
+ std::chrono::milliseconds delta{t.time.msecsTo(currentTime)};
if (delta > XdndDropTransactionTimeout) {
/* delete transactions which are older than XdndDropTransactionTimeout. It could mean
one of these:
@@ -1127,7 +1144,7 @@ static xcb_window_t findXdndAwareParent(QXcbConnection *c, xcb_window_t window)
forever {
// check if window has XdndAware
auto gpReply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(), false, window,
- c->atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
+ c->atom(QXcbAtom::AtomXdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
bool aware = gpReply && gpReply->type != XCB_NONE;
if (aware) {
target = window;
@@ -1217,6 +1234,7 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event
bool QXcbDrag::dndEnable(QXcbWindow *w, bool on)
{
+ qCDebug(lcQpaXDnd) << "dndEnable" << static_cast<QPlatformWindow *>(w) << on;
// Windows announce that they support the XDND protocol by creating a window property XdndAware.
if (on) {
QXcbWindow *window = nullptr;
@@ -1233,7 +1251,7 @@ bool QXcbDrag::dndEnable(QXcbWindow *w, bool on)
desktop_proxy = new QWindow;
window = static_cast<QXcbWindow *>(desktop_proxy->handle());
proxy_id = window->xcb_window();
- xcb_atom_t xdnd_proxy = atom(QXcbAtom::XdndProxy);
+ xcb_atom_t xdnd_proxy = atom(QXcbAtom::AtomXdndProxy);
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, w->xcb_window(), xdnd_proxy,
XCB_ATOM_WINDOW, 32, 1, &proxy_id);
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, proxy_id, xdnd_proxy,
@@ -1247,14 +1265,14 @@ bool QXcbDrag::dndEnable(QXcbWindow *w, bool on)
qCDebug(lcQpaXDnd) << "setting XdndAware for" << window->xcb_window();
xcb_atom_t atm = xdnd_version;
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, window->xcb_window(),
- atom(QXcbAtom::XdndAware), XCB_ATOM_ATOM, 32, 1, &atm);
+ atom(QXcbAtom::AtomXdndAware), XCB_ATOM_ATOM, 32, 1, &atm);
return true;
} else {
return false;
}
} else {
if (w->window()->type() == Qt::Desktop) {
- xcb_delete_property(xcb_connection(), w->xcb_window(), atom(QXcbAtom::XdndProxy));
+ xcb_delete_property(xcb_connection(), w->xcb_window(), atom(QXcbAtom::AtomXdndProxy));
delete desktop_proxy;
desktop_proxy = nullptr;
} else {
@@ -1306,10 +1324,10 @@ QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QMetaType reques
return result;
#ifndef QT_NO_CLIPBOARD
- if (c->selectionOwner(c->atom(QXcbAtom::XdndSelection)) == XCB_NONE)
+ if (c->selectionOwner(c->atom(QXcbAtom::AtomXdndSelection)) == XCB_NONE)
return result; // should never happen?
- xcb_atom_t xdnd_selection = c->atom(QXcbAtom::XdndSelection);
+ xcb_atom_t xdnd_selection = c->atom(QXcbAtom::AtomXdndSelection);
result = c->clipboard()->getSelection(xdnd_selection, a, xdnd_selection, drag->targetTime());
#endif
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index a58b7e850e..ae7cc915c8 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -14,7 +14,6 @@
#include <qpoint.h>
#include <qpointer.h>
#include <qrect.h>
-#include <qsharedpointer.h>
#include <qxcbobject.h>
#include <QtCore/QDebug>
@@ -128,7 +127,7 @@ private:
QXcbVirtualDesktop *current_virtual_desktop;
// 10 minute timer used to discard old XdndDrop transactions
- enum { XdndDropTransactionTimeout = 600000 };
+ static constexpr std::chrono::minutes XdndDropTransactionTimeout{10};
int cleanup_timer;
QList<xcb_atom_t> drag_types;
diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.cpp b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
index 5c87cba80d..33795d63cf 100644
--- a/src/plugins/platforms/xcb/qxcbeventqueue.cpp
+++ b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
@@ -345,7 +345,7 @@ void QXcbEventQueue::sendCloseConnectionEvent() const
event.format = 32;
event.sequence = 0;
event.window = window;
- event.type = m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION);
+ event.type = m_connection->atom(QXcbAtom::Atom_QT_CLOSE_CONNECTION);
event.data.data32[0] = 0;
xcb_send_event(c, false, window, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char *>(&event));
@@ -357,7 +357,7 @@ bool QXcbEventQueue::isCloseConnectionEvent(const xcb_generic_event_t *event)
{
if (event && (event->response_type & ~0x80) == XCB_CLIENT_MESSAGE) {
auto clientMessage = reinterpret_cast<const xcb_client_message_event_t *>(event);
- if (clientMessage->type == m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION))
+ if (clientMessage->type == m_connection->atom(QXcbAtom::Atom_QT_CLOSE_CONNECTION))
m_closeConnectionDetected = true;
}
return m_closeConnectionDetected;
diff --git a/src/plugins/platforms/xcb/qxcbimage.h b/src/plugins/platforms/xcb/qxcbimage.h
index e550102881..c022fae639 100644
--- a/src/plugins/platforms/xcb/qxcbimage.h
+++ b/src/plugins/platforms/xcb/qxcbimage.h
@@ -5,7 +5,6 @@
#define QXCBIMAGE_H
#include "qxcbscreen.h"
-#include <QtCore/QPair>
#include <QtGui/QImage>
#include <QtGui/QPixmap>
#include <xcb/xcb_image.h>
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 893b11c8c3..4dafae31e3 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -20,6 +20,7 @@
#ifndef QT_NO_SESSIONMANAGER
#include "qxcbsessionmanager.h"
#endif
+#include "qxcbxsettings.h"
#include <xcb/xcb.h>
@@ -48,9 +49,9 @@
#include <QtGui/QOpenGLContext>
#include <QtGui/QScreen>
#include <QtGui/QOffscreenSurface>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <qpa/qplatformaccessibility.h>
-#ifndef QT_NO_ACCESSIBILITY_ATSPI_BRIDGE
+#if QT_CONFIG(accessibility_atspi_bridge)
#include <QtGui/private/qspiaccessiblebridge_p.h>
#endif
#endif
@@ -92,10 +93,17 @@ static bool runningUnderDebugger()
#endif
}
+class QXcbUnixServices : public QGenericUnixServices
+{
+public:
+ QString portalWindowIdentifier(QWindow *window) override;
+};
+
+
QXcbIntegration *QXcbIntegration::m_instance = nullptr;
QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char **argv)
- : m_services(new QGenericUnixServices)
+ : m_services(new QXcbUnixServices)
, m_instanceName(nullptr)
, m_canGrab(true)
, m_defaultVisualId(UINT_MAX)
@@ -196,7 +204,7 @@ QPlatformPixmap *QXcbIntegration::createPlatformPixmap(QPlatformPixmap::PixelTyp
QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const
{
QXcbGlIntegration *glIntegration = nullptr;
- const bool isTrayIconWindow = QXcbWindow::isTrayIconWindow(window);;
+ const bool isTrayIconWindow = QXcbWindow::isTrayIconWindow(window);
if (window->type() != Qt::Desktop && !isTrayIconWindow) {
if (window->supportsOpenGL()) {
glIntegration = connection()->glIntegration();
@@ -324,19 +332,38 @@ QAbstractEventDispatcher *QXcbIntegration::createEventDispatcher() const
return QXcbEventDispatcher::createEventDispatcher(connection());
}
+using namespace Qt::Literals::StringLiterals;
+static const auto xsNetCursorBlink = "Net/CursorBlink"_ba;
+static const auto xsNetCursorBlinkTime = "Net/CursorBlinkTime"_ba;
+static const auto xsNetDoubleClickTime = "Net/DoubleClickTime"_ba;
+static const auto xsNetDoubleClickDistance = "Net/DoubleClickDistance"_ba;
+static const auto xsNetDndDragThreshold = "Net/DndDragThreshold"_ba;
+
void QXcbIntegration::initialize()
{
const auto defaultInputContext = "compose"_L1;
// Perform everything that may potentially need the event dispatcher (timers, socket
// notifiers) here instead of the constructor.
- QString icStr = QPlatformInputContextFactory::requested();
- if (icStr.isNull())
- icStr = defaultInputContext;
- m_inputContext.reset(QPlatformInputContextFactory::create(icStr));
- if (!m_inputContext && icStr != defaultInputContext && icStr != "none"_L1)
+ auto icStrs = QPlatformInputContextFactory::requested();
+ if (icStrs.isEmpty())
+ icStrs = { defaultInputContext };
+ m_inputContext.reset(QPlatformInputContextFactory::create(icStrs));
+ if (!m_inputContext && !icStrs.contains(defaultInputContext)
+ && icStrs != QStringList{"none"_L1})
m_inputContext.reset(QPlatformInputContextFactory::create(defaultInputContext));
connection()->keyboard()->initialize();
+
+ auto notifyThemeChanged = [](QXcbVirtualDesktop *, const QByteArray &, const QVariant &, void *) {
+ QWindowSystemInterface::handleThemeChange();
+ };
+
+ auto *xsettings = connection()->primaryScreen()->xSettings();
+ xsettings->registerCallbackForProperty(xsNetCursorBlink, notifyThemeChanged, this);
+ xsettings->registerCallbackForProperty(xsNetCursorBlinkTime, notifyThemeChanged, this);
+ xsettings->registerCallbackForProperty(xsNetDoubleClickTime, notifyThemeChanged, this);
+ xsettings->registerCallbackForProperty(xsNetDoubleClickDistance, notifyThemeChanged, this);
+ xsettings->registerCallbackForProperty(xsNetDndDragThreshold, notifyThemeChanged, this);
}
void QXcbIntegration::moveToScreen(QWindow *window, int screen)
@@ -383,7 +410,7 @@ QPlatformInputContext *QXcbIntegration::inputContext() const
return m_inputContext.data();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QPlatformAccessibility *QXcbIntegration::accessibility() const
{
#if !defined(QT_NO_ACCESSIBILITY_ATSPI_BRIDGE)
@@ -403,14 +430,9 @@ QPlatformServices *QXcbIntegration::services() const
return m_services.data();
}
-Qt::KeyboardModifiers QXcbIntegration::queryKeyboardModifiers() const
+QPlatformKeyMapper *QXcbIntegration::keyMapper() const
{
- return m_connection->queryKeyboardModifiers();
-}
-
-QList<int> QXcbIntegration::possibleKeys(const QKeyEvent *e) const
-{
- return m_connection->keyboard()->possibleKeys(e);
+ return m_connection->keyboard();
}
QStringList QXcbIntegration::themeNames() const
@@ -423,31 +445,53 @@ QPlatformTheme *QXcbIntegration::createPlatformTheme(const QString &name) const
return QGenericUnixTheme::createUnixTheme(name);
}
+#define RETURN_VALID_XSETTINGS(key) { \
+ auto value = connection()->primaryScreen()->xSettings()->setting(key); \
+ if (value.isValid()) return value; \
+}
+
QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
{
switch (hint) {
- case QPlatformIntegration::CursorFlashTime:
- case QPlatformIntegration::KeyboardInputInterval:
+ case QPlatformIntegration::CursorFlashTime: {
+ bool ok = false;
+ // If cursor blinking is off, returns 0 to keep the cursor awlays display.
+ if (connection()->primaryScreen()->xSettings()->setting(xsNetCursorBlink).toInt(&ok) == 0 && ok)
+ return 0;
+
+ RETURN_VALID_XSETTINGS(xsNetCursorBlinkTime);
+ break;
+ }
case QPlatformIntegration::MouseDoubleClickInterval:
+ RETURN_VALID_XSETTINGS(xsNetDoubleClickTime);
+ break;
+ case QPlatformIntegration::MouseDoubleClickDistance:
+ RETURN_VALID_XSETTINGS(xsNetDoubleClickDistance);
+ break;
+ case QPlatformIntegration::KeyboardInputInterval:
case QPlatformIntegration::StartDragTime:
case QPlatformIntegration::KeyboardAutoRepeatRate:
case QPlatformIntegration::PasswordMaskDelay:
case QPlatformIntegration::StartDragVelocity:
case QPlatformIntegration::UseRtlExtensions:
case QPlatformIntegration::PasswordMaskCharacter:
+ case QPlatformIntegration::FlickMaximumVelocity:
+ case QPlatformIntegration::FlickDeceleration:
// TODO using various xcb, gnome or KDE settings
break; // Not implemented, use defaults
+ case QPlatformIntegration::FlickStartDistance:
case QPlatformIntegration::StartDragDistance: {
+ RETURN_VALID_XSETTINGS(xsNetDndDragThreshold);
// The default (in QPlatformTheme::defaultThemeHint) is 10 pixels, but
// on a high-resolution screen it makes sense to increase it.
- qreal dpi = 100.0;
+ qreal dpi = 100;
if (const QXcbScreen *screen = connection()->primaryScreen()) {
if (screen->logicalDpi().first > dpi)
dpi = screen->logicalDpi().first;
if (screen->logicalDpi().second > dpi)
dpi = screen->logicalDpi().second;
}
- return 10.0 * dpi / 100.0;
+ return (hint == QPlatformIntegration::FlickStartDistance ? qreal(15) : qreal(10)) * dpi / qreal(100);
}
case QPlatformIntegration::ShowIsFullScreen:
// X11 always has support for windows, but the
@@ -546,4 +590,15 @@ QPlatformVulkanInstance *QXcbIntegration::createPlatformVulkanInstance(QVulkanIn
}
#endif
+void QXcbIntegration::setApplicationBadge(qint64 number)
+{
+ auto unixServices = dynamic_cast<QGenericUnixServices *>(services());
+ unixServices->setApplicationBadge(number);
+}
+
+QString QXcbUnixServices::portalWindowIdentifier(QWindow *window)
+{
+ return "x11:"_L1 + QString::number(window->winId(), 16);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index 4553bbe700..a1e0c3f3e1 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -68,14 +68,13 @@ public:
QPlatformInputContext *inputContext() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QPlatformAccessibility *accessibility() const override;
#endif
QPlatformServices *services() const override;
- Qt::KeyboardModifiers queryKeyboardModifiers() const override;
- QList<int> possibleKeys(const QKeyEvent *e) const override;
+ QPlatformKeyMapper *keyMapper() const override;
QStringList themeNames() const override;
QPlatformTheme *createPlatformTheme(const QString &name) const override;
@@ -102,6 +101,8 @@ public:
static QXcbIntegration *instance() { return m_instance; }
+ void setApplicationBadge(qint64 number) override;
+
private:
QXcbConnection *m_connection = nullptr;
@@ -110,7 +111,7 @@ private:
QScopedPointer<QPlatformInputContext> m_inputContext;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
mutable QScopedPointer<QPlatformAccessibility> m_accessibility;
#endif
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 79fef496b4..17da54bc7a 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -3,6 +3,7 @@
#include "qxcbkeyboard.h"
#include "qxcbwindow.h"
#include "qxcbscreen.h"
+#include "qxcbcursor.h"
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatforminputcontext.h>
@@ -377,9 +378,18 @@ void QXcbKeyboard::updateKeymap()
QXkbCommon::verifyHasLatinLayout(m_xkbKeymap.get());
}
-QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
+QList<QKeyCombination> QXcbKeyboard::possibleKeyCombinations(const QKeyEvent *event) const
{
- return QXkbCommon::possibleKeys(m_xkbState.get(), event, m_superAsMeta, m_hyperAsMeta);
+ return QXkbCommon::possibleKeyCombinations(
+ m_xkbState.get(), event, m_superAsMeta, m_hyperAsMeta);
+}
+
+Qt::KeyboardModifiers QXcbKeyboard::queryKeyboardModifiers() const
+{
+ // FIXME: Should we base this on m_xkbState?
+ int stateMask = 0;
+ QXcbCursor::queryPointer(connection(), nullptr, nullptr, &stateMask);
+ return translateModifiers(stateMask);
}
void QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state)
@@ -405,7 +415,7 @@ static xkb_layout_index_t lockedGroup(quint16 state)
void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
{
- if (m_config && !connection()->hasXKB()) {
+ if (m_config) {
struct xkb_state *xkbState = m_xkbState.get();
xkb_mod_mask_t modsDepressed = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_DEPRESSED);
xkb_mod_mask_t modsLatched = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_LATCHED);
@@ -427,7 +437,7 @@ void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo)
{
- if (m_config && !connection()->hasXKB()) {
+ if (m_config) {
auto *mods = static_cast<xcb_input_modifier_info_t *>(modInfo);
auto *group = static_cast<xcb_input_group_info_t *>(groupInfo);
const xkb_state_component changedComponents
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index 15b08fbead..62d9268c64 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -14,11 +14,13 @@
#include <QtGui/private/qxkbcommon_p.h>
#include <xkbcommon/xkbcommon-x11.h>
+#include <qpa/qplatformkeymapper.h>
+
#include <QEvent>
QT_BEGIN_NAMESPACE
-class QXcbKeyboard : public QXcbObject
+class QXcbKeyboard : public QXcbObject, public QPlatformKeyMapper
{
public:
QXcbKeyboard(QXcbConnection *connection);
@@ -34,7 +36,9 @@ public:
Qt::KeyboardModifiers translateModifiers(int s) const;
void updateKeymap(xcb_mapping_notify_event_t *event);
void updateKeymap();
- QList<int> possibleKeys(const QKeyEvent *event) const;
+
+ QList<QKeyCombination> possibleKeyCombinations(const QKeyEvent *event) const override;
+ Qt::KeyboardModifiers queryKeyboardModifiers() const override;
void updateXKBMods();
xkb_mod_mask_t xkbModMask(quint16 state);
diff --git a/src/plugins/platforms/xcb/qxcbmime.cpp b/src/plugins/platforms/xcb/qxcbmime.cpp
index 7161af279c..860d195d13 100644
--- a/src/plugins/platforms/xcb/qxcbmime.cpp
+++ b/src/plugins/platforms/xcb/qxcbmime.cpp
@@ -27,8 +27,8 @@ QString QXcbMime::mimeAtomToString(QXcbConnection *connection, xcb_atom_t a)
// special cases for string type
if (a == XCB_ATOM_STRING
- || a == connection->atom(QXcbAtom::UTF8_STRING)
- || a == connection->atom(QXcbAtom::TEXT))
+ || a == connection->atom(QXcbAtom::AtomUTF8_STRING)
+ || a == connection->atom(QXcbAtom::AtomTEXT))
return "text/plain"_L1;
// special case for images
@@ -54,15 +54,15 @@ bool QXcbMime::mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeDa
*atomFormat = a;
*dataFormat = 8;
- if ((a == connection->atom(QXcbAtom::UTF8_STRING)
+ if ((a == connection->atom(QXcbAtom::AtomUTF8_STRING)
|| a == XCB_ATOM_STRING
- || a == connection->atom(QXcbAtom::TEXT))
+ || a == connection->atom(QXcbAtom::AtomTEXT))
&& QInternalMimeData::hasFormatHelper("text/plain"_L1, mimeData)) {
- if (a == connection->atom(QXcbAtom::UTF8_STRING)) {
+ if (a == connection->atom(QXcbAtom::AtomUTF8_STRING)) {
*data = QInternalMimeData::renderDataHelper("text/plain"_L1, mimeData);
ret = true;
} else if (a == XCB_ATOM_STRING ||
- a == connection->atom(QXcbAtom::TEXT)) {
+ a == connection->atom(QXcbAtom::AtomTEXT)) {
// ICCCM says STRING is latin1
*data = QString::fromUtf8(QInternalMimeData::renderDataHelper(
"text/plain"_L1, mimeData)).toLatin1();
@@ -79,8 +79,7 @@ bool QXcbMime::mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeDa
if (atomName == "text/uri-list"_L1
&& connection->atomName(a) == "text/x-moz-url") {
const QString mozUri = QLatin1StringView(data->split('\n').constFirst()) + u'\n';
- *data = QByteArray(reinterpret_cast<const char *>(mozUri.data()),
- mozUri.length() * 2);
+ data->assign({reinterpret_cast<const char *>(mozUri.data()), mozUri.size() * 2});
} else if (atomName == "application/x-color"_L1)
*dataFormat = 16;
ret = true;
@@ -102,9 +101,9 @@ QList<xcb_atom_t> QXcbMime::mimeAtomsForFormat(QXcbConnection *connection, const
// special cases for strings
if (format == "text/plain"_L1) {
- atoms.append(connection->atom(QXcbAtom::UTF8_STRING));
+ atoms.append(connection->atom(QXcbAtom::AtomUTF8_STRING));
atoms.append(XCB_ATOM_STRING);
- atoms.append(connection->atom(QXcbAtom::TEXT));
+ atoms.append(connection->atom(QXcbAtom::AtomTEXT));
}
// special cases for uris
@@ -139,11 +138,11 @@ QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a,
if (format == "text/plain"_L1) {
if (data.endsWith('\0'))
data.chop(1);
- if (a == connection->atom(QXcbAtom::UTF8_STRING)) {
+ if (a == connection->atom(QXcbAtom::AtomUTF8_STRING)) {
return QString::fromUtf8(data);
}
if (a == XCB_ATOM_STRING ||
- a == connection->atom(QXcbAtom::TEXT))
+ a == connection->atom(QXcbAtom::AtomTEXT))
return QString::fromLatin1(data);
}
// If data contains UTF16 text, convert it to a string.
@@ -156,7 +155,7 @@ QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a,
const quint8 byte1 = data.at(1);
if ((byte0 == 0xff && byte1 == 0xfe) || (byte0 == 0xfe && byte1 == 0xff)
|| (byte0 != 0 && byte1 == 0) || (byte0 == 0 && byte1 != 0)) {
- const QString str = QString::fromUtf16(
+ const QStringView str(
reinterpret_cast<const char16_t *>(data.constData()), data.size() / 2);
if (!str.isNull()) {
if (format == "text/uri-list"_L1) {
@@ -175,7 +174,7 @@ QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a,
return list.constFirst();
return list;
} else {
- return str;
+ return str.toString();
}
}
}
@@ -227,12 +226,12 @@ xcb_atom_t QXcbMime::mimeAtomForFormat(QXcbConnection *connection, const QString
// find matches for string types
if (format == "text/plain"_L1) {
- if (atoms.contains(connection->atom(QXcbAtom::UTF8_STRING)))
- return connection->atom(QXcbAtom::UTF8_STRING);
+ if (atoms.contains(connection->atom(QXcbAtom::AtomUTF8_STRING)))
+ return connection->atom(QXcbAtom::AtomUTF8_STRING);
if (atoms.contains(XCB_ATOM_STRING))
return XCB_ATOM_STRING;
- if (atoms.contains(connection->atom(QXcbAtom::TEXT)))
- return connection->atom(QXcbAtom::TEXT);
+ if (atoms.contains(connection->atom(QXcbAtom::AtomTEXT)))
+ return connection->atom(QXcbAtom::AtomTEXT);
}
// find matches for uri types
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index cd6ff40df9..06f5241d8c 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -350,7 +350,7 @@ void *QXcbNativeInterface::atspiBus()
QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
QXcbConnection *connection = integration->connection();
if (connection) {
- auto atspiBusAtom = connection->atom(QXcbAtom::AT_SPI_BUS);
+ auto atspiBusAtom = connection->atom(QXcbAtom::AtomAT_SPI_BUS);
auto reply = Q_XCB_REPLY(xcb_get_property, connection->xcb_connection(),
false, connection->rootWindow(),
atspiBusAtom, XCB_ATOM_STRING, 0, 128);
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index bb33f393ec..06f4b66edb 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -50,7 +50,7 @@ QXcbVirtualDesktop::QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t
auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
false, screen->root,
- atom(QXcbAtom::_NET_SUPPORTING_WM_CHECK),
+ atom(QXcbAtom::Atom_NET_SUPPORTING_WM_CHECK),
XCB_ATOM_WINDOW, 0, 1024);
if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) {
xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply.get()));
@@ -92,7 +92,7 @@ QXcbVirtualDesktop::~QXcbVirtualDesktop()
{
delete m_xSettings;
- for (auto cmap : qAsConst(m_visualColormaps))
+ for (auto cmap : std::as_const(m_visualColormaps))
xcb_free_colormap(xcb_connection(), cmap);
}
@@ -222,7 +222,7 @@ void QXcbVirtualDesktop::handleScreenChange(xcb_randr_screen_change_notify_event
case XCB_RANDR_ROTATION_REFLECT_Y: break;
}
- for (QPlatformScreen *platformScreen : qAsConst(m_screens)) {
+ for (QPlatformScreen *platformScreen : std::as_const(m_screens)) {
QDpi ldpi = platformScreen->logicalDpi();
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(platformScreen->screen(), ldpi.first, ldpi.second);
}
@@ -249,7 +249,7 @@ QRect QXcbVirtualDesktop::getWorkArea() const
{
QRect r;
auto workArea = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), false, screen()->root,
- atom(QXcbAtom::_NET_WORKAREA),
+ atom(QXcbAtom::Atom_NET_WORKAREA),
XCB_ATOM_CARDINAL, 0, 1024);
if (workArea && workArea->type == XCB_ATOM_CARDINAL && workArea->format == 32 && workArea->value_len >= 4) {
// If workArea->value_len > 4, the remaining ones seem to be for WM's virtual desktops
@@ -271,7 +271,7 @@ void QXcbVirtualDesktop::updateWorkArea()
QRect workArea = getWorkArea();
if (m_workArea != workArea) {
m_workArea = workArea;
- for (QPlatformScreen *screen : qAsConst(m_screens))
+ for (QPlatformScreen *screen : std::as_const(m_screens))
((QXcbScreen *)screen)->updateAvailableGeometry();
}
}
@@ -499,6 +499,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
, m_crtc(output ? output->crtc : XCB_NONE)
, m_outputName(getOutputName(output))
, m_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize())
+ , m_cursor(std::make_unique<QXcbCursor>(connection, this))
{
if (connection->isAtLeastXRandR12()) {
xcb_randr_select_input(xcb_connection(), screen()->root, true);
@@ -519,8 +520,6 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
if (m_sizeMillimeters.isEmpty())
m_sizeMillimeters = virtualDesktop->physicalSize();
- m_cursor = new QXcbCursor(connection, this);
-
updateColorSpaceAndEdid();
}
@@ -530,7 +529,7 @@ void QXcbScreen::updateColorSpaceAndEdid()
// Read colord ICC data (from GNOME settings)
auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
false, screen()->root,
- connection()->atom(QXcbAtom::_ICC_PROFILE),
+ connection()->atom(QXcbAtom::Atom_ICC_PROFILE),
XCB_ATOM_CARDINAL, 0, 8192);
if (reply->format == 8 && reply->type == XCB_ATOM_CARDINAL) {
QByteArray data(reinterpret_cast<const char *>(xcb_get_property_value(reply.get())), reply->value_len);
@@ -557,11 +556,11 @@ void QXcbScreen::updateColorSpaceAndEdid()
m_edid.greenChromaticity, m_edid.blueChromaticity,
QColorSpace::TransferFunction::Gamma, m_edid.gamma);
} else {
- if (m_edid.tables.length() == 1) {
+ if (m_edid.tables.size() == 1) {
m_colorSpace = QColorSpace(m_edid.whiteChromaticity, m_edid.redChromaticity,
m_edid.greenChromaticity, m_edid.blueChromaticity,
m_edid.tables[0]);
- } else if (m_edid.tables.length() == 3) {
+ } else if (m_edid.tables.size() == 3) {
m_colorSpace = QColorSpace(m_edid.whiteChromaticity, m_edid.redChromaticity,
m_edid.greenChromaticity, m_edid.blueChromaticity,
m_edid.tables[0], m_edid.tables[1], m_edid.tables[2]);
@@ -585,6 +584,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
: QXcbObject(connection)
, m_virtualDesktop(virtualDesktop)
, m_monitor(monitorInfo)
+ , m_cursor(std::make_unique<QXcbCursor>(connection, this))
{
setMonitor(monitorInfo, timestamp);
}
@@ -598,6 +598,7 @@ void QXcbScreen::setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp
m_crtcs.clear();
m_output = XCB_NONE;
m_crtc = XCB_NONE;
+ m_singlescreen = false;
if (!monitorInfo) {
m_monitor = nullptr;
@@ -678,12 +679,11 @@ void QXcbScreen::setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp
m_sizeMillimeters = virtualDesktop()->physicalSize();
m_outputName = getName(monitorInfo);
- if (connection()->primaryScreenNumber() == virtualDesktop()->number() && monitorInfo->primary)
- m_primary = true;
- else
- m_primary = false;
-
- m_cursor = new QXcbCursor(connection(), this);
+ m_primary = false;
+ if (connection()->primaryScreenNumber() == virtualDesktop()->number()) {
+ if (monitorInfo->primary || isPrimaryInXScreen())
+ m_primary = true;
+ }
updateColorSpaceAndEdid();
}
@@ -700,9 +700,19 @@ QString QXcbScreen::defaultName()
return name;
}
+bool QXcbScreen::isPrimaryInXScreen()
+{
+ auto primary = Q_XCB_REPLY(xcb_randr_get_output_primary, connection()->xcb_connection(), root());
+ if (!primary)
+ qWarning("failed to get the primary output of the screen");
+
+ const bool isPrimary = primary ? (m_monitor ? m_outputs.contains(primary->output) : m_output == primary->output) : false;
+
+ return isPrimary;
+}
+
QXcbScreen::~QXcbScreen()
{
- delete m_cursor;
}
QString QXcbScreen::getOutputName(xcb_randr_get_output_info_reply_t *outputInfo)
@@ -786,7 +796,7 @@ void QXcbScreen::windowShown(QXcbWindow *window)
// Freedesktop.org Startup Notification
if (!connection()->startupId().isEmpty() && window->window()->isTopLevel()) {
sendStartupMessage(QByteArrayLiteral("remove: ID=") + connection()->startupId());
- connection()->clearStartupId();
+ connection()->setStartupId({});
}
}
@@ -807,15 +817,15 @@ void QXcbScreen::sendStartupMessage(const QByteArray &message) const
xcb_client_message_event_t ev;
ev.response_type = XCB_CLIENT_MESSAGE;
ev.format = 8;
- ev.type = connection()->atom(QXcbAtom::_NET_STARTUP_INFO_BEGIN);
+ ev.type = connection()->atom(QXcbAtom::Atom_NET_STARTUP_INFO_BEGIN);
ev.sequence = 0;
ev.window = rootWindow;
int sent = 0;
- int length = message.length() + 1; // include NUL byte
+ int length = message.size() + 1; // include NUL byte
const char *data = message.constData();
do {
if (sent == 20)
- ev.type = connection()->atom(QXcbAtom::_NET_STARTUP_INFO);
+ ev.type = connection()->atom(QXcbAtom::Atom_NET_STARTUP_INFO);
const int start = sent;
const int numBytes = qMin(length - start, 20);
@@ -829,7 +839,7 @@ void QXcbScreen::sendStartupMessage(const QByteArray &message) const
QRect QXcbScreen::availableGeometry() const
{
static bool enforceNetWorkarea = !qEnvironmentVariableIsEmpty("QT_RELY_ON_NET_WORKAREA_ATOM");
- bool isMultiHeadSystem = virtualSiblings().length() > 1;
+ bool isMultiHeadSystem = virtualSiblings().size() > 1;
bool useScreenGeometry = isMultiHeadSystem && !enforceNetWorkarea;
return useScreenGeometry ? m_geometry : m_availableGeometry;
}
@@ -869,7 +879,7 @@ QDpi QXcbScreen::logicalDpi() const
QPlatformCursor *QXcbScreen::cursor() const
{
- return m_cursor;
+ return m_cursor.get();
}
void QXcbScreen::setOutput(xcb_randr_output_t outputId,
@@ -1085,11 +1095,11 @@ QByteArray QXcbScreen::getEdid() const
return result;
// Try a bunch of atoms
- result = getOutputProperty(atom(QXcbAtom::EDID));
+ result = getOutputProperty(atom(QXcbAtom::AtomEDID));
if (result.isEmpty())
- result = getOutputProperty(atom(QXcbAtom::EDID_DATA));
+ result = getOutputProperty(atom(QXcbAtom::AtomEDID_DATA));
if (result.isEmpty())
- result = getOutputProperty(atom(QXcbAtom::XFree86_DDC_EDID1_RAWDATA));
+ result = getOutputProperty(atom(QXcbAtom::AtomXFree86_DDC_EDID1_RAWDATA));
return result;
}
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 12c13ef80e..49165d3ba4 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -18,6 +18,8 @@
#include <QtGui/private/qedidparser_p.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QXcbConnection;
@@ -161,6 +163,7 @@ public:
void setCrtc(xcb_randr_crtc_t crtc) { m_crtc = crtc; }
void setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp_t timestamp = XCB_NONE);
QString defaultName();
+ bool isPrimaryInXScreen();
void windowShown(QXcbWindow *window);
QString windowManagerName() const { return m_virtualDesktop->windowManagerName(); }
@@ -212,7 +215,7 @@ private:
QRect m_availableGeometry;
QColorSpace m_colorSpace;
Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
- QXcbCursor *m_cursor;
+ std::unique_ptr<QXcbCursor> m_cursor;
qreal m_refreshRate = 60.0;
QEdidParser m_edid;
diff --git a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp
index ec305d5030..b4e28ab831 100644
--- a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp
+++ b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp
@@ -101,19 +101,19 @@ static void sm_setProperty(const QString &name, const QString &value)
{
QByteArray v = value.toUtf8();
SmPropValue prop;
- prop.length = v.length();
+ prop.length = v.size();
prop.value = (SmPointer) const_cast<char *>(v.constData());
sm_setProperty(name.toLatin1().data(), SmARRAY8, 1, &prop);
}
static void sm_setProperty(const QString &name, const QStringList &value)
{
- SmPropValue *prop = new SmPropValue[value.count()];
+ SmPropValue *prop = new SmPropValue[value.size()];
int count = 0;
QList<QByteArray> vl;
vl.reserve(value.size());
for (QStringList::ConstIterator it = value.begin(); it != value.end(); ++it) {
- prop[count].length = (*it).length();
+ prop[count].length = (*it).size();
vl.append((*it).toUtf8());
prop[count].value = (char*)vl.constLast().data();
++count;
diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
index e184c07128..84d2d73f91 100644
--- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
+++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
@@ -26,7 +26,7 @@ enum {
QXcbSystemTrayTracker *QXcbSystemTrayTracker::create(QXcbConnection *connection)
{
// Selection, tray atoms for GNOME, NET WM Specification
- const xcb_atom_t trayAtom = connection->atom(QXcbAtom::_NET_SYSTEM_TRAY_OPCODE);
+ const xcb_atom_t trayAtom = connection->atom(QXcbAtom::Atom_NET_SYSTEM_TRAY_OPCODE);
if (!trayAtom)
return nullptr;
const QByteArray netSysTray = QByteArrayLiteral("_NET_SYSTEM_TRAY_S") + QByteArray::number(connection->primaryScreenNumber());
@@ -113,7 +113,7 @@ xcb_visualid_t QXcbSystemTrayTracker::netSystemTrayVisual()
if (m_trayWindow == XCB_WINDOW_NONE)
return XCB_NONE;
- xcb_atom_t tray_atom = m_connection->atom(QXcbAtom::_NET_SYSTEM_TRAY_VISUAL);
+ xcb_atom_t tray_atom = m_connection->atom(QXcbAtom::Atom_NET_SYSTEM_TRAY_VISUAL);
// Get the xcb property for the _NET_SYSTEM_TRAY_VISUAL atom
auto systray_atom_reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, m_connection->xcb_connection(),
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 0162d058a6..d3e4fa9548 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -6,6 +6,7 @@
#include <QtDebug>
#include <QMetaEnum>
#include <QScreen>
+#include <QtCore/QFileInfo>
#include <QtGui/QIcon>
#include <QtGui/QRegion>
#include <QtGui/private/qhighdpiscaling_p.h>
@@ -59,6 +60,7 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window");
+Q_LOGGING_CATEGORY(lcQpaXcbWindow, "qt.qpa.xcb.window");
Q_DECLARE_TYPEINFO(xcb_rectangle_t, Q_PRIMITIVE_TYPE);
@@ -94,12 +96,14 @@ const quint32 XEMBED_VERSION = 0;
QXcbScreen *QXcbWindow::parentScreen()
{
- return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : xcbScreen();
+ return QPlatformWindow::parent() ? static_cast<QXcbWindow*>(QPlatformWindow::parent())->parentScreen() : xcbScreen();
}
-//QPlatformWindow::screenForGeometry version that uses deviceIndependentGeometry
QXcbScreen *QXcbWindow::initialScreen() const
{
+ // Resolve initial screen via QWindowPrivate::screenForGeometry(),
+ // which works in platform independent coordinates, as opposed to
+ // QPlatformWindow::screenForGeometry() that uses native coordinates.
QWindowPrivate *windowPrivate = qt_window_private(window());
QScreen *screen = windowPrivate->screenForGeometry(window()->geometry());
return static_cast<QXcbScreen*>(screen->handle());
@@ -131,6 +135,7 @@ void QXcbWindow::setImageFormatForVisual(const xcb_visualtype_t *visual)
case 16:
qWarning("Using RGB16 fallback, if this works your X11 server is reporting a bad screen format.");
m_imageFormat = QImage::Format_RGB16;
+ break;
default:
break;
}
@@ -166,7 +171,7 @@ static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s)
tp.value = (uchar*)qcs.data();
tp.encoding = XA_STRING;
tp.format = 8;
- tp.nitems = qcs.length();
+ tp.nitems = qcs.size();
free_prop = false;
}
return &tp;
@@ -221,6 +226,7 @@ enum : quint32 {
void QXcbWindow::create()
{
+ xcb_window_t old_m_window = m_window;
destroy();
m_windowState = Qt::WindowNoState;
@@ -229,8 +235,8 @@ void QXcbWindow::create()
Qt::WindowType type = window()->type();
QXcbScreen *currentScreen = xcbScreen();
- QXcbScreen *platformScreen = parent() ? parentScreen() : initialScreen();
- QRect rect = parent()
+ QXcbScreen *platformScreen = QPlatformWindow::parent() ? parentScreen() : initialScreen();
+ QRect rect = QPlatformWindow::parent()
? QHighDpi::toNativeLocalPosition(window()->geometry(), platformScreen)
: QHighDpi::toNativePixels(window()->geometry(), platformScreen);
@@ -253,11 +259,6 @@ void QXcbWindow::create()
return;
}
- QPlatformWindow::setGeometry(rect);
-
- if (platformScreen != currentScreen)
- QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen());
-
const QSize minimumSize = windowMinimumSize();
if (rect.width() > 0 || rect.height() > 0) {
rect.setWidth(qBound(1, rect.width(), XCOORD_MAX));
@@ -269,12 +270,17 @@ void QXcbWindow::create()
rect.setHeight(QHighDpi::toNativePixels(int(defaultWindowHeight), platformScreen->QPlatformScreen::screen()));
}
+ QPlatformWindow::setGeometry(rect);
+
+ if (platformScreen != currentScreen)
+ QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen());
+
xcb_window_t xcb_parent_id = platformScreen->root();
- if (parent()) {
- xcb_parent_id = static_cast<QXcbWindow *>(parent())->xcb_window();
- m_embedded = parent()->isForeignWindow();
+ if (QPlatformWindow::parent()) {
+ xcb_parent_id = static_cast<QXcbWindow *>(QPlatformWindow::parent())->xcb_window();
+ m_embedded = QPlatformWindow::parent()->isForeignWindow();
- QSurfaceFormat parentFormat = parent()->window()->requestedFormat();
+ QSurfaceFormat parentFormat = QPlatformWindow::parent()->window()->requestedFormat();
if (window()->surfaceType() != QSurface::OpenGLSurface && parentFormat.hasAlpha()) {
window()->setFormat(parentFormat);
}
@@ -292,16 +298,16 @@ void QXcbWindow::create()
qWarning() << "Failed to use requested visual id.";
}
- if (parent()) {
+ if (QPlatformWindow::parent()) {
// When using a Vulkan QWindow via QWidget::createWindowContainer() we
// must make sure the visuals are compatible. Now, the parent will be
// of RasterGLSurface which typically chooses a GLX/EGL compatible
// visual which may not be what the Vulkan window would choose.
// Therefore, take the parent's visual.
if (window()->surfaceType() == QSurface::VulkanSurface
- && parent()->window()->surfaceType() != QSurface::VulkanSurface)
+ && QPlatformWindow::parent()->window()->surfaceType() != QSurface::VulkanSurface)
{
- visual = platformScreen->visualForId(static_cast<QXcbWindow *>(parent())->visualId());
+ visual = platformScreen->visualForId(static_cast<QXcbWindow *>(QPlatformWindow::parent())->visualId());
}
}
@@ -358,20 +364,20 @@ void QXcbWindow::create()
xcb_atom_t properties[5];
int propertyCount = 0;
- properties[propertyCount++] = atom(QXcbAtom::WM_DELETE_WINDOW);
- properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS);
- properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING);
+ properties[propertyCount++] = atom(QXcbAtom::AtomWM_DELETE_WINDOW);
+ properties[propertyCount++] = atom(QXcbAtom::AtomWM_TAKE_FOCUS);
+ properties[propertyCount++] = atom(QXcbAtom::Atom_NET_WM_PING);
if (connection()->hasXSync())
- properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST);
+ properties[propertyCount++] = atom(QXcbAtom::Atom_NET_WM_SYNC_REQUEST);
if (window()->flags() & Qt::WindowContextHelpButtonHint)
- properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP);
+ properties[propertyCount++] = atom(QXcbAtom::Atom_NET_WM_CONTEXT_HELP);
xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_window,
- atom(QXcbAtom::WM_PROTOCOLS),
+ atom(QXcbAtom::AtomWM_PROTOCOLS),
XCB_ATOM_ATOM,
32,
propertyCount,
@@ -382,10 +388,35 @@ void QXcbWindow::create()
const QByteArray wmClass = QXcbIntegration::instance()->wmClass();
if (!wmClass.isEmpty()) {
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE,
- m_window, atom(QXcbAtom::WM_CLASS),
+ m_window, atom(QXcbAtom::AtomWM_CLASS),
XCB_ATOM_STRING, 8, wmClass.size(), wmClass.constData());
}
+ QString desktopFileName = QGuiApplication::desktopFileName();
+ if (QGuiApplication::desktopFileName().isEmpty()) {
+ QFileInfo fi = QFileInfo(QCoreApplication::instance()->applicationFilePath());
+ QStringList domainName =
+ QCoreApplication::instance()->organizationDomain().split(QLatin1Char('.'),
+ Qt::SkipEmptyParts);
+
+ if (domainName.isEmpty()) {
+ desktopFileName = fi.baseName();
+ } else {
+ for (int i = 0; i < domainName.size(); ++i)
+ desktopFileName.prepend(QLatin1Char('.')).prepend(domainName.at(i));
+ desktopFileName.append(fi.baseName());
+ }
+ }
+ if (!desktopFileName.isEmpty()) {
+ const QByteArray dfName = desktopFileName.toUtf8();
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE,
+ m_window, atom(QXcbAtom::Atom_KDE_NET_WM_DESKTOP_FILE),
+ atom(QXcbAtom::AtomUTF8_STRING), 8, dfName.size(), dfName.constData());
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE,
+ m_window, atom(QXcbAtom::Atom_GTK_APPLICATION_ID),
+ atom(QXcbAtom::AtomUTF8_STRING), 8, dfName.size(), dfName.constData());
+ }
+
if (connection()->hasXSync()) {
m_syncCounter = xcb_generate_id(xcb_connection());
xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue);
@@ -393,7 +424,7 @@ void QXcbWindow::create()
xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_window,
- atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER),
+ atom(QXcbAtom::Atom_NET_WM_SYNC_REQUEST_COUNTER),
XCB_ATOM_CARDINAL,
32,
1,
@@ -403,13 +434,13 @@ void QXcbWindow::create()
// set the PID to let the WM kill the application if unresponsive
quint32 pid = getpid();
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32,
+ atom(QXcbAtom::Atom_NET_WM_PID), XCB_ATOM_CARDINAL, 32,
1, &pid);
const QByteArray clientMachine = QSysInfo::machineHostName().toLocal8Bit();
if (!clientMachine.isEmpty()) {
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::WM_CLIENT_MACHINE), XCB_ATOM_STRING, 8,
+ atom(QXcbAtom::AtomWM_CLIENT_MACHINE), XCB_ATOM_STRING, 8,
clientMachine.size(), clientMachine.constData());
}
@@ -423,14 +454,14 @@ void QXcbWindow::create()
xcb_window_t leader = connection()->clientLeader();
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32,
+ atom(QXcbAtom::AtomWM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32,
1, &leader);
/* Add XEMBED info; this operation doesn't initiate the embedding. */
quint32 data[] = { XEMBED_VERSION, XEMBED_MAPPED };
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::_XEMBED_INFO),
- atom(QXcbAtom::_XEMBED_INFO),
+ atom(QXcbAtom::Atom_XEMBED_INFO),
+ atom(QXcbAtom::Atom_XEMBED_INFO),
32, 2, (void *)data);
if (connection()->hasXInput2())
@@ -440,10 +471,8 @@ void QXcbWindow::create()
setWindowFlags(window()->flags());
setWindowTitle(window()->title());
-#if QT_CONFIG(xcb_xlib)
// force sync to read outstanding requests - see QTBUG-29106
- XSync(static_cast<Display*>(platformScreen->connection()->xlib_display()), false);
-#endif
+ connection()->sync();
#if QT_CONFIG(draganddrop)
connection()->drag()->dndEnable(this, true);
@@ -465,6 +494,17 @@ void QXcbWindow::create()
if (m_trayIconWindow)
m_embedded = requestSystemTrayWindowDock();
+
+ if (m_window != old_m_window) {
+ if (!m_wmTransientForChildren.isEmpty()) {
+ QList<QPointer<QXcbWindow>> transientChildren = m_wmTransientForChildren;
+ m_wmTransientForChildren.clear();
+ for (auto transientChild : transientChildren) {
+ if (transientChild)
+ transientChild->updateWmTransientFor();
+ }
+ }
+ }
}
QXcbWindow::~QXcbWindow()
@@ -472,6 +512,22 @@ QXcbWindow::~QXcbWindow()
destroy();
}
+QXcbForeignWindow::QXcbForeignWindow(QWindow *window, WId nativeHandle)
+ : QXcbWindow(window)
+{
+ m_window = nativeHandle;
+
+ // Reflect the foreign window's geometry as our own
+ if (auto geometry = Q_XCB_REPLY(xcb_get_geometry, xcb_connection(), m_window)) {
+ QRect nativeGeometry(geometry->x, geometry->y, geometry->width, geometry->height);
+ QPlatformWindow::setGeometry(nativeGeometry);
+ }
+
+ // And reparent, if we have a parent already
+ if (QPlatformWindow::parent())
+ setParent(QPlatformWindow::parent());
+}
+
QXcbForeignWindow::~QXcbForeignWindow()
{
// Clear window so that destroy() does not affect it
@@ -489,12 +545,14 @@ void QXcbWindow::destroy()
doFocusOut();
if (connection()->mouseGrabber() == this)
connection()->setMouseGrabber(nullptr);
+ if (connection()->mousePressWindow() == this)
+ connection()->setMousePressWindow(nullptr);
if (m_syncCounter && connection()->hasXSync())
xcb_sync_destroy_counter(xcb_connection(), m_syncCounter);
if (m_window) {
if (m_netWmUserTimeWindow) {
- xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW));
+ xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::Atom_NET_WM_USER_TIME_WINDOW));
// Some window managers, like metacity, do XSelectInput on the _NET_WM_USER_TIME_WINDOW window,
// without trapping BadWindow (which crashes when the user time window is destroyed).
connection()->sync();
@@ -515,12 +573,14 @@ void QXcbWindow::destroy()
void QXcbWindow::setGeometry(const QRect &rect)
{
+ setWindowState(Qt::WindowNoState);
+
QPlatformWindow::setGeometry(rect);
propagateSizeHints();
QXcbScreen *currentScreen = xcbScreen();
- QXcbScreen *newScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
+ QXcbScreen *newScreen = QPlatformWindow::parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
if (!newScreen)
newScreen = xcbScreen();
@@ -561,9 +621,9 @@ void QXcbWindow::setGeometry(const QRect &rect)
QMargins QXcbWindow::frameMargins() const
{
if (m_dirtyFrameMargins) {
- if (connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_FRAME_EXTENTS))) {
+ if (connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::Atom_NET_FRAME_EXTENTS))) {
auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, m_window,
- atom(QXcbAtom::_NET_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 0, 4);
+ atom(QXcbAtom::Atom_NET_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 0, 4);
if (reply && reply->type == XCB_ATOM_CARDINAL && reply->format == 32 && reply->value_len == 4) {
quint32 *data = (quint32 *)xcb_get_property_value(reply.get());
// _NET_FRAME_EXTENTS format is left, right, top, bottom
@@ -639,6 +699,44 @@ void QXcbWindow::setVisible(bool visible)
hide();
}
+void QXcbWindow::updateWmTransientFor()
+{
+ xcb_window_t transientXcbParent = XCB_NONE;
+ if (isTransient(window())) {
+ QWindow *tp = window()->transientParent();
+ if (tp && tp->handle()) {
+ QXcbWindow *handle = static_cast<QXcbWindow *>(tp->handle());
+ transientXcbParent = tp->handle()->winId();
+ if (transientXcbParent) {
+ handle->registerWmTransientForChild(this);
+ qCDebug(lcQpaXcbWindow) << Q_FUNC_INFO << static_cast<QPlatformWindow *>(handle)
+ << " registerWmTransientForChild " << static_cast<QPlatformWindow *>(this);
+ }
+ }
+ // Default to client leader if there is no transient parent, else modal dialogs can
+ // be hidden by their parents.
+ if (!transientXcbParent)
+ transientXcbParent = connection()->clientLeader();
+ if (transientXcbParent) { // ICCCM 4.1.2.6
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
+ 1, &transientXcbParent);
+ qCDebug(lcQpaXcbWindow, "0x%x added XCB_ATOM_WM_TRANSIENT_FOR 0x%x", m_window, transientXcbParent);
+ }
+ }
+ if (!transientXcbParent)
+ xcb_delete_property(xcb_connection(), m_window, XCB_ATOM_WM_TRANSIENT_FOR);
+}
+
+void QXcbWindow::registerWmTransientForChild(QXcbWindow *child)
+{
+ if (!child)
+ return;
+
+ if (!m_wmTransientForChildren.contains(child))
+ m_wmTransientForChildren.append(child);
+}
+
void QXcbWindow::show()
{
if (window()->isTopLevel()) {
@@ -652,23 +750,7 @@ void QXcbWindow::show()
propagateSizeHints();
// update WM_TRANSIENT_FOR
- xcb_window_t transientXcbParent = 0;
- if (isTransient(window())) {
- const QWindow *tp = window()->transientParent();
- if (tp && tp->handle())
- transientXcbParent = tp->handle()->winId();
- // Default to client leader if there is no transient parent, else modal dialogs can
- // be hidden by their parents.
- if (!transientXcbParent)
- transientXcbParent = connection()->clientLeader();
- if (transientXcbParent) { // ICCCM 4.1.2.6
- xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
- 1, &transientXcbParent);
- }
- }
- if (!transientXcbParent)
- xcb_delete_property(xcb_connection(), m_window, XCB_ATOM_WM_TRANSIENT_FOR);
+ updateWmTransientFor();
// update _NET_WM_STATE
setNetWmStateOnUnmappedWindow();
@@ -779,7 +861,7 @@ void QXcbWindow::doFocusIn()
return;
QWindow *w = static_cast<QWindowPrivate *>(QObjectPrivate::get(window()))->eventReceiver();
connection()->setFocusWindow(w);
- QWindowSystemInterface::handleWindowActivated(w, Qt::ActiveWindowFocusReason);
+ QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
}
void QXcbWindow::doFocusOut()
@@ -822,29 +904,29 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates()
NetWmStates result;
auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
- 0, m_window, atom(QXcbAtom::_NET_WM_STATE),
+ 0, m_window, atom(QXcbAtom::Atom_NET_WM_STATE),
XCB_ATOM_ATOM, 0, 1024);
if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) {
const xcb_atom_t *states = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get()));
const xcb_atom_t *statesEnd = states + reply->length;
- if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_ABOVE)))
+ if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::Atom_NET_WM_STATE_ABOVE)))
result |= NetWmStateAbove;
- if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_BELOW)))
+ if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::Atom_NET_WM_STATE_BELOW)))
result |= NetWmStateBelow;
- if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)))
+ if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::Atom_NET_WM_STATE_FULLSCREEN)))
result |= NetWmStateFullScreen;
- if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)))
+ if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::Atom_NET_WM_STATE_MAXIMIZED_HORZ)))
result |= NetWmStateMaximizedHorz;
- if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)))
+ if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::Atom_NET_WM_STATE_MAXIMIZED_VERT)))
result |= NetWmStateMaximizedVert;
- if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_MODAL)))
+ if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::Atom_NET_WM_STATE_MODAL)))
result |= NetWmStateModal;
- if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP)))
+ if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::Atom_NET_WM_STATE_STAYS_ON_TOP)))
result |= NetWmStateStaysOnTop;
- if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)))
+ if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::Atom_NET_WM_STATE_DEMANDS_ATTENTION)))
result |= NetWmStateDemandsAttention;
- if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_HIDDEN)))
+ if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::Atom_NET_WM_STATE_HIDDEN)))
result |= NetWmStateHidden;
} else {
qCDebug(lcQpaXcb, "getting net wm state (%x), empty\n", m_window);
@@ -959,13 +1041,13 @@ void QXcbWindow::setMotifWmHints(Qt::WindowFlags flags)
xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_window,
- atom(QXcbAtom::_MOTIF_WM_HINTS),
- atom(QXcbAtom::_MOTIF_WM_HINTS),
+ atom(QXcbAtom::Atom_MOTIF_WM_HINTS),
+ atom(QXcbAtom::Atom_MOTIF_WM_HINTS),
32,
5,
&mwmhints);
} else {
- xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_MOTIF_WM_HINTS));
+ xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::Atom_MOTIF_WM_HINTS));
}
}
@@ -977,7 +1059,7 @@ void QXcbWindow::setNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
event.format = 32;
event.sequence = 0;
event.window = m_window;
- event.type = atom(QXcbAtom::_NET_WM_STATE);
+ event.type = atom(QXcbAtom::Atom_NET_WM_STATE);
event.data.data32[0] = set ? 1 : 0;
event.data.data32[1] = one;
event.data.data32[2] = two;
@@ -993,26 +1075,26 @@ void QXcbWindow::setNetWmState(Qt::WindowStates state)
{
if ((m_windowState ^ state) & Qt::WindowMaximized) {
setNetWmState(state & Qt::WindowMaximized,
- atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
- atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
+ atom(QXcbAtom::Atom_NET_WM_STATE_MAXIMIZED_HORZ),
+ atom(QXcbAtom::Atom_NET_WM_STATE_MAXIMIZED_VERT));
}
if ((m_windowState ^ state) & Qt::WindowFullScreen)
- setNetWmState(state & Qt::WindowFullScreen, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
+ setNetWmState(state & Qt::WindowFullScreen, atom(QXcbAtom::Atom_NET_WM_STATE_FULLSCREEN));
}
void QXcbWindow::setNetWmState(Qt::WindowFlags flags)
{
setNetWmState(flags & Qt::WindowStaysOnTopHint,
- atom(QXcbAtom::_NET_WM_STATE_ABOVE),
- atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP));
- setNetWmState(flags & Qt::WindowStaysOnBottomHint, atom(QXcbAtom::_NET_WM_STATE_BELOW));
+ atom(QXcbAtom::Atom_NET_WM_STATE_ABOVE),
+ atom(QXcbAtom::Atom_NET_WM_STATE_STAYS_ON_TOP));
+ setNetWmState(flags & Qt::WindowStaysOnBottomHint, atom(QXcbAtom::Atom_NET_WM_STATE_BELOW));
}
void QXcbWindow::setNetWmStateOnUnmappedWindow()
{
if (Q_UNLIKELY(m_mapped))
- qCWarning(lcQpaXcb()) << "internal error: " << Q_FUNC_INFO << "called on mapped window";
+ qCDebug(lcQpaXcb()) << "internal info: " << Q_FUNC_INFO << "called on mapped window";
NetWmStates states;
const Qt::WindowFlags flags = window()->flags();
@@ -1047,7 +1129,7 @@ void QXcbWindow::setNetWmStateOnUnmappedWindow()
QList<xcb_atom_t> atoms;
auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
- 0, m_window, atom(QXcbAtom::_NET_WM_STATE),
+ 0, m_window, atom(QXcbAtom::Atom_NET_WM_STATE),
XCB_ATOM_ATOM, 0, 1024);
if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM && reply->value_len > 0) {
const xcb_atom_t *data = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get()));
@@ -1055,31 +1137,31 @@ void QXcbWindow::setNetWmStateOnUnmappedWindow()
memcpy((void *)&atoms.first(), (void *)data, reply->value_len * sizeof(xcb_atom_t));
}
- if (states & NetWmStateAbove && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_ABOVE)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
- if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW));
- if (states & NetWmStateHidden && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_HIDDEN)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_HIDDEN));
- if (states & NetWmStateFullScreen && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
- if (states & NetWmStateMaximizedHorz && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ));
- if (states & NetWmStateMaximizedVert && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
- if (states & NetWmStateModal && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MODAL)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MODAL));
- if (states & NetWmStateStaysOnTop && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP));
- if (states & NetWmStateDemandsAttention && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)))
- atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION));
+ if (states & NetWmStateAbove && !atoms.contains(atom(QXcbAtom::Atom_NET_WM_STATE_ABOVE)))
+ atoms.push_back(atom(QXcbAtom::Atom_NET_WM_STATE_ABOVE));
+ if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::Atom_NET_WM_STATE_BELOW)))
+ atoms.push_back(atom(QXcbAtom::Atom_NET_WM_STATE_BELOW));
+ if (states & NetWmStateHidden && !atoms.contains(atom(QXcbAtom::Atom_NET_WM_STATE_HIDDEN)))
+ atoms.push_back(atom(QXcbAtom::Atom_NET_WM_STATE_HIDDEN));
+ if (states & NetWmStateFullScreen && !atoms.contains(atom(QXcbAtom::Atom_NET_WM_STATE_FULLSCREEN)))
+ atoms.push_back(atom(QXcbAtom::Atom_NET_WM_STATE_FULLSCREEN));
+ if (states & NetWmStateMaximizedHorz && !atoms.contains(atom(QXcbAtom::Atom_NET_WM_STATE_MAXIMIZED_HORZ)))
+ atoms.push_back(atom(QXcbAtom::Atom_NET_WM_STATE_MAXIMIZED_HORZ));
+ if (states & NetWmStateMaximizedVert && !atoms.contains(atom(QXcbAtom::Atom_NET_WM_STATE_MAXIMIZED_VERT)))
+ atoms.push_back(atom(QXcbAtom::Atom_NET_WM_STATE_MAXIMIZED_VERT));
+ if (states & NetWmStateModal && !atoms.contains(atom(QXcbAtom::Atom_NET_WM_STATE_MODAL)))
+ atoms.push_back(atom(QXcbAtom::Atom_NET_WM_STATE_MODAL));
+ if (states & NetWmStateStaysOnTop && !atoms.contains(atom(QXcbAtom::Atom_NET_WM_STATE_STAYS_ON_TOP)))
+ atoms.push_back(atom(QXcbAtom::Atom_NET_WM_STATE_STAYS_ON_TOP));
+ if (states & NetWmStateDemandsAttention && !atoms.contains(atom(QXcbAtom::Atom_NET_WM_STATE_DEMANDS_ATTENTION)))
+ atoms.push_back(atom(QXcbAtom::Atom_NET_WM_STATE_DEMANDS_ATTENTION));
if (atoms.isEmpty()) {
- xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_STATE));
+ xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::Atom_NET_WM_STATE));
} else {
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::_NET_WM_STATE), XCB_ATOM_ATOM, 32,
- atoms.count(), atoms.constData());
+ atom(QXcbAtom::Atom_NET_WM_STATE), XCB_ATOM_ATOM, 32,
+ atoms.size(), atoms.constData());
}
xcb_flush(xcb_connection());
}
@@ -1089,18 +1171,21 @@ void QXcbWindow::setWindowState(Qt::WindowStates state)
if (state == m_windowState)
return;
+ Qt::WindowStates unsetState = m_windowState & ~state;
+ Qt::WindowStates newState = state & ~m_windowState;
+
// unset old state
- if (m_windowState & Qt::WindowMinimized)
+ if (unsetState & Qt::WindowMinimized)
xcb_map_window(xcb_connection(), m_window);
- if (m_windowState & Qt::WindowMaximized)
+ if (unsetState & Qt::WindowMaximized)
setNetWmState(false,
- atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
- atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
- if (m_windowState & Qt::WindowFullScreen)
- setNetWmState(false, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
+ atom(QXcbAtom::Atom_NET_WM_STATE_MAXIMIZED_HORZ),
+ atom(QXcbAtom::Atom_NET_WM_STATE_MAXIMIZED_VERT));
+ if (unsetState & Qt::WindowFullScreen)
+ setNetWmState(false, atom(QXcbAtom::Atom_NET_WM_STATE_FULLSCREEN));
// set new state
- if (state & Qt::WindowMinimized) {
+ if (newState & Qt::WindowMinimized) {
{
xcb_client_message_event_t event;
@@ -1108,7 +1193,7 @@ void QXcbWindow::setWindowState(Qt::WindowStates state)
event.format = 32;
event.sequence = 0;
event.window = m_window;
- event.type = atom(QXcbAtom::WM_CHANGE_STATE);
+ event.type = atom(QXcbAtom::AtomWM_CHANGE_STATE);
event.data.data32[0] = XCB_ICCCM_WM_STATE_ICONIC;
event.data.data32[1] = 0;
event.data.data32[2] = 0;
@@ -1121,13 +1206,8 @@ void QXcbWindow::setWindowState(Qt::WindowStates state)
}
m_minimized = true;
}
- if (state & Qt::WindowMaximized)
- setNetWmState(true,
- atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
- atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
- if (state & Qt::WindowFullScreen)
- setNetWmState(true, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
+ // set Maximized && FullScreen state if need
setNetWmState(state);
xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_hints_unchecked(xcb_connection(), m_window);
@@ -1153,7 +1233,7 @@ void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp)
if (timestamp != 0)
connection()->setNetWmUserTime(timestamp);
- const bool isSupportedByWM = connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW));
+ const bool isSupportedByWM = connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::Atom_NET_WM_USER_TIME_WINDOW));
if (m_netWmUserTimeWindow || isSupportedByWM) {
if (!m_netWmUserTimeWindow) {
m_netWmUserTimeWindow = xcb_generate_id(xcb_connection());
@@ -1168,9 +1248,9 @@ void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp)
0, // value mask
nullptr); // value list
wid = m_netWmUserTimeWindow;
- xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW),
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::Atom_NET_WM_USER_TIME_WINDOW),
XCB_ATOM_WINDOW, 32, 1, &m_netWmUserTimeWindow);
- xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME));
+ xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::Atom_NET_WM_USER_TIME));
QXcbWindow::setWindowTitle(connection(), m_netWmUserTimeWindow,
QStringLiteral("Qt NET_WM User Time Window"));
@@ -1178,14 +1258,14 @@ void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp)
} else if (!isSupportedByWM) {
// WM no longer supports it, then we should remove the
// _NET_WM_USER_TIME_WINDOW atom.
- xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW));
+ xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::Atom_NET_WM_USER_TIME_WINDOW));
xcb_destroy_window(xcb_connection(), m_netWmUserTimeWindow);
m_netWmUserTimeWindow = XCB_NONE;
} else {
wid = m_netWmUserTimeWindow;
}
}
- xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, wid, atom(QXcbAtom::_NET_WM_USER_TIME),
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, wid, atom(QXcbAtom::Atom_NET_WM_USER_TIME),
XCB_ATOM_CARDINAL, 32, 1, &timestamp);
}
@@ -1260,10 +1340,10 @@ void QXcbWindow::setWindowIconText(const QString &title)
xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_window,
- atom(QXcbAtom::_NET_WM_ICON_NAME),
- atom(QXcbAtom::UTF8_STRING),
+ atom(QXcbAtom::Atom_NET_WM_ICON_NAME),
+ atom(QXcbAtom::AtomUTF8_STRING),
8,
- ba.length(),
+ ba.size(),
ba.constData());
}
@@ -1295,23 +1375,24 @@ void QXcbWindow::setWindowIcon(const QIcon &icon)
if (!icon_data.isEmpty()) {
// Ignore icon exceeding maximum xcb request length
- if (icon_data.size() > xcb_get_maximum_request_length(xcb_connection())) {
- qWarning("Ignoring window icon: Size %llu exceeds maximum xcb request length %u.",
- icon_data.size(), xcb_get_maximum_request_length(xcb_connection()));
+ if (quint64(icon_data.size()) > quint64(xcb_get_maximum_request_length(xcb_connection()))) {
+ qWarning() << "Ignoring window icon" << icon_data.size()
+ << "exceeds maximum xcb request length"
+ << xcb_get_maximum_request_length(xcb_connection());
return;
}
xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_window,
- atom(QXcbAtom::_NET_WM_ICON),
- atom(QXcbAtom::CARDINAL),
+ atom(QXcbAtom::Atom_NET_WM_ICON),
+ atom(QXcbAtom::AtomCARDINAL),
32,
icon_data.size(),
(unsigned char *) icon_data.data());
} else {
xcb_delete_property(xcb_connection(),
m_window,
- atom(QXcbAtom::_NET_WM_ICON));
+ atom(QXcbAtom::Atom_NET_WM_ICON));
}
}
@@ -1368,7 +1449,8 @@ void QXcbWindow::propagateSizeHints()
qMin(XCOORD_MAX, maximumSize.height()));
if (sizeIncrement.width() > 0 || sizeIncrement.height() > 0) {
- xcb_icccm_size_hints_set_base_size(&hints, baseSize.width(), baseSize.height());
+ if (!baseSize.isNull() && baseSize.isValid())
+ xcb_icccm_size_hints_set_base_size(&hints, baseSize.width(), baseSize.height());
xcb_icccm_size_hints_set_resize_inc(&hints, sizeIncrement.width(), sizeIncrement.height());
}
@@ -1386,29 +1468,37 @@ void QXcbWindow::requestActivateWindow()
return;
}
- if (!m_mapped) {
- m_deferredActivation = true;
- return;
+ {
+ QMutexLocker locker(&m_mappedMutex);
+ if (!m_mapped) {
+ m_deferredActivation = true;
+ return;
+ }
+ m_deferredActivation = false;
}
- m_deferredActivation = false;
updateNetWmUserTime(connection()->time());
QWindow *focusWindow = QGuiApplication::focusWindow();
+ xcb_window_t current = XCB_NONE;
+ if (focusWindow) {
+ if (QPlatformWindow *pw = focusWindow->handle())
+ current = pw->winId();
+ }
if (window()->isTopLevel()
&& !(window()->flags() & Qt::X11BypassWindowManagerHint)
&& (!focusWindow || !window()->isAncestorOf(focusWindow))
- && connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_ACTIVE_WINDOW))) {
+ && connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::Atom_NET_ACTIVE_WINDOW))) {
xcb_client_message_event_t event;
event.response_type = XCB_CLIENT_MESSAGE;
event.format = 32;
event.sequence = 0;
event.window = m_window;
- event.type = atom(QXcbAtom::_NET_ACTIVE_WINDOW);
+ event.type = atom(QXcbAtom::Atom_NET_ACTIVE_WINDOW);
event.data.data32[0] = 1;
event.data.data32[1] = connection()->time();
- event.data.data32[2] = focusWindow ? focusWindow->winId() : XCB_NONE;
+ event.data.data32[2] = current;
event.data.data32[3] = 0;
event.data.data32[4] = 0;
@@ -1432,7 +1522,7 @@ QXcbWindow::WindowTypes QXcbWindow::wmWindowTypes() const
WindowTypes result;
auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
- 0, m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE),
+ 0, m_window, atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE),
XCB_ATOM_ATOM, 0, 1024);
if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) {
const xcb_atom_t *types = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get()));
@@ -1440,49 +1530,49 @@ QXcbWindow::WindowTypes QXcbWindow::wmWindowTypes() const
for (; types != types_end; types++) {
QXcbAtom::Atom type = connection()->qatom(*types);
switch (type) {
- case QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_NORMAL:
result |= WindowType::Normal;
break;
- case QXcbAtom::_NET_WM_WINDOW_TYPE_DESKTOP:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_DESKTOP:
result |= WindowType::Desktop;
break;
- case QXcbAtom::_NET_WM_WINDOW_TYPE_DOCK:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_DOCK:
result |= WindowType::Dock;
break;
- case QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLBAR:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_TOOLBAR:
result |= WindowType::Toolbar;
break;
- case QXcbAtom::_NET_WM_WINDOW_TYPE_MENU:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_MENU:
result |= WindowType::Menu;
break;
- case QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_UTILITY:
result |= WindowType::Utility;
break;
- case QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_SPLASH:
result |= WindowType::Splash;
break;
- case QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_DIALOG:
result |= WindowType::Dialog;
break;
- case QXcbAtom::_NET_WM_WINDOW_TYPE_DROPDOWN_MENU:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_DROPDOWN_MENU:
result |= WindowType::DropDownMenu;
break;
- case QXcbAtom::_NET_WM_WINDOW_TYPE_POPUP_MENU:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_POPUP_MENU:
result |= WindowType::PopupMenu;
break;
- case QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_TOOLTIP:
result |= WindowType::Tooltip;
break;
- case QXcbAtom::_NET_WM_WINDOW_TYPE_NOTIFICATION:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_NOTIFICATION:
result |= WindowType::Notification;
break;
- case QXcbAtom::_NET_WM_WINDOW_TYPE_COMBO:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_COMBO:
result |= WindowType::Combo;
break;
- case QXcbAtom::_NET_WM_WINDOW_TYPE_DND:
+ case QXcbAtom::Atom_NET_WM_WINDOW_TYPE_DND:
result |= WindowType::Dnd;
break;
- case QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE:
+ case QXcbAtom::Atom_KDE_NET_WM_WINDOW_TYPE_OVERRIDE:
result |= WindowType::KdeOverride;
break;
default:
@@ -1499,41 +1589,41 @@ void QXcbWindow::setWmWindowType(WindowTypes types, Qt::WindowFlags flags)
// manual selection 1 (these are never set by Qt and take precedence)
if (types & WindowType::Normal)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_NORMAL));
if (types & WindowType::Desktop)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DESKTOP));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_DESKTOP));
if (types & WindowType::Dock)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DOCK));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_DOCK));
if (types & WindowType::Notification)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NOTIFICATION));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_NOTIFICATION));
// manual selection 2 (Qt uses these during auto selection);
if (types & WindowType::Utility)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_UTILITY));
if (types & WindowType::Splash)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_SPLASH));
if (types & WindowType::Dialog)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_DIALOG));
if (types & WindowType::Tooltip)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_TOOLTIP));
if (types & WindowType::KdeOverride)
- atoms.append(atom(QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
+ atoms.append(atom(QXcbAtom::Atom_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
// manual selection 3 (these can be set by Qt, but don't have a
// corresponding Qt::WindowType). note that order of the *MENU
// atoms is important
if (types & WindowType::Menu)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_MENU));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_MENU));
if (types & WindowType::DropDownMenu)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DROPDOWN_MENU));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_DROPDOWN_MENU));
if (types & WindowType::PopupMenu)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_POPUP_MENU));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_POPUP_MENU));
if (types & WindowType::Toolbar)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLBAR));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_TOOLBAR));
if (types & WindowType::Combo)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_COMBO));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_COMBO));
if (types & WindowType::Dnd)
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DND));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_DND));
// automatic selection
Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
@@ -1541,20 +1631,20 @@ void QXcbWindow::setWmWindowType(WindowTypes types, Qt::WindowFlags flags)
case Qt::Dialog:
case Qt::Sheet:
if (!(types & WindowType::Dialog))
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_DIALOG));
break;
case Qt::Tool:
case Qt::Drawer:
if (!(types & WindowType::Utility))
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_UTILITY));
break;
case Qt::ToolTip:
if (!(types & WindowType::Tooltip))
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_TOOLTIP));
break;
case Qt::SplashScreen:
if (!(types & WindowType::Splash))
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_SPLASH));
break;
default:
break;
@@ -1562,20 +1652,20 @@ void QXcbWindow::setWmWindowType(WindowTypes types, Qt::WindowFlags flags)
if ((flags & Qt::FramelessWindowHint) && !(types & WindowType::KdeOverride)) {
// override netwm type - quick and easy for KDE noborder
- atoms.append(atom(QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
+ atoms.append(atom(QXcbAtom::Atom_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
}
- if (atoms.size() == 1 && atoms.first() == atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL))
+ if (atoms.size() == 1 && atoms.first() == atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_NORMAL))
atoms.clear();
else
- atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL));
+ atoms.append(atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE_NORMAL));
if (atoms.isEmpty()) {
- xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE));
+ xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE));
} else {
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32,
- atoms.count(), atoms.constData());
+ atom(QXcbAtom::Atom_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32,
+ atoms.size(), atoms.constData());
}
xcb_flush(xcb_connection());
}
@@ -1584,7 +1674,7 @@ void QXcbWindow::setWindowRole(const QString &role)
{
QByteArray roleData = role.toLatin1();
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::WM_WINDOW_ROLE), XCB_ATOM_STRING, 8,
+ atom(QXcbAtom::AtomWM_WINDOW_ROLE), XCB_ATOM_STRING, 8,
roleData.size(), roleData.constData());
}
@@ -1643,15 +1733,15 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
if (event->format != 32)
return;
- if (event->type == atom(QXcbAtom::WM_PROTOCOLS)) {
+ if (event->type == atom(QXcbAtom::AtomWM_PROTOCOLS)) {
xcb_atom_t protocolAtom = event->data.data32[0];
- if (protocolAtom == atom(QXcbAtom::WM_DELETE_WINDOW)) {
+ if (protocolAtom == atom(QXcbAtom::AtomWM_DELETE_WINDOW)) {
QWindowSystemInterface::handleCloseEvent(window());
- } else if (protocolAtom == atom(QXcbAtom::WM_TAKE_FOCUS)) {
+ } else if (protocolAtom == atom(QXcbAtom::AtomWM_TAKE_FOCUS)) {
connection()->setTime(event->data.data32[1]);
relayFocusToModalWindow();
return;
- } else if (protocolAtom == atom(QXcbAtom::_NET_WM_PING)) {
+ } else if (protocolAtom == atom(QXcbAtom::Atom_NET_WM_PING)) {
if (event->window == xcbScreen()->root())
return;
@@ -1664,14 +1754,14 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
(const char *)&reply);
xcb_flush(xcb_connection());
- } else if (protocolAtom == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) {
+ } else if (protocolAtom == atom(QXcbAtom::Atom_NET_WM_SYNC_REQUEST)) {
connection()->setTime(event->data.data32[1]);
m_syncValue.lo = event->data.data32[2];
m_syncValue.hi = event->data.data32[3];
if (connection()->hasXSync())
m_syncState = SyncReceived;
#ifndef QT_NO_WHATSTHIS
- } else if (protocolAtom == atom(QXcbAtom::_NET_WM_CONTEXT_HELP)) {
+ } else if (protocolAtom == atom(QXcbAtom::Atom_NET_WM_CONTEXT_HELP)) {
QWindowSystemInterface::handleEnterWhatsThisEvent();
#endif
} else {
@@ -1679,29 +1769,29 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
connection()->atomName(protocolAtom).constData());
}
#if QT_CONFIG(draganddrop)
- } else if (event->type == atom(QXcbAtom::XdndEnter)) {
+ } else if (event->type == atom(QXcbAtom::AtomXdndEnter)) {
connection()->drag()->handleEnter(this, event);
- } else if (event->type == atom(QXcbAtom::XdndPosition)) {
+ } else if (event->type == atom(QXcbAtom::AtomXdndPosition)) {
connection()->drag()->handlePosition(this, event);
- } else if (event->type == atom(QXcbAtom::XdndLeave)) {
+ } else if (event->type == atom(QXcbAtom::AtomXdndLeave)) {
connection()->drag()->handleLeave(this, event);
- } else if (event->type == atom(QXcbAtom::XdndDrop)) {
+ } else if (event->type == atom(QXcbAtom::AtomXdndDrop)) {
connection()->drag()->handleDrop(this, event);
#endif
- } else if (event->type == atom(QXcbAtom::_XEMBED)) {
+ } else if (event->type == atom(QXcbAtom::Atom_XEMBED)) {
handleXEmbedMessage(event);
- } else if (event->type == atom(QXcbAtom::_NET_ACTIVE_WINDOW)) {
+ } else if (event->type == atom(QXcbAtom::Atom_NET_ACTIVE_WINDOW)) {
doFocusIn();
- } else if (event->type == atom(QXcbAtom::MANAGER)
- || event->type == atom(QXcbAtom::_NET_WM_STATE)
- || event->type == atom(QXcbAtom::WM_CHANGE_STATE)) {
+ } else if (event->type == atom(QXcbAtom::AtomMANAGER)
+ || event->type == atom(QXcbAtom::Atom_NET_WM_STATE)
+ || event->type == atom(QXcbAtom::AtomWM_CHANGE_STATE)) {
// Ignore _NET_WM_STATE, MANAGER which are relate to tray icons
// and other messages.
- } else if (event->type == atom(QXcbAtom::_COMPIZ_DECOR_PENDING)
- || event->type == atom(QXcbAtom::_COMPIZ_DECOR_REQUEST)
- || event->type == atom(QXcbAtom::_COMPIZ_DECOR_DELETE_PIXMAP)
- || event->type == atom(QXcbAtom::_COMPIZ_TOOLKIT_ACTION)
- || event->type == atom(QXcbAtom::_GTK_LOAD_ICONTHEMES)) {
+ } else if (event->type == atom(QXcbAtom::Atom_COMPIZ_DECOR_PENDING)
+ || event->type == atom(QXcbAtom::Atom_COMPIZ_DECOR_REQUEST)
+ || event->type == atom(QXcbAtom::Atom_COMPIZ_DECOR_DELETE_PIXMAP)
+ || event->type == atom(QXcbAtom::Atom_COMPIZ_TOOLKIT_ACTION)
+ || event->type == atom(QXcbAtom::Atom_GTK_LOAD_ICONTHEMES)) {
//silence the _COMPIZ and _GTK messages for now
} else {
qCWarning(lcQpaXcb) << "Unhandled client message: " << connection()->atomName(event->type);
@@ -1712,7 +1802,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
{
bool fromSendEvent = (event->response_type & 0x80);
QPoint pos(event->x, event->y);
- if (!parent() && !fromSendEvent) {
+ if (!QPlatformWindow::parent() && !fromSendEvent) {
// Do not trust the position, query it instead.
auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(),
xcb_window(), xcbScreen()->root(), 0, 0);
@@ -1723,7 +1813,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
}
const QRect actualGeometry = QRect(pos, QSize(event->width, event->height));
- QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry);
+ QPlatformScreen *newScreen = QPlatformWindow::parent() ? QPlatformWindow::parent()->screen() : screenForGeometry(actualGeometry);
if (!newScreen)
return;
@@ -1799,8 +1889,11 @@ QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const
void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event)
{
if (event->window == m_window) {
+ m_mappedMutex.lock();
m_mapped = true;
- if (m_deferredActivation)
+ const bool deferredActivation = m_deferredActivation;
+ m_mappedMutex.unlock();
+ if (deferredActivation)
requestActivateWindow();
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
@@ -1810,7 +1903,9 @@ void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event)
void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event)
{
if (event->window == m_window) {
+ m_mappedMutex.lock();
m_mapped = false;
+ m_mappedMutex.unlock();
QWindowSystemInterface::handleExposeEvent(window(), QRegion());
}
}
@@ -1833,7 +1928,7 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
if (m_embedded && !m_trayIconWindow) {
if (window() != QGuiApplication::focusWindow()) {
- const QXcbWindow *container = static_cast<const QXcbWindow *>(parent());
+ const QXcbWindow *container = static_cast<const QXcbWindow *>(QPlatformWindow::parent());
Q_ASSERT(container != nullptr);
sendXEmbedMessage(container->xcb_window(), XEMBED_REQUEST_FOCUS);
@@ -1877,8 +1972,10 @@ void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x,
return;
}
- if (connection()->buttonState() == Qt::NoButton)
+ if (connection()->buttonState() == Qt::NoButton) {
connection()->setMousePressWindow(nullptr);
+ m_ignorePressedWindowOnMouseLeave = false;
+ }
handleMouseEvent(timestamp, local, global, modifiers, type, source);
}
@@ -1898,10 +1995,10 @@ static inline bool doCheckUnGrabAncestor(QXcbConnection *conn)
return true;
}
-static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn = nullptr)
+static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn)
{
return ((doCheckUnGrabAncestor(conn)
- && mode == XCB_NOTIFY_MODE_GRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR)
+ && mode == XCB_NOTIFY_MODE_GRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR)
|| (mode == XCB_NOTIFY_MODE_UNGRAB && detail == XCB_NOTIFY_DETAIL_INFERIOR)
|| detail == XCB_NOTIFY_DETAIL_VIRTUAL
|| detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL);
@@ -1921,14 +2018,18 @@ void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, in
{
connection()->setTime(timestamp);
- const QPoint global = QPoint(root_x, root_y);
-
- if (ignoreEnterEvent(mode, detail, connection()) || connection()->mousePressWindow())
+ if (ignoreEnterEvent(mode, detail, connection())
+ || (connection()->mousePressWindow() && !m_ignorePressedWindowOnMouseLeave)) {
return;
+ }
// Updates scroll valuators, as user might have done some scrolling outside our X client.
connection()->xi2UpdateScrollingDevices();
+ if (mode == XCB_NOTIFY_MODE_UNGRAB && connection()->queryMouseButtons() != Qt::NoButton)
+ m_ignorePressedWindowOnMouseLeave = true;
+
+ const QPoint global = QPoint(root_x, root_y);
const QPoint local(event_x, event_y);
QWindowSystemInterface::handleEnterEvent(window(), local, global);
}
@@ -1938,8 +2039,11 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y,
{
connection()->setTime(timestamp);
- if (ignoreLeaveEvent(mode, detail, connection()) || connection()->mousePressWindow())
+ QXcbWindow *mousePressWindow = connection()->mousePressWindow();
+ if (ignoreLeaveEvent(mode, detail, connection())
+ || (mousePressWindow && !m_ignorePressedWindowOnMouseLeave)) {
return;
+ }
// check if enter event is buffered
auto event = connection()->eventQueue()->peek([](xcb_generic_event_t *event, int type) {
@@ -1957,6 +2061,8 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y,
QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global);
} else {
QWindowSystemInterface::handleLeaveEvent(window());
+ if (m_ignorePressedWindowOnMouseLeave)
+ connection()->setMousePressWindow(nullptr);
}
free(enter);
@@ -2133,17 +2239,17 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
- if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
+ if (event->atom == atom(QXcbAtom::Atom_NET_WM_STATE) || event->atom == atom(QXcbAtom::AtomWM_STATE)) {
if (propertyDeleted)
return;
Qt::WindowStates newState = Qt::WindowNoState;
- if (event->atom == atom(QXcbAtom::WM_STATE)) { // WM_STATE: Quick check for 'Minimize'.
+ if (event->atom == atom(QXcbAtom::AtomWM_STATE)) { // WM_STATE: Quick check for 'Minimize'.
auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
- 0, m_window, atom(QXcbAtom::WM_STATE),
+ 0, m_window, atom(QXcbAtom::AtomWM_STATE),
XCB_ATOM_ANY, 0, 1024);
- if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) {
+ if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::AtomWM_STATE)) {
const quint32 *data = (const quint32 *)xcb_get_property_value(reply.get());
if (reply->length != 0)
m_minimized = (data[0] == XCB_ICCCM_WM_STATE_ICONIC
@@ -2173,7 +2279,7 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
connection()->setMouseGrabber(nullptr);
}
return;
- } else if (event->atom == atom(QXcbAtom::_NET_FRAME_EXTENTS)) {
+ } else if (event->atom == atom(QXcbAtom::Atom_NET_FRAME_EXTENTS)) {
m_dirtyFrameMargins = true;
}
}
@@ -2282,7 +2388,7 @@ bool QXcbWindow::windowEvent(QEvent *event)
case Qt::BacktabFocusReason:
{
const QXcbWindow *container =
- static_cast<const QXcbWindow *>(parent());
+ static_cast<const QXcbWindow *>(QPlatformWindow::parent());
sendXEmbedMessage(container->xcb_window(),
focusEvent->reason() == Qt::TabFocusReason ?
XEMBED_FOCUS_NEXT : XEMBED_FOCUS_PREV);
@@ -2312,7 +2418,7 @@ bool QXcbWindow::startSystemMove()
bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int edges)
{
- const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
+ const xcb_atom_t moveResize = connection()->atom(QXcbAtom::Atom_NET_WM_MOVERESIZE);
if (!connection()->wmSupport()->isSupportedByWM(moveResize))
return false;
@@ -2360,7 +2466,7 @@ static uint qtEdgesToXcbMoveResizeDirection(Qt::Edges edges)
void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int edges)
{
qCDebug(lcQpaXInputDevices) << "triggered system move or resize via sending _NET_WM_MOVERESIZE client message";
- const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
+ const xcb_atom_t moveResize = connection()->atom(QXcbAtom::Atom_NET_WM_MOVERESIZE);
xcb_client_message_event_t xev;
xev.response_type = XCB_CLIENT_MESSAGE;
xev.type = moveResize;
@@ -2393,7 +2499,7 @@ void QXcbWindow::sendXEmbedMessage(xcb_window_t window, quint32 message,
event.format = 32;
event.sequence = 0;
event.window = window;
- event.type = atom(QXcbAtom::_XEMBED);
+ event.type = atom(QXcbAtom::Atom_XEMBED);
event.data.data32[0] = connection()->time();
event.data.data32[1] = message;
event.data.data32[2] = detail;
@@ -2402,15 +2508,15 @@ void QXcbWindow::sendXEmbedMessage(xcb_window_t window, quint32 message,
xcb_send_event(xcb_connection(), false, window, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
}
-static bool activeWindowChangeQueued(const QWindow *window)
+static bool focusWindowChangeQueued(const QWindow *window)
{
/* Check from window system event queue if the next queued activation
* targets a window other than @window.
*/
- QWindowSystemInterfacePrivate::ActivatedWindowEvent *systemEvent =
- static_cast<QWindowSystemInterfacePrivate::ActivatedWindowEvent *>
- (QWindowSystemInterfacePrivate::peekWindowSystemEvent(QWindowSystemInterfacePrivate::ActivatedWindow));
- return systemEvent && systemEvent->activated != window;
+ QWindowSystemInterfacePrivate::FocusWindowEvent *systemEvent =
+ static_cast<QWindowSystemInterfacePrivate::FocusWindowEvent *>
+ (QWindowSystemInterfacePrivate::peekWindowSystemEvent(QWindowSystemInterfacePrivate::FocusWindow));
+ return systemEvent && systemEvent->focused != window;
}
void QXcbWindow::handleXEmbedMessage(const xcb_client_message_event_t *event)
@@ -2440,13 +2546,13 @@ void QXcbWindow::handleXEmbedMessage(const xcb_client_message_event_t *event)
break;
}
connection()->setFocusWindow(window());
- QWindowSystemInterface::handleWindowActivated(window(), reason);
+ QWindowSystemInterface::handleFocusWindowChanged(window(), reason);
break;
case XEMBED_FOCUS_OUT:
if (window() == QGuiApplication::focusWindow()
- && !activeWindowChangeQueued(window())) {
+ && !focusWindowChangeQueued(window())) {
connection()->setFocusWindow(nullptr);
- QWindowSystemInterface::handleWindowActivated(nullptr);
+ QWindowSystemInterface::handleFocusWindowChanged(nullptr);
}
break;
}
@@ -2472,7 +2578,7 @@ void QXcbWindow::setOpacity(qreal level)
xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_window,
- atom(QXcbAtom::_NET_WM_WINDOW_OPACITY),
+ atom(QXcbAtom::Atom_NET_WM_WINDOW_OPACITY),
XCB_ATOM_CARDINAL,
32,
1,
@@ -2510,7 +2616,7 @@ void QXcbWindow::setAlertState(bool enabled)
m_alertState = enabled;
- setNetWmState(enabled, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION));
+ setNetWmState(enabled, atom(QXcbAtom::Atom_NET_WM_STATE_DEMANDS_ATTENTION));
}
uint QXcbWindow::visualId() const
@@ -2544,10 +2650,10 @@ void QXcbWindow::setWindowTitle(const QXcbConnection *conn, xcb_window_t window,
xcb_change_property(conn->xcb_connection(),
XCB_PROP_MODE_REPLACE,
window,
- conn->atom(QXcbAtom::_NET_WM_NAME),
- conn->atom(QXcbAtom::UTF8_STRING),
+ conn->atom(QXcbAtom::Atom_NET_WM_NAME),
+ conn->atom(QXcbAtom::AtomUTF8_STRING),
8,
- ba.length(),
+ ba.size(),
ba.constData());
#if QT_CONFIG(xcb_xlib)
@@ -2561,9 +2667,9 @@ void QXcbWindow::setWindowTitle(const QXcbConnection *conn, xcb_window_t window,
QString QXcbWindow::windowTitle(const QXcbConnection *conn, xcb_window_t window)
{
- const xcb_atom_t utf8Atom = conn->atom(QXcbAtom::UTF8_STRING);
+ const xcb_atom_t utf8Atom = conn->atom(QXcbAtom::AtomUTF8_STRING);
auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, conn->xcb_connection(),
- false, window, conn->atom(QXcbAtom::_NET_WM_NAME),
+ false, window, conn->atom(QXcbAtom::Atom_NET_WM_NAME),
utf8Atom, 0, 1024);
if (reply && reply->format == 8 && reply->type == utf8Atom) {
const char *name = reinterpret_cast<const char *>(xcb_get_property_value(reply.get()));
@@ -2571,7 +2677,7 @@ QString QXcbWindow::windowTitle(const QXcbConnection *conn, xcb_window_t window)
}
reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, conn->xcb_connection(),
- false, window, conn->atom(QXcbAtom::WM_NAME),
+ false, window, conn->atom(QXcbAtom::AtomWM_NAME),
XCB_ATOM_STRING, 0, 1024);
if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) {
const char *name = reinterpret_cast<const char *>(xcb_get_property_value(reply.get()));
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 54a96a7a0a..0c047d569b 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -6,6 +6,8 @@
#include <qpa/qplatformwindow.h>
#include <qpa/qplatformwindow_p.h>
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
#include <QtGui/QSurfaceFormat>
#include <QtGui/QImage>
@@ -20,9 +22,10 @@ class QXcbScreen;
class QXcbSyncWindowRequest;
class QIcon;
-class Q_XCB_EXPORT QXcbWindow : public QXcbObject, public QXcbWindowEventListener, public QPlatformWindow
+class Q_XCB_EXPORT QXcbWindow : public QObject, public QXcbObject, public QXcbWindowEventListener, public QPlatformWindow
, public QNativeInterface::Private::QXcbWindow
{
+ Q_OBJECT
public:
enum NetWmState {
NetWmStateAbove = 0x1,
@@ -118,6 +121,8 @@ public:
Qt::KeyboardModifiers modifiers, QEvent::Type type, Qt::MouseEventSource source);
void updateNetWmUserTime(xcb_timestamp_t timestamp);
+ void updateWmTransientFor();
+ void registerWmTransientForChild(QXcbWindow *);
WindowTypes wmWindowTypes() const;
void setWmWindowType(WindowTypes types, Qt::WindowFlags flags);
@@ -217,6 +222,7 @@ protected:
Qt::WindowStates m_windowState = Qt::WindowNoState;
+ QMutex m_mappedMutex;
bool m_mapped = false;
bool m_transparent = false;
bool m_deferredActivation = false;
@@ -224,6 +230,7 @@ protected:
bool m_alertState = false;
bool m_minimized = false;
bool m_trayIconWindow = false;
+ bool m_ignorePressedWindowOnMouseLeave = false;
xcb_window_t m_netWmUserTimeWindow = XCB_NONE;
QSurfaceFormat m_format;
@@ -253,13 +260,14 @@ protected:
qreal m_sizeHintsScaleFactor = 1.0;
RecreationReasons m_recreationReasons = RecreationNotNeeded;
+
+ QList<QPointer<QXcbWindow>> m_wmTransientForChildren;
};
class QXcbForeignWindow : public QXcbWindow
{
public:
- QXcbForeignWindow(QWindow *window, WId nativeHandle)
- : QXcbWindow(window) { m_window = nativeHandle; }
+ QXcbForeignWindow(QWindow *window, WId nativeHandle);
~QXcbForeignWindow();
bool isForeignWindow() const override { return true; }
diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
index 50e85c0aa5..0e3c470c89 100644
--- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp
+++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
@@ -30,7 +30,7 @@ void QXcbWMSupport::updateNetWMAtoms()
int offset = 0;
int remaining = 0;
do {
- auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, root, atom(QXcbAtom::_NET_SUPPORTED), XCB_ATOM_ATOM, offset, 1024);
+ auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, root, atom(QXcbAtom::Atom_NET_SUPPORTED), XCB_ATOM_ATOM, offset, 1024);
if (!reply)
break;
@@ -54,7 +54,7 @@ void QXcbWMSupport::updateVirtualRoots()
{
net_virtual_roots.clear();
- if (!isSupportedByWM(atom(QXcbAtom::_NET_VIRTUAL_ROOTS)))
+ if (!isSupportedByWM(atom(QXcbAtom::Atom_NET_VIRTUAL_ROOTS)))
return;
xcb_window_t root = connection()->primaryScreen()->root();
@@ -62,7 +62,7 @@ void QXcbWMSupport::updateVirtualRoots()
int remaining = 0;
do {
auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
- false, root, atom(QXcbAtom::_NET_VIRTUAL_ROOTS), XCB_ATOM_WINDOW, offset, 1024);
+ false, root, atom(QXcbAtom::Atom_NET_VIRTUAL_ROOTS), XCB_ATOM_WINDOW, offset, 1024);
if (!reply)
break;
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp
index 62fd13e5b9..6b62864add 100644
--- a/src/plugins/platforms/xcb/qxcbxsettings.cpp
+++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp
@@ -68,7 +68,7 @@ public:
int offset = 0;
QByteArray settings;
- xcb_atom_t _xsettings_atom = screen->connection()->atom(QXcbAtom::_XSETTINGS_SETTINGS);
+ xcb_atom_t _xsettings_atom = screen->connection()->atom(QXcbAtom::Atom_XSETTINGS_SETTINGS);
while (1) {
auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property,
screen->xcb_connection(),
@@ -104,7 +104,7 @@ public:
void populateSettings(const QByteArray &xSettings)
{
- if (xSettings.length() < 12)
+ if (xSettings.size() < 12)
return;
char byteOrder = xSettings.at(0);
if (byteOrder != XCB_IMAGE_ORDER_LSB_FIRST && byteOrder != XCB_IMAGE_ORDER_MSB_FIRST) {
@@ -192,7 +192,7 @@ QXcbXSettings::QXcbXSettings(QXcbVirtualDesktop *screen)
auto atom_reply = Q_XCB_REPLY(xcb_intern_atom,
screen->xcb_connection(),
true,
- settings_atom_for_screen.length(),
+ settings_atom_for_screen.size(),
settings_atom_for_screen.constData());
if (!atom_reply)
return;