diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbconnection.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 74 |
1 files changed, 50 insertions, 24 deletions
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() |