diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbconnection.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 128 |
1 files changed, 97 insertions, 31 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index f100f2d2e9..636914fd07 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -73,7 +73,7 @@ #include <X11/Xlibint.h> #endif -#if defined(XCB_USE_XINPUT2) || defined(XCB_USE_XINPUT2_MAEMO) +#if defined(XCB_USE_XINPUT2) #include <X11/extensions/XInput2.h> #include <X11/extensions/XI2proto.h> #endif @@ -92,6 +92,9 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaXInput, "qt.qpa.input") +Q_LOGGING_CATEGORY(lcQpaXInputDevices, "qt.qpa.input.devices") + #ifdef XCB_USE_XLIB static const char * const xcbConnectionErrors[] = { "No error", /* Error 0 */ @@ -126,6 +129,39 @@ static int ioErrorHandler(Display *dpy) } #endif +#if defined(XCB_HAS_XCB_GLX) && XCB_GLX_MAJOR_VERSION == 1 && XCB_GLX_MINOR_VERSION < 4 + +#define XCB_GLX_BUFFER_SWAP_COMPLETE 1 + +typedef struct xcb_glx_buffer_swap_complete_event_t { + uint8_t response_type; + uint8_t pad0; + uint16_t sequence; + uint16_t event_type; + uint8_t pad1[2]; + xcb_glx_drawable_t drawable; + uint32_t ust_hi; + uint32_t ust_lo; + uint32_t msc_hi; + uint32_t msc_lo; + uint32_t sbc; +} xcb_glx_buffer_swap_complete_event_t; +#endif + +#if defined(XCB_USE_XLIB) && defined(XCB_USE_GLX) +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Drawable drawable; /* drawable on which event was requested in event mask */ + int event_type; + int64_t ust; + int64_t msc; + int64_t sbc; +} QGLXBufferSwapComplete; +#endif + QXcbScreen* QXcbConnection::findOrCreateScreen(QList<QXcbScreen *>& newScreens, int screenNumber, xcb_screen_t* xcbScreen, xcb_randr_get_output_info_reply_t *output) { @@ -281,20 +317,16 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra , m_primaryScreen(0) , m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY")) , m_nativeInterface(nativeInterface) -#ifdef XCB_USE_XINPUT2_MAEMO - , m_xinputData(0) -#endif , xfixes_first_event(0) , xrandr_first_event(0) , xkb_first_event(0) + , glx_first_event(0) , has_glx_extension(false) , has_shape_extension(false) , has_randr_extension(false) , has_input_shape(false) , has_touch_without_mouse_emulation(false) , has_xkb(false) - , debug_xinput_devices(false) - , debug_xinput(false) , m_buttons(0) , m_focusWindow(0) , m_systemTrayTracker(0) @@ -362,9 +394,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra initializeXFixes(); initializeXRender(); m_xi2Enabled = false; -#ifdef XCB_USE_XINPUT2_MAEMO - initializeXInput2Maemo(); -#elif defined(XCB_USE_XINPUT2) +#if defined(XCB_USE_XINPUT2) initializeXInput2(); #endif initializeXShape(); @@ -398,9 +428,7 @@ QXcbConnection::~QXcbConnection() delete m_drag; #endif -#ifdef XCB_USE_XINPUT2_MAEMO - finalizeXInput2Maemo(); -#elif defined(XCB_USE_XINPUT2) +#if defined(XCB_USE_XINPUT2) finalizeXInput2(); #endif @@ -774,8 +802,7 @@ void QXcbConnection::handleButtonPress(xcb_generic_event_t *ev) // the rest we need to manage ourselves m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state); m_buttons |= translateMouseButton(event->detail); - if (Q_UNLIKELY(debug_xinput)) - qDebug("xcb: pressed mouse button %d, button state %X", event->detail, static_cast<unsigned int>(m_buttons)); + qCDebug(lcQpaXInput, "xcb: pressed mouse button %d, button state %X", event->detail, static_cast<unsigned int>(m_buttons)); } void QXcbConnection::handleButtonRelease(xcb_generic_event_t *ev) @@ -786,8 +813,7 @@ void QXcbConnection::handleButtonRelease(xcb_generic_event_t *ev) // the rest we need to manage ourselves m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state); m_buttons &= ~translateMouseButton(event->detail); - if (Q_UNLIKELY(debug_xinput)) - qDebug("xcb: released mouse button %d, button state %X", event->detail, static_cast<unsigned int>(m_buttons)); + qCDebug(lcQpaXInput, "xcb: released mouse button %d, button state %X", event->detail, static_cast<unsigned int>(m_buttons)); } #ifndef QT_NO_XKB @@ -840,7 +866,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) handleButtonRelease(event); HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); case XCB_MOTION_NOTIFY: - if (Q_UNLIKELY(debug_xinput)) { + if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) { xcb_motion_notify_event_t *mev = (xcb_motion_notify_event_t *)event; qDebug("xcb: moved mouse to %4d, %4d; button state %X", mev->event_x, mev->event_y, static_cast<unsigned int>(m_buttons)); } @@ -904,11 +930,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) case XCB_PROPERTY_NOTIFY: HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent); break; -#ifdef XCB_USE_XINPUT2_MAEMO - case GenericEvent: - handleGenericEventMaemo((xcb_ge_event_t*)event); - break; -#elif defined(XCB_USE_XINPUT2) +#if defined(XCB_USE_XINPUT2) case GenericEvent: if (m_xi2Enabled) xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(event)); @@ -972,14 +994,43 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) // XESetWireToEvent might be used by libraries to intercept messages from the X server e.g. the OpenGL lib waiting for DRI2 events. Display *xdisplay = (Display *)m_xlib_display; XLockDisplay(xdisplay); + bool locked = true; Bool (*proc)(Display*, XEvent*, xEvent*) = XESetWireToEvent(xdisplay, response_type, 0); if (proc) { XESetWireToEvent(xdisplay, response_type, proc); XEvent dummy; event->sequence = LastKnownRequestProcessed(m_xlib_display); - proc(xdisplay, &dummy, (xEvent*)event); + if (proc(xdisplay, &dummy, (xEvent*)event)) { +#if defined(XCB_USE_GLX) && defined(XCB_HAS_XCB_GLX) + // DRI2 clients don't receive GLXBufferSwapComplete events on the wire. + // Instead the GLX event is synthesized from the DRI2BufferSwapComplete event + // by DRI2WireToEvent(). For an application to be able to see the event + // we have to convert it to an xcb_glx_buffer_swap_complete_event_t and + // pass it to the native event filter. + const uint swap_complete = glx_first_event + XCB_GLX_BUFFER_SWAP_COMPLETE; + if (dispatcher && has_glx_extension && uint(dummy.type) == swap_complete && response_type != swap_complete) { + QGLXBufferSwapComplete *xev = reinterpret_cast<QGLXBufferSwapComplete *>(&dummy); + xcb_glx_buffer_swap_complete_event_t ev; + memset(&ev, 0, sizeof(xcb_glx_buffer_swap_complete_event_t)); + ev.response_type = xev->type; + ev.sequence = xev->serial; + ev.event_type = xev->event_type; + ev.drawable = xev->drawable; + ev.ust_hi = xev->ust >> 32; + ev.ust_lo = xev->ust & 0xffffffff; + ev.msc_hi = xev->msc >> 32; + ev.msc_lo = xev->msc & 0xffffffff; + ev.sbc = xev->sbc & 0xffffffff; + // Unlock the display before calling the native event filter + XUnlockDisplay(xdisplay); + locked = false; + handled = dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), &ev, &result); + } +#endif + } } - XUnlockDisplay(xdisplay); + if (locked) + XUnlockDisplay(xdisplay); } #endif @@ -1483,9 +1534,6 @@ static const char * xcb_atomnames = { "Rel Vert Wheel\0" "Rel Horiz Scroll\0" "Rel Vert Scroll\0" -#if XCB_USE_MAEMO_WINDOW_PROPERTIES - "_MEEGOTOUCH_ORIENTATION_ANGLE\0" -#endif "_XSETTINGS_SETTINGS\0" "_COMPIZ_DECOR_PENDING\0" "_COMPIZ_DECOR_REQUEST\0" @@ -1632,6 +1680,7 @@ void QXcbConnection::initializeGLX() return; has_glx_extension = true; + glx_first_event = reply->first_event; xcb_generic_error_t *error = 0; xcb_glx_query_version_cookie_t xglx_query_cookie = xcb_glx_query_version(m_connection, @@ -1767,7 +1816,7 @@ bool QXcbConnection::hasEgl() const } #endif // defined(XCB_USE_EGL) -#if defined(XCB_USE_XINPUT2) || defined(XCB_USE_XINPUT2_MAEMO) +#if defined(XCB_USE_XINPUT2) static int xi2ValuatorOffset(unsigned char *maskPtr, int maskLen, int number) { int offset = 0; @@ -1832,7 +1881,7 @@ bool QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *ev, int opCo } return false; } -#endif // defined(XCB_USE_XINPUT2) || defined(XCB_USE_XINPUT2_MAEMO) +#endif // defined(XCB_USE_XINPUT2) QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() { @@ -1845,9 +1894,26 @@ QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() return m_systemTrayTracker; } -void QXcbConnection::syncWindow(QXcbWindow *window) +bool QXcbConnection::event(QEvent *e) { - window->updateSyncRequestCounter(); + if (e->type() == QEvent::User + 1) { + QXcbSyncWindowRequest *ev = static_cast<QXcbSyncWindowRequest *>(e); + QXcbWindow *w = ev->window(); + if (w) { + w->updateSyncRequestCounter(); + ev->invalidate(); + } + return true; + } + return QObject::event(e); +} + +void QXcbSyncWindowRequest::invalidate() +{ + if (m_window) { + m_window->clearSyncWindowRequest(); + m_window = 0; + } } QXcbConnectionGrabber::QXcbConnectionGrabber(QXcbConnection *connection) |