diff options
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r-- | src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri | 4 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 74 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 15 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbcursor.cpp | 9 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbcursor.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbintegration.cpp | 11 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbintegration.h | 3 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbkeyboard.cpp | 1 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 3 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbscreen.cpp | 95 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbscreen.h | 41 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 226 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.h | 12 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwmsupport.cpp | 12 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbxsettings.cpp | 10 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbxsettings.h | 4 |
16 files changed, 365 insertions, 157 deletions
diff --git a/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri b/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri index 8c60268e0d..e859865687 100644 --- a/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri +++ b/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri @@ -29,8 +29,8 @@ CONFIG += qpa/genericunixfontdatabase contains(QT_CONFIG, xcb-qt) { DEFINES += XCB_USE_RENDER - XCB_DIR = ../../../3rdparty/xcb - INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/sysinclude + XCB_DIR = $$clean_path($$PWD/../../../../3rdparty/xcb) + INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/include/xcb $$XCB_DIR/sysinclude LIBS += -lxcb -L$$OUT_PWD/xcb-static -lxcb-static } else { LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 706b9c8e48..8500aa1ffa 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -66,6 +66,7 @@ #include <X11/Xlib.h> #include <X11/Xlib-xcb.h> #include <X11/Xlibint.h> +#include <X11/Xutil.h> #endif #if defined(XCB_USE_XINPUT2) @@ -83,6 +84,12 @@ Q_LOGGING_CATEGORY(lcQpaXInput, "qt.qpa.input") Q_LOGGING_CATEGORY(lcQpaXInputDevices, "qt.qpa.input.devices") Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen") +// this event type was added in libxcb 1.10, +// but we support also older version +#ifndef XCB_GE_GENERIC +#define XCB_GE_GENERIC 35 +#endif + #ifdef XCB_USE_XLIB static const char * const xcbConnectionErrors[] = { "No error", /* Error 0 */ @@ -137,7 +144,7 @@ QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_ran return 0; } -QXcbScreen* QXcbConnection::createScreen(int screenNumber, xcb_screen_t* xcbScreen, +QXcbScreen* QXcbConnection::createScreen(QXcbVirtualDesktop* virtualDesktop, xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output) { @@ -150,10 +157,10 @@ QXcbScreen* QXcbConnection::createScreen(int screenNumber, xcb_screen_t* xcbScre int dotPos = displayName.lastIndexOf('.'); if (dotPos != -1) displayName.truncate(dotPos); - name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(screenNumber); + name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(virtualDesktop->number()); } - return new QXcbScreen(this, xcbScreen, outputId, output, name, screenNumber); + return new QXcbScreen(this, virtualDesktop, outputId, output, name); } bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output) @@ -173,15 +180,11 @@ bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_out return isPrimary; } -xcb_screen_t* QXcbConnection::xcbScreenForRootWindow(xcb_window_t rootWindow, int *xcbScreenNumber) +QXcbVirtualDesktop* QXcbConnection::virtualDesktopForRootWindow(xcb_window_t rootWindow) { - xcb_screen_iterator_t xcbScreenIter = xcb_setup_roots_iterator(m_setup); - for (; xcbScreenIter.rem; xcb_screen_next(&xcbScreenIter)) { - if (xcbScreenIter.data->root == rootWindow) { - if (xcbScreenNumber) - *xcbScreenNumber = xcb_setup_roots_length(m_setup) - xcbScreenIter.rem; - return xcbScreenIter.data; - } + foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) { + if (virtualDesktop->screen()->root == rootWindow) + return virtualDesktop; } return 0; @@ -194,8 +197,8 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) { if (event->subCode == XCB_RANDR_NOTIFY_CRTC_CHANGE) { xcb_randr_crtc_change_t crtc = event->u.cc; - xcb_screen_t *xcbScreen = xcbScreenForRootWindow(crtc.window); - if (!xcbScreen) + QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(crtc.window); + if (!virtualDesktop) // Not for us return; @@ -212,9 +215,8 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) } else if (event->subCode == XCB_RANDR_NOTIFY_OUTPUT_CHANGE) { xcb_randr_output_change_t output = event->u.oc; - int xcbScreenNumber = 0; - xcb_screen_t *xcbScreen = xcbScreenForRootWindow(output.window, &xcbScreenNumber); - if (!xcbScreen) + QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(output.window); + if (!virtualDesktop) // Not for us return; @@ -242,7 +244,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo( xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL)); - screen = createScreen(xcbScreenNumber, xcbScreen, output.output, outputInfo.data()); + screen = createScreen(virtualDesktop, output.output, outputInfo.data()); qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled"; screen->setPrimary(checkOutputIsPrimary(output.window, output.output)); @@ -293,14 +295,15 @@ void QXcbConnection::initializeScreens() xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); int xcbScreenNumber = 0; // screen number in the xcb sense QXcbScreen* primaryScreen = Q_NULLPTR; - xcb_screen_t *xcbScreen = Q_NULLPTR; bool hasOutputs = false; while (it.rem) { // Each "screen" in xcb terminology is a virtual desktop, // potentially a collection of separate juxtaposed monitors. // But we want a separate QScreen for each output (e.g. DVI-I-1, VGA-1, etc.) // which will become virtual siblings. - xcbScreen = it.data; + xcb_screen_t *xcbScreen = it.data; + QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber); + m_virtualDesktops.append(virtualDesktop); QList<QPlatformScreen *> siblings; int outputCount = 0; int connectedOutputCount = 0; @@ -370,7 +373,7 @@ void QXcbConnection::initializeScreens() continue; } - QXcbScreen *screen = createScreen(xcbScreenNumber, xcbScreen, outputs[i], output.data()); + QXcbScreen *screen = createScreen(virtualDesktop, outputs[i], output.data()); siblings << screen; ++connectedOutputCount; hasOutputs = true; @@ -405,8 +408,9 @@ void QXcbConnection::initializeScreens() // but the dimensions are known anyway, and we don't already have any lingering // (possibly disconnected) screens, then showing windows should be possible, // so create one screen. (QTBUG-31389) - if (xcbScreen && !hasOutputs && xcbScreen->width_in_pixels > 0 && xcbScreen->height_in_pixels > 0 && m_screens.isEmpty()) { - QXcbScreen *screen = createScreen(0, xcbScreen, 0, Q_NULLPTR); + QXcbVirtualDesktop *virtualDesktop = m_virtualDesktops.value(0); + if (virtualDesktop && !hasOutputs && !virtualDesktop->size().isEmpty() && m_screens.isEmpty()) { + QXcbScreen *screen = createScreen(virtualDesktop, 0, Q_NULLPTR); screen->setVirtualSiblings(QList<QPlatformScreen *>() << screen); m_screens << screen; primaryScreen = screen; @@ -434,9 +438,10 @@ void QXcbConnection::initializeScreens() qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name(); } -QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName) +QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName) : m_connection(0) , m_canGrabServer(canGrabServer) + , m_defaultVisualId(defaultVisualId) , m_primaryScreenNumber(0) , m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY")) , m_nativeInterface(nativeInterface) @@ -577,6 +582,9 @@ QXcbConnection::~QXcbConnection() while (!m_screens.isEmpty()) integration->destroyScreen(m_screens.takeLast()); + while (!m_virtualDesktops.isEmpty()) + delete m_virtualDesktops.takeLast(); + delete m_glIntegration; #ifdef XCB_USE_XLIB @@ -666,6 +674,7 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event) PRINT_XCB_EVENT(XCB_KEYMAP_NOTIFY); PRINT_XCB_EVENT(XCB_EXPOSE); PRINT_XCB_EVENT(XCB_GRAPHICS_EXPOSURE); + PRINT_XCB_EVENT(XCB_NO_EXPOSURE); PRINT_XCB_EVENT(XCB_VISIBILITY_NOTIFY); PRINT_XCB_EVENT(XCB_CREATE_NOTIFY); PRINT_XCB_EVENT(XCB_DESTROY_NOTIFY); @@ -685,6 +694,8 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event) PRINT_XCB_EVENT(XCB_SELECTION_NOTIFY); PRINT_XCB_EVENT(XCB_COLORMAP_NOTIFY); PRINT_XCB_EVENT(XCB_CLIENT_MESSAGE); + PRINT_XCB_EVENT(XCB_MAPPING_NOTIFY); + PRINT_XCB_EVENT(XCB_GE_GENERIC); default: qDebug("QXcbConnection: %s: unknown event - response_type: %d - sequence: %d", message, int(event->response_type & ~0x80), int(event->sequence)); } @@ -1080,7 +1091,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent); break; #if defined(XCB_USE_XINPUT2) - case GenericEvent: + case XCB_GE_GENERIC: if (m_xi2Enabled) xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(event)); break; @@ -1342,6 +1353,21 @@ void *QXcbConnection::xlib_display() const { return m_xlib_display; } + +void *QXcbConnection::createVisualInfoForDefaultVisualId() const +{ + if (m_defaultVisualId == UINT_MAX) + return 0; + XVisualInfo info; + memset(&info, 0, sizeof info); + info.visualid = m_defaultVisualId; + + int count = 0; + XVisualInfo *retVisual = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &info, &count); + Q_ASSERT(count < 2); + return retVisual; +} + #endif void QXcbConnection::processXcbEvents() diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 1190e7c2b0..466492ce42 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -80,6 +80,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaXInput) Q_DECLARE_LOGGING_CATEGORY(lcQpaXInputDevices) Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen) +class QXcbVirtualDesktop; class QXcbScreen; class QXcbWindow; class QXcbDrag; @@ -369,7 +370,7 @@ class Q_XCB_EXPORT QXcbConnection : public QObject { Q_OBJECT public: - QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName = 0); + QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName = 0); ~QXcbConnection(); QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); } @@ -399,8 +400,13 @@ public: QXcbWMSupport *wmSupport() const { return m_wmSupport.data(); } xcb_window_t rootWindow(); + + bool hasDefaultVisualId() const { return m_defaultVisualId != UINT_MAX; } + xcb_visualid_t defaultVisualId() const { return m_defaultVisualId; } + #ifdef XCB_USE_XLIB void *xlib_display() const; + void *createVisualInfoForDefaultVisualId() const; #endif #if defined(XCB_USE_XINPUT2) @@ -497,12 +503,12 @@ private: void initializeXShape(); void initializeXKB(); void handleClientMessageEvent(const xcb_client_message_event_t *event); - QXcbScreen* createScreen(int screenNumber, xcb_screen_t* xcbScreen, + QXcbScreen* createScreen(QXcbVirtualDesktop *virtualDesktop, xcb_randr_output_t outputId = XCB_NONE, xcb_randr_get_output_info_reply_t *output = 0); QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc); QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output); - xcb_screen_t* xcbScreenForRootWindow(xcb_window_t rootWindow, int *xcbScreenNumber = 0); + QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow); bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output); void initializeScreens(); void updateScreens(const xcb_randr_notify_event_t *event); @@ -566,7 +572,9 @@ private: xcb_connection_t *m_connection; const xcb_setup_t *m_setup; bool m_canGrabServer; + xcb_visualid_t m_defaultVisualId; + QList<QXcbVirtualDesktop *> m_virtualDesktops; QList<QXcbScreen *> m_screens; int m_primaryScreenNumber; @@ -633,6 +641,7 @@ private: }; #define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display())) +#define CREATE_VISUALINFO_FROM_DEFAULT_VISUALID(object) ((XVisualInfo *)(object->connection()->createVisualInfoForDefaultVisualId())) template<typename T> xcb_generic_event_t *QXcbConnection::checkEvent(T &checker) diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index 8dd27ec9c5..e51ab85e30 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -502,7 +502,7 @@ bool updateCursorTheme(void *dpy, const QByteArray &theme) { return setTheme; } - void QXcbCursor::cursorThemePropertyChanged(QXcbScreen *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); @@ -633,18 +633,17 @@ void QXcbCursor::queryPointer(QXcbConnection *c, xcb_window_t *rootWin, QPoint * QPoint QXcbCursor::pos() const { - const int dpr = int(m_screen->devicePixelRatio()); QPoint p; queryPointer(connection(), 0, &p); - return p / dpr; + return m_screen->mapFromNative(p); } void QXcbCursor::setPos(const QPoint &pos) { - const int dpr = int(m_screen->devicePixelRatio()); + const QPoint xPos = m_screen->mapToNative(pos); xcb_window_t root = 0; queryPointer(connection(), &root, 0); - xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, pos.x()*dpr, pos.y()*dpr); + xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, xPos.x(), xPos.y()); xcb_flush(xcb_connection()); } diff --git a/src/plugins/platforms/xcb/qxcbcursor.h b/src/plugins/platforms/xcb/qxcbcursor.h index 1280c7e042..7e5cdc6870 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.h +++ b/src/plugins/platforms/xcb/qxcbcursor.h @@ -91,7 +91,7 @@ private: CursorHash m_cursorHash; #endif #ifdef XCB_USE_XLIB - static void cursorThemePropertyChanged(QXcbScreen *screen, + static void cursorThemePropertyChanged(QXcbVirtualDesktop *screen, const QByteArray &name, const QVariant &property, void *handle); diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 2547e537a7..fc06f1a7b0 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -116,6 +116,7 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char : m_services(new QGenericUnixServices) , m_instanceName(0) , m_canGrab(true) + , m_defaultVisualId(UINT_MAX) { m_instance = this; @@ -143,6 +144,12 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char noGrabArg = true; else if (arg == "-dograb") doGrabArg = true; + else if (arg == "-visual" && i < argc - 1) { + bool ok = false; + m_defaultVisualId = QByteArray(argv[++i]).toUInt(&ok, 0); + if (!ok) + m_defaultVisualId = UINT_MAX; + } else argv[j++] = argv[i]; } @@ -167,12 +174,12 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char if (canNotGrabEnv) m_canGrab = false; - m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, displayName); + m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, m_defaultVisualId, displayName); for (int i = 0; i < parameters.size() - 1; i += 2) { qCDebug(lcQpaScreen) << "connecting to additional display: " << parameters.at(i) << parameters.at(i+1); QString display = parameters.at(i) + QLatin1Char(':') + parameters.at(i+1); - m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, display.toLatin1().constData()); + m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, m_defaultVisualId, display.toLatin1().constData()); } m_fontDatabase.reset(new QGenericUnixFontDatabase()); diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index 4212d53810..4e2a3c2bbd 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -39,6 +39,8 @@ #include "qxcbexport.h" +#include <xcb/xcb.h> + QT_BEGIN_NAMESPACE class QXcbConnection; @@ -123,6 +125,7 @@ private: mutable QByteArray m_wmClass; const char *m_instanceName; bool m_canGrab; + xcb_visualid_t m_defaultVisualId; static QXcbIntegration *m_instance; }; diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 6c80c1b30e..5a7c2cef83 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -437,6 +437,7 @@ static const unsigned int KeyTbl[] = { XF86XK_AudioPrev, Qt::Key_MediaPrevious, XF86XK_AudioNext, Qt::Key_MediaNext, XF86XK_AudioRecord, Qt::Key_MediaRecord, + XF86XK_AudioPause, Qt::Key_MediaPause, XF86XK_Mail, Qt::Key_LaunchMail, XF86XK_MyComputer, Qt::Key_Launch0, // ### Qt 6: remap properly XF86XK_Calculator, Qt::Key_Launch1, diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 75ffaa37bb..1629f3013c 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -361,6 +361,9 @@ QFunctionPointer QXcbNativeInterface::platformFunction(const QByteArray &functio if (function == QXcbIntegrationFunctions::xEmbedSystemTrayVisualHasAlphaChannelIdentifier()) return QFunctionPointer(QXcbIntegrationFunctions::XEmbedSystemTrayVisualHasAlphaChannel(QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel)); + if (function == QXcbWindowFunctions::visualIdIdentifier()) { + return QFunctionPointer(QXcbWindowFunctions::VisualId(QXcbWindow::visualIdStatic)); + } return Q_NULLPTR; } diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 383adf9734..a0d6d88d11 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -47,11 +47,33 @@ QT_BEGIN_NAMESPACE -QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, +QXcbVirtualDesktop::QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t *screen, int number) + : QXcbObject(connection) + , m_screen(screen) + , m_number(number) + , m_xSettings(Q_NULLPTR) +{ +} + +QXcbVirtualDesktop::~QXcbVirtualDesktop() +{ + delete m_xSettings; +} + +QXcbXSettings *QXcbVirtualDesktop::xSettings() const +{ + if (!m_xSettings) { + QXcbVirtualDesktop *self = const_cast<QXcbVirtualDesktop *>(this); + self->m_xSettings = new QXcbXSettings(self); + } + return m_xSettings; +} + +QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop, xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output, - QString outputName, int number) + QString outputName) : QXcbObject(connection) - , m_screen(scr) + , m_virtualDesktop(virtualDesktop) , m_output(outputId) , m_crtc(output ? output->crtc : 0) , m_mode(XCB_NONE) @@ -59,10 +81,9 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, , m_rotation(XCB_RANDR_ROTATION_ROTATE_0) , m_outputName(outputName) , m_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize()) - , m_virtualSize(scr->width_in_pixels, scr->height_in_pixels) - , m_virtualSizeMillimeters(scr->width_in_millimeters, scr->height_in_millimeters) + , m_virtualSize(virtualDesktop->size()) + , m_virtualSizeMillimeters(virtualDesktop->physicalSize()) , m_orientation(Qt::PrimaryOrientation) - , m_number(number) , m_refreshRate(60) , m_forcedDpi(-1) , m_devicePixelRatio(1) @@ -70,7 +91,6 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, , m_noFontHinting(false) , m_subpixelType(QFontEngine::SubpixelAntialiasingType(-1)) , m_antialiasingEnabled(-1) - , m_xSettings(0) { if (connection->hasXRandr()) { xcb_randr_select_input(xcb_connection(), screen()->root, true); @@ -215,7 +235,7 @@ QXcbScreen::~QXcbScreen() QWindow *QXcbScreen::topLevelAt(const QPoint &p) const { - xcb_window_t root = m_screen->root; + xcb_window_t root = screen()->root; int dpr = int(devicePixelRatio()); int x = p.x() / dpr; @@ -253,6 +273,31 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const return 0; } + +QPoint QXcbScreen::mapToNative(const QPoint &pos) const +{ + const int dpr = int(devicePixelRatio()); + return (pos - m_geometry.topLeft()) * dpr + m_nativeGeometry.topLeft(); +} + +QPoint QXcbScreen::mapFromNative(const QPoint &pos) const +{ + const int dpr = int(devicePixelRatio()); + return (pos - m_nativeGeometry.topLeft()) / dpr + m_geometry.topLeft(); +} + +QRect QXcbScreen::mapToNative(const QRect &rect) const +{ + const int dpr = int(devicePixelRatio()); + return QRect(mapToNative(rect.topLeft()), rect.size() * dpr); +} + +QRect QXcbScreen::mapFromNative(const QRect &rect) const +{ + const int dpr = int(devicePixelRatio()); + return QRect(mapFromNative(rect.topLeft()), rect.size() / dpr); +} + void QXcbScreen::windowShown(QXcbWindow *window) { // Freedesktop.org Startup Notification @@ -310,19 +355,16 @@ QImage::Format QXcbScreen::format() const QDpi QXcbScreen::logicalDpi() const { - int dpr = int(devicePixelRatio()); - - if (m_forcedDpi > 0) - return QDpi(m_forcedDpi/dpr, m_forcedDpi/dpr); + static const int overrideDpi = qEnvironmentVariableIntValue("QT_FONT_DPI"); + if (overrideDpi) + return QDpi(overrideDpi, overrideDpi); - static const bool auto_dpr = qgetenv("QT_DEVICE_PIXEL_RATIO").toLower() == "auto"; - if (auto_dpr) { - return QDpi(Q_MM_PER_INCH * m_geometry.width() / m_sizeMillimeters.width(), - Q_MM_PER_INCH * m_geometry.height() / m_sizeMillimeters.height()); - } else { - return QDpi(Q_MM_PER_INCH * m_virtualSize.width() / m_virtualSizeMillimeters.width() / dpr, - Q_MM_PER_INCH * m_virtualSize.height() / m_virtualSizeMillimeters.height() / dpr); + if (m_forcedDpi > 0) { + int primaryDpr = int(connection()->screens().at(0)->devicePixelRatio()); + return QDpi(m_forcedDpi/primaryDpr, m_forcedDpi/primaryDpr); } + return QDpi(Q_MM_PER_INCH * m_virtualSize.width() / m_virtualSizeMillimeters.width(), + Q_MM_PER_INCH * m_virtualSize.height() / m_virtualSizeMillimeters.height()); } @@ -426,6 +468,9 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp) { + if (!connection()->hasXRandr()) + return; + xcb_randr_get_crtc_info_cookie_t crtcCookie = xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, timestamp); xcb_randr_get_crtc_info_reply_t *crtc = @@ -482,9 +527,9 @@ void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation) qreal dpi = xGeometry.width() / physicalSize().width() * qreal(25.4); m_devicePixelRatio = qRound(dpi/96); const int dpr = int(devicePixelRatio()); // we may override m_devicePixelRatio - m_geometry = QRect(xGeometry.topLeft()/dpr, xGeometry.size()/dpr); + m_geometry = QRect(xGeometry.topLeft(), xGeometry.size()/dpr); m_nativeGeometry = QRect(xGeometry.topLeft(), xGeometry.size()); - m_availableGeometry = QRect(xAvailableGeometry.topLeft()/dpr, xAvailableGeometry.size()/dpr); + m_availableGeometry = QRect(mapFromNative(xAvailableGeometry.topLeft()), xAvailableGeometry.size()/dpr); QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry); } @@ -499,7 +544,7 @@ void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode) // we can safely use get_screen_resources_current here, because in order to // get here, we must have called get_screen_resources before xcb_randr_get_screen_resources_current_cookie_t resourcesCookie = - xcb_randr_get_screen_resources_current_unchecked(xcb_connection(), m_screen->root); + xcb_randr_get_screen_resources_current_unchecked(xcb_connection(), screen()->root); xcb_randr_get_screen_resources_current_reply_t *resources = xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, NULL); if (resources) { @@ -710,11 +755,7 @@ void QXcbScreen::readXResources() QXcbXSettings *QXcbScreen::xSettings() const { - if (!m_xSettings) { - QXcbScreen *self = const_cast<QXcbScreen *>(this); - self->m_xSettings = new QXcbXSettings(self); - } - return m_xSettings; + return m_virtualDesktop->xSettings(); } static inline void formatRect(QDebug &debug, const QRect r) diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index 3f228465f2..a29efc1e79 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -54,12 +54,32 @@ class QXcbXSettings; class QDebug; #endif +class QXcbVirtualDesktop : public QXcbObject +{ +public: + QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t *screen, int number); + ~QXcbVirtualDesktop(); + + xcb_screen_t *screen() const { return m_screen; } + int number() const { return m_number; } + QSize size() const { return QSize(m_screen->width_in_pixels, m_screen->height_in_pixels); } + QSize physicalSize() const { return QSize(m_screen->width_in_millimeters, m_screen->height_in_millimeters); } + + QXcbXSettings *xSettings() const; + +private: + xcb_screen_t *m_screen; + int m_number; + + QXcbXSettings *m_xSettings; +}; + class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen { public: - QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, + QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop, xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output, - QString outputName, int number); + QString outputName); ~QXcbScreen(); QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE; @@ -69,7 +89,7 @@ public: QRect geometry() const Q_DECL_OVERRIDE { return m_geometry; } QRect nativeGeometry() const { return m_nativeGeometry; } QRect availableGeometry() const Q_DECL_OVERRIDE {return m_availableGeometry;} - int depth() const Q_DECL_OVERRIDE { return m_screen->root_depth; } + int depth() const Q_DECL_OVERRIDE { return screen()->root_depth; } QImage::Format format() const Q_DECL_OVERRIDE; QSizeF physicalSize() const Q_DECL_OVERRIDE { return m_sizeMillimeters; } QSize virtualSize() const { return m_virtualSize; } @@ -87,10 +107,10 @@ public: void setPrimary(bool primary) { m_primary = primary; } bool isPrimary() const { return m_primary; } - int screenNumber() const { return m_number; } + int screenNumber() const { return m_virtualDesktop->number(); } - xcb_screen_t *screen() const { return m_screen; } - xcb_window_t root() const { return m_screen->root; } + xcb_screen_t *screen() const { return m_virtualDesktop->screen(); } + xcb_window_t root() const { return screen()->root; } xcb_randr_output_t output() const { return m_output; } xcb_randr_crtc_t crtc() const { return m_crtc; } xcb_randr_mode_t mode() const { return m_mode; } @@ -120,13 +140,18 @@ public: QXcbXSettings *xSettings() const; + QPoint mapToNative(const QPoint &pos) const; + QPoint mapFromNative(const QPoint &pos) const; + QRect mapToNative(const QRect &rect) const; + QRect mapFromNative(const QRect &rect) const; + private: static bool xResource(const QByteArray &identifier, const QByteArray &expectedIdentifier, QByteArray &stringValue); void sendStartupMessage(const QByteArray &message) const; - xcb_screen_t *m_screen; + QXcbVirtualDesktop *m_virtualDesktop; xcb_randr_output_t m_output; xcb_randr_crtc_t m_crtc; xcb_randr_mode_t m_mode; @@ -143,7 +168,6 @@ private: QSizeF m_virtualSizeMillimeters; QList<QPlatformScreen *> m_siblings; Qt::ScreenOrientation m_orientation; - int m_number; QString m_windowManagerName; bool m_syncRequestSupported; xcb_window_t m_clientLeader; @@ -157,7 +181,6 @@ private: bool m_noFontHinting; QFontEngine::SubpixelAntialiasingType m_subpixelType; int m_antialiasingEnabled; - QXcbXSettings *m_xSettings; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index ceb95a1515..076cc1aa80 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -139,7 +139,7 @@ enum QX11EmbedMessageType { const quint32 XEMBED_VERSION = 0; -static inline QRect mapToNative(const QRect &qtRect, int dpr) +static inline QRect mapLocalGeometryToNative(const QRect &qtRect, int dpr) { return QRect(qtRect.x() * dpr, qtRect.y() * dpr, qtRect.width() * dpr, qtRect.height() * dpr); } @@ -167,11 +167,45 @@ static inline QRect mapExposeFromNative(const QRect &xRect, int dpr) return QRect(dpr_floor(xRect.topLeft(), dpr), dpr_ceil(xRect.bottomRight(), dpr)); } -static inline QRect mapGeometryFromNative(const QRect &xRect, int dpr) +static inline QRect mapLocalGeometryFromNative(const QRect &xRect, int dpr) { return QRect(xRect.topLeft() / dpr, dpr_ceil(xRect.size(), dpr)); } +QXcbScreen *QXcbWindow::parentScreen() +{ + return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : m_xcbScreen; +} + +QPoint QXcbWindow::mapToNative(const QPoint &pos, const QXcbScreen *screen) const +{ + if (parent()) + return pos * int(screen->devicePixelRatio()); + else + return screen->mapToNative(pos); +} +QPoint QXcbWindow::mapFromNative(const QPoint &pos, const QXcbScreen *screen) const +{ + if (parent()) + return pos / int(screen->devicePixelRatio()); + else + return screen->mapFromNative(pos); +} +QRect QXcbWindow::mapToNative(const QRect &rect, const QXcbScreen *screen) const +{ + if (parent()) + return mapLocalGeometryToNative(rect, int(screen->devicePixelRatio())); + else + return screen->mapToNative(rect); +} +QRect QXcbWindow::mapFromNative(const QRect &rect, const QXcbScreen *screen) const +{ + if (parent()) + return mapLocalGeometryFromNative(rect, int(screen->devicePixelRatio())); + else + return screen->mapFromNative(rect); +} + // Returns \c true if we should set WM_TRANSIENT_FOR on \a w static inline bool isTransient(const QWindow *w) { @@ -292,6 +326,7 @@ static const char *wm_window_type_property_id = "_q_xcb_wm_window_type"; QXcbWindow::QXcbWindow(QWindow *window) : QPlatformWindow(window) , m_window(0) + , m_xcbScreen(0) , m_syncCounter(0) , m_gravity(XCB_GRAVITY_STATIC) , m_mapped(false) @@ -345,13 +380,25 @@ void QXcbWindow::create() Qt::WindowType type = window()->type(); - QXcbScreen *platformScreen = xcbScreen(); + QXcbScreen *currentScreen = xcbScreen(); + QRect rect = window()->geometry(); + QXcbScreen *platformScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect)); + m_xcbScreen = platformScreen; if (type == Qt::Desktop) { m_window = platformScreen->root(); m_depth = platformScreen->screen()->root_depth; m_visualId = platformScreen->screen()->root_visual; - const xcb_visualtype_t *visual = platformScreen->visualForId(m_visualId); + const xcb_visualtype_t *visual = 0; + if (connection()->hasDefaultVisualId()) { + visual = platformScreen->visualForId(connection()->defaultVisualId()); + if (visual) + m_visualId = connection()->defaultVisualId(); + if (!visual) + qWarning() << "Could not use default visual id. Falling back to root_visual for screen."; + } + if (!visual) + visual = platformScreen->visualForId(m_visualId); m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap); connection()->addWindowEventListener(m_window, this); return; @@ -372,13 +419,10 @@ void QXcbWindow::create() // Parameters to XCreateWindow() are frame corner + inner size. // This fits in case position policy is frame inclusive. There is // currently no way to implement it for frame-exclusive geometries. - QRect rect = window()->geometry(); QPlatformWindow::setGeometry(rect); - QXcbScreen *currentScreen = xcbScreen(); - QPlatformScreen *newScreen = screenForGeometry(rect); - if (newScreen != currentScreen) - QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + if (platformScreen != currentScreen) + QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen()); const int dpr = int(devicePixelRatio()); @@ -408,7 +452,12 @@ void QXcbWindow::create() #ifdef XCB_USE_XLIB if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) { - XVisualInfo *visualInfo = static_cast<XVisualInfo *>(createVisual()); + XVisualInfo *visualInfo = Q_NULLPTR; + if (connection()->hasDefaultVisualId()) + visualInfo = CREATE_VISUALINFO_FROM_DEFAULT_VISUALID(this); + if (!visualInfo) + visualInfo = static_cast<XVisualInfo *>(createVisual()); + if (!visualInfo && window()->surfaceType() == QSurface::OpenGLSurface) qFatal("Could not initialize OpenGL"); @@ -429,7 +478,7 @@ void QXcbWindow::create() m_visualId = visualInfo->visualid; - const QRect xRect = mapToNative(rect, dpr); + const QRect xRect = mapToNative(rect, platformScreen); m_window = XCreateWindow(DISPLAY_FROM_XCB(this), xcb_parent_id, xRect.x(), xRect.y(), xRect.width(), xRect.height(), 0, visualInfo->depth, InputOutput, visualInfo->visual, @@ -443,45 +492,60 @@ void QXcbWindow::create() if (!m_window) { m_window = xcb_generate_id(xcb_connection()); - m_visualId = platformScreen->screen()->root_visual; + m_visualId = UINT_MAX; + const xcb_visualtype_t *visual = Q_NULLPTR; m_depth = platformScreen->screen()->root_depth; uint32_t mask = 0; uint32_t values[3]; - if (m_format.alphaBufferSize() == 8) { - xcb_depth_iterator_t depthIter = xcb_screen_allowed_depths_iterator(platformScreen->screen()); - while (depthIter.rem) { - if (depthIter.data->depth == 32) { - xcb_visualtype_iterator_t visualIter = xcb_depth_visuals_iterator(depthIter.data); - if (visualIter.rem) { - m_visualId = visualIter.data->visual_id; - m_depth = 32; - uint32_t colormap = xcb_generate_id(xcb_connection()); - xcb_create_colormap(xcb_connection(), XCB_COLORMAP_ALLOC_NONE, colormap, - xcb_parent_id, m_visualId); - mask |= XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP; - values[0] = platformScreen->screen()->white_pixel; - values[1] = platformScreen->screen()->black_pixel; - values[2] = colormap; - break; + if (connection()->hasDefaultVisualId()) { + m_visualId = connection()->defaultVisualId(); + visual = platformScreen->visualForId(m_visualId); + } + + if (!visual) { + if (connection()->hasDefaultVisualId()) + qWarning("Failed to use default visual id. Falling back to using screens root_visual"); + + m_visualId = platformScreen->screen()->root_visual; + + if (m_format.alphaBufferSize() == 8) { + xcb_depth_iterator_t depthIter = xcb_screen_allowed_depths_iterator(platformScreen->screen()); + while (depthIter.rem) { + if (depthIter.data->depth == 32) { + xcb_visualtype_iterator_t visualIter = xcb_depth_visuals_iterator(depthIter.data); + if (visualIter.rem) { + m_visualId = visualIter.data->visual_id; + m_depth = 32; + uint32_t colormap = xcb_generate_id(xcb_connection()); + xcb_create_colormap(xcb_connection(), XCB_COLORMAP_ALLOC_NONE, colormap, + xcb_parent_id, m_visualId); + mask |= XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP; + values[0] = platformScreen->screen()->white_pixel; + values[1] = platformScreen->screen()->black_pixel; + values[2] = colormap; + break; + } } + xcb_depth_next(&depthIter); } - xcb_depth_next(&depthIter); } + + visual = platformScreen->visualForId(m_visualId); } - const xcb_visualtype_t *visual = platformScreen->visualForId(m_visualId); m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap); + const QRect xRect = mapToNative(rect, platformScreen); Q_XCB_CALL(xcb_create_window(xcb_connection(), m_depth, m_window, // window id xcb_parent_id, // parent window id - rect.x(), - rect.y(), - rect.width(), - rect.height(), + xRect.x(), + xRect.y(), + xRect.width(), + xRect.height(), 0, // border width XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class m_visualId, // visual @@ -632,7 +696,7 @@ void QXcbWindow::destroy() void QXcbWindow::maybeSetScreen(QXcbScreen *screen) { - if (!window()->screen() && screen->geometry().contains(geometry().topLeft() * int(devicePixelRatio()))) { + if (!window()->screen() && screen->geometry().contains(geometry().topLeft())) { QWindowSystemInterface::handleWindowScreenChanged(window(), static_cast<QPlatformScreen *>(screen)->screen()); QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size()))); } @@ -645,16 +709,17 @@ void QXcbWindow::setGeometry(const QRect &rect) propagateSizeHints(); QXcbScreen *currentScreen = xcbScreen(); - QPlatformScreen *newScreen = screenForGeometry(rect); + QXcbScreen *newScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect)); + if (!newScreen) newScreen = currentScreen; - const QRect xRect = mapToNative(rect, int(newScreen->devicePixelRatio())); + m_xcbScreen = newScreen; + const QRect xRect = mapToNative(rect, newScreen); const QRect wmGeometry = windowToWmGeometry(xRect); - if (newScreen != currentScreen) - QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen()); if (qt_window_private(window())->positionAutomatic) { const quint32 mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; @@ -1161,6 +1226,8 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two) event.data.data32[3] = 0; event.data.data32[4] = 0; + if (!xcbScreen()) + return; Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); } @@ -1567,7 +1634,7 @@ void QXcbWindow::propagateSizeHints() memset(&hints, 0, sizeof(hints)); const int dpr = int(devicePixelRatio()); - const QRect xRect = mapToNative(windowToWmGeometry(geometry()), dpr); + const QRect xRect = windowToWmGeometry(mapToNative(geometry(), xcbScreen())); QWindow *win = window(); @@ -1660,6 +1727,13 @@ void QXcbWindow::setWindowIconTextStatic(QWindow *window, const QString &text) static_cast<QXcbWindow *>(window->handle())->setWindowIconText(text); } +uint QXcbWindow::visualIdStatic(QWindow *window) +{ + if (window && window->handle()) + return static_cast<QXcbWindow *>(window->handle())->visualId(); + return UINT_MAX; +} + QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const { QXcbWindowFunctions::WmWindowTypes result(0); @@ -1953,20 +2027,21 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even } } -// Temporary workaround for bug in QPlatformScreen::screenForNativeGeometry +// Temporary workaround for bug in QPlatformScreen::screenForGeometry // we need the native geometries to detect our screen, but that's not // available in cross-platform code. Will be fixed properly when highDPI // support is refactored to expose the native coordinate system. -QPlatformScreen *QXcbWindow::screenForNativeGeometry(const QRect &newGeometry) const +QXcbScreen *QXcbWindow::screenForNativeGeometry(const QRect &newGeometry) const { - QXcbScreen *currentScreen = static_cast<QXcbScreen*>(screen()); + QXcbScreen *currentScreen = xcbScreen(); if (!currentScreen && QGuiApplication::primaryScreen()) currentScreen = static_cast<QXcbScreen*>(QGuiApplication::primaryScreen()->handle()); if (currentScreen && !parent() && !currentScreen->nativeGeometry().intersects(newGeometry)) { Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) { - if (static_cast<QXcbScreen*>(screen)->nativeGeometry().intersects(newGeometry)) - return screen; + QXcbScreen *xcbScreen = static_cast<QXcbScreen*>(screen); + if (xcbScreen->nativeGeometry().intersects(newGeometry)) + return xcbScreen; } } return currentScreen; @@ -1988,23 +2063,19 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * } } - const int dpr = devicePixelRatio(); const QRect nativeRect = QRect(pos, QSize(event->width, event->height)); - const QRect rect = mapGeometryFromNative(nativeRect, dpr); + QXcbScreen *newScreen = parent() ? parentScreen() : screenForNativeGeometry(nativeRect); + + QXcbScreen *currentScreen = m_xcbScreen; + m_xcbScreen = newScreen; + if (!newScreen) + return; + const QRect rect = mapFromNative(nativeRect, newScreen); QPlatformWindow::setGeometry(rect); QWindowSystemInterface::handleGeometryChange(window(), rect); - QPlatformScreen *newScreen = screenForNativeGeometry(nativeRect); - if (newScreen != screen()) { - if (newScreen) - QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); - int newDpr = newScreen->devicePixelRatio(); - if (newDpr != dpr) { - QRect newRect = mapGeometryFromNative(nativeRect, newDpr); - QPlatformWindow::setGeometry(newRect); - QWindowSystemInterface::handleGeometryChange(window(), newRect); - } - } + if (newScreen != currentScreen) + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen()); m_configureNotifyPending = false; @@ -2045,12 +2116,12 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); if (reply) { - ret.setX(reply->dst_x / dpr); - ret.setY(reply->dst_y / dpr); + ret.setX(reply->dst_x); + ret.setY(reply->dst_y); free(reply); } - return ret; + return mapFromNative(ret, xcbScreen()); } QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const @@ -2060,9 +2131,10 @@ QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const const int dpr = int(devicePixelRatio()); QPoint ret; + QPoint xPos = mapToNative(pos, xcbScreen()); xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcbScreen()->root(), xcb_window(), - pos.x() *dpr, pos.y() * dpr); + xPos.x(), xPos.y()); xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); if (reply) { @@ -2116,7 +2188,7 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) } const int dpr = int(devicePixelRatio()); QPoint local(event->event_x/dpr, event->event_y/dpr); - QPoint global(event->root_x/dpr, event->root_y/dpr); + QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y)); Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); @@ -2141,7 +2213,7 @@ void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *even { const int dpr = int(devicePixelRatio()); QPoint local(event->event_x/dpr, event->event_y/dpr); - QPoint global(event->root_x/dpr, event->root_y/dpr); + QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y)); Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); if (event->detail >= 4 && event->detail <= 7) { @@ -2156,7 +2228,9 @@ void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event) { const int dpr = int(devicePixelRatio()); QPoint local(event->event_x/dpr, event->event_y/dpr); - QPoint global(event->root_x/dpr, event->root_y/dpr); + if (!xcbScreen()) + return; + QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y)); Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); handleMouseEvent(event->time, local, global, modifiers); @@ -2213,7 +2287,9 @@ void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event) const int dpr = int(devicePixelRatio()); const QPoint local(event->event_x/dpr, event->event_y/dpr); - const QPoint global(event->root_x/dpr, event->root_y/dpr); + if (!xcbScreen()) + return; + QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y)); QWindowSystemInterface::handleEnterEvent(window(), local, global); } @@ -2231,7 +2307,9 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event) if (enterWindow) { const int dpr = int(devicePixelRatio()); QPoint local(enter->event_x/dpr, enter->event_y/dpr); - QPoint global(enter->root_x/dpr, enter->root_y/dpr); + if (!xcbScreen()) + return; + QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y)); QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global); } else { @@ -2246,6 +2324,8 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev connection()->setTime(event->time); const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE; + if (!xcbScreen()) + return; if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) { if (propertyDeleted) @@ -2394,7 +2474,6 @@ void QXcbWindow::windowEvent(QEvent *event) bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) { - const int dpr = int(devicePixelRatio()); const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE); if (!connection()->wmSupport()->isSupportedByWM(moveResize)) return false; @@ -2403,7 +2482,7 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) xev.type = moveResize; xev.window = xcb_window(); xev.format = 32; - const QPoint globalPos = window()->mapToGlobal(pos) * dpr; + const QPoint globalPos = mapToNative(window()->mapToGlobal(pos), xcbScreen()); xev.data.data32[0] = globalPos.x(); xev.data.data32[1] = globalPos.y(); const bool bottom = corner == Qt::BottomRightCorner || corner == Qt::BottomLeftCorner; @@ -2532,7 +2611,7 @@ void QXcbWindow::setMask(const QRegion ®ion) const int dpr = devicePixelRatio(); QVector<xcb_rectangle_t> rects; foreach (const QRect &r, region.rects()) - rects.push_back(qRectToXCBRectangle(mapToNative(r, dpr))); + rects.push_back(qRectToXCBRectangle(mapLocalGeometryToNative(r, dpr))); xcb_shape_rectangles(connection()->xcb_connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, xcb_window(), 0, 0, rects.size(), &rects[0]); @@ -2549,6 +2628,11 @@ void QXcbWindow::setAlertState(bool enabled) changeNetWmState(enabled, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)); } +uint QXcbWindow::visualId() const +{ + return m_visualId; +} + bool QXcbWindow::needsSync() const { return m_syncState == SyncAndConfigureReceived; @@ -2556,6 +2640,8 @@ bool QXcbWindow::needsSync() const void QXcbWindow::postSyncWindowRequest() { + if (!xcbScreen()) + return; if (!m_pendingSyncRequest) { QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this); m_pendingSyncRequest = e; diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 2442e6c4e3..52e8ac1459 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -140,6 +140,7 @@ public: void updateNetWmUserTime(xcb_timestamp_t timestamp); static void setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowTypes); + static uint visualIdStatic(QWindow *window); QXcbWindowFunctions::WmWindowTypes wmWindowTypes() const; void setWmWindowType(QXcbWindowFunctions::WmWindowTypes types); @@ -154,6 +155,7 @@ public: static QRect systemTrayWindowGlobalGeometryStatic(const QWindow *window); QRect systemTrayWindowGlobalGeometry() const; + uint visualId() const; bool needsSync() const; @@ -167,7 +169,7 @@ public: virtual void create(); virtual void destroy(); void maybeSetScreen(QXcbScreen *screen); - QPlatformScreen *screenForNativeGeometry(const QRect &newGeometry) const; + QXcbScreen *screenForNativeGeometry(const QRect &newGeometry) const; public Q_SLOTS: void updateSyncRequestCounter(); @@ -177,6 +179,12 @@ protected: virtual void *createVisual() { return Q_NULLPTR; } virtual bool supportsSyncProtocol() { return !window()->supportsOpenGL(); } + QPoint mapToNative(const QPoint &pos, const QXcbScreen *screen) const; + QPoint mapFromNative(const QPoint &pos, const QXcbScreen *screen) const; + QRect mapToNative(const QRect &rect, const QXcbScreen *screen) const; + QRect mapFromNative(const QRect &rect, const QXcbScreen *screen) const; + QXcbScreen *parentScreen(); + void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0); NetWmStates netWmStates(); void setNetWmStates(NetWmStates); @@ -204,6 +212,8 @@ protected: xcb_window_t m_window; + QXcbScreen *m_xcbScreen; + uint m_depth; QImage::Format m_imageFormat; bool m_imageRgbSwap; diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp index bcdfde2ef9..7d31ac7118 100644 --- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp +++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp @@ -68,7 +68,7 @@ void QXcbWMSupport::updateNetWMAtoms() remaining = 0; if (reply->type == XCB_ATOM_ATOM && reply->format == 32) { - int len = xcb_get_property_value_length(reply)/4; + int len = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t); xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply); int s = net_wm_atoms.size(); net_wm_atoms.resize(s + len); @@ -102,11 +102,11 @@ void QXcbWMSupport::updateVirtualRoots() remaining = 0; if (reply->type == XCB_ATOM_ATOM && reply->format == 32) { - int len = xcb_get_property_value_length(reply)/4; - xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply); - int s = net_wm_atoms.size(); - net_wm_atoms.resize(s + len); - memcpy(net_wm_atoms.data() + s, atoms, len*sizeof(xcb_atom_t)); + int len = xcb_get_property_value_length(reply)/sizeof(xcb_window_t); + xcb_window_t *roots = (xcb_window_t *)xcb_get_property_value(reply); + int s = net_virtual_roots.size(); + net_virtual_roots.resize(s + len); + memcpy(net_virtual_roots.data() + s, roots, len*sizeof(xcb_window_t)); remaining = reply->bytes_after; offset += len; diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp index c83edd506d..46cee5d6d0 100644 --- a/src/plugins/platforms/xcb/qxcbxsettings.cpp +++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp @@ -63,7 +63,7 @@ public: : last_change_serial(-1) {} - void updateValue(QXcbScreen *screen, const QByteArray &name, const QVariant &value, int last_change_serial) + void updateValue(QXcbVirtualDesktop *screen, const QByteArray &name, const QVariant &value, int last_change_serial) { if (last_change_serial <= this->last_change_serial) return; @@ -92,7 +92,7 @@ public: class QXcbXSettingsPrivate { public: - QXcbXSettingsPrivate(QXcbScreen *screen) + QXcbXSettingsPrivate(QXcbVirtualDesktop *screen) : screen(screen) , initialized(false) { @@ -217,18 +217,18 @@ public: } #endif //XCB_USE_XLIB - QXcbScreen *screen; + QXcbVirtualDesktop *screen; xcb_window_t x_settings_window; QMap<QByteArray, QXcbXSettingsPropertyValue> settings; bool initialized; }; -QXcbXSettings::QXcbXSettings(QXcbScreen *screen) +QXcbXSettings::QXcbXSettings(QXcbVirtualDesktop *screen) : d_ptr(new QXcbXSettingsPrivate(screen)) { QByteArray settings_atom_for_screen("_XSETTINGS_S"); - settings_atom_for_screen.append(QByteArray::number(screen->screenNumber())); + settings_atom_for_screen.append(QByteArray::number(screen->number())); xcb_intern_atom_cookie_t atom_cookie = xcb_intern_atom(screen->xcb_connection(), true, settings_atom_for_screen.length(), diff --git a/src/plugins/platforms/xcb/qxcbxsettings.h b/src/plugins/platforms/xcb/qxcbxsettings.h index 4022f0a2c4..3f1d175336 100644 --- a/src/plugins/platforms/xcb/qxcbxsettings.h +++ b/src/plugins/platforms/xcb/qxcbxsettings.h @@ -44,13 +44,13 @@ class QXcbXSettings : public QXcbWindowEventListener { Q_DECLARE_PRIVATE(QXcbXSettings) public: - QXcbXSettings(QXcbScreen *screen); + QXcbXSettings(QXcbVirtualDesktop *screen); ~QXcbXSettings(); bool initialized() const; QVariant setting(const QByteArray &property) const; - typedef void (*PropertyChangeFunc)(QXcbScreen *screen, const QByteArray &name, const QVariant &property, void *handle); + typedef void (*PropertyChangeFunc)(QXcbVirtualDesktop *screen, const QByteArray &name, const QVariant &property, void *handle); void registerCallbackForProperty(const QByteArray &property, PropertyChangeFunc func, void *handle); void removeCallbackForHandle(const QByteArray &property, void *handle); void removeCallbackForHandle(void *handle); |