diff options
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r-- | src/plugins/platforms/xcb/README | 10 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.pro | 1 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbclipboard.cpp | 12 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbclipboard.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 21 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbcursor.cpp | 24 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbintegration.cpp | 5 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 4 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbnativeinterface.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 48 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/xcb-static/xcb-static.pro | 3 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/xcb_qpa_lib.pro | 3 |
13 files changed, 78 insertions, 60 deletions
diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README index 15cf4cf241..5efc9b7f99 100644 --- a/src/plugins/platforms/xcb/README +++ b/src/plugins/platforms/xcb/README @@ -21,3 +21,13 @@ REDUCING RUNTIME DEPENDENCIES The '-qt-xcb' configure option can be used to get rid of most xcb- dependencies. Only libxcb will still be linked dynamically, since it will be most likely be pulled in via other dependencies anyway. This should allow for binaries that are portable across most modern Linux distributions. + +PACKAGE VERSION REQUIREMENTS + +When using touch input via XInput 2.2 or higher, there is a potential issue on systems that ship with +a libXi older than 1.7.4. This is because XIAllowTouchEvents can deadlock with libXi 1.7.3 and earlier. +When touch events are never received, this is not an issue, so plain mouse/keyboard systems are not affected. +See http://lists.x.org/archives/xorg-devel/2014-July/043059.html for details on the libXi patch. +Qt versions before 5.8 attempted to recognize this scenario based on the pkg-config package version and skip +the call. This has been removed starting from 5.8 since relying on pkg-config package versions is unsafe given +that Qt must also support systems with limited or incomplete pkg-config setups. diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.pro b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.pro index d82a1f2d17..e52677d091 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.pro +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.pro @@ -10,7 +10,6 @@ qtConfig(xcb-glx) { DEFINES += XCB_HAS_XCB_GLX QMAKE_USE += xcb_glx } -QMAKE_USE += xcb LIBS += $$QMAKE_LIBS_DYNLOAD diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index b95ad4b5c9..f9c32cd0a4 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -275,8 +275,6 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c) { Q_ASSERT(QClipboard::Clipboard == 0); Q_ASSERT(QClipboard::Selection == 1); - m_xClipboard[QClipboard::Clipboard] = 0; - m_xClipboard[QClipboard::Selection] = 0; m_clientClipboard[QClipboard::Clipboard] = 0; m_clientClipboard[QClipboard::Selection] = 0; m_timestamp[QClipboard::Clipboard] = XCB_CURRENT_TIME; @@ -329,6 +327,10 @@ QXcbClipboard::~QXcbClipboard() } free(reply); } + + if (m_clientClipboard[QClipboard::Clipboard] != m_clientClipboard[QClipboard::Selection]) + delete m_clientClipboard[QClipboard::Clipboard]; + delete m_clientClipboard[QClipboard::Selection]; } void QXcbClipboard::incrTransactionPeeker(xcb_generic_event_t *ge, bool &accepted) @@ -378,9 +380,9 @@ QMimeData * QXcbClipboard::mimeData(QClipboard::Mode mode) return m_clientClipboard[mode]; } else { if (!m_xClipboard[mode]) - m_xClipboard[mode] = new QXcbClipboardMime(mode, this); + m_xClipboard[mode].reset(new QXcbClipboardMime(mode, this)); - return m_xClipboard[mode]; + return m_xClipboard[mode].data(); } } @@ -730,7 +732,7 @@ void QXcbClipboard::handleXFixesSelectionRequest(xcb_xfixes_selection_notify_eve // here we care only about the xfixes events that come from non Qt processes if (event->owner != XCB_NONE && event->owner != owner()) { if (!m_xClipboard[mode]) { - m_xClipboard[mode] = new QXcbClipboardMime(mode, this); + m_xClipboard[mode].reset(new QXcbClipboardMime(mode, this)); } else { m_xClipboard[mode]->reset(); } diff --git a/src/plugins/platforms/xcb/qxcbclipboard.h b/src/plugins/platforms/xcb/qxcbclipboard.h index 58c7f32c4c..ffd565c56f 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.h +++ b/src/plugins/platforms/xcb/qxcbclipboard.h @@ -98,7 +98,7 @@ private: QClipboard::Mode modeForAtom(xcb_atom_t atom) const; // Selection and Clipboard - QXcbClipboardMime *m_xClipboard[2]; + QScopedPointer<QXcbClipboardMime> m_xClipboard[2]; QMimeData *m_clientClipboard[2]; xcb_timestamp_t m_timestamp[2]; diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 1147fc82b2..93f8db92bf 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -697,26 +697,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo if (m_xiGrab) { // XIAllowTouchEvents deadlocks with libXi < 1.7.4 (this has nothing to do with the XI2 versions like 2.2) // http://lists.x.org/archives/xorg-devel/2014-July/043059.html -#ifndef XCB_USE_XINPUT2 - static bool allowTouchWarningShown = false; - if (!allowTouchWarningShown) { - allowTouchWarningShown = true; - qWarning("Skipping XIAllowTouchEvents() because it was not possible to detect libXi version at build time." - " Minimum libXi version required is 1.7.4." - " Expect issues with touch behavior."); - } -#elif QT_LIBRARY_VERSION(xinput2) < QT_VERSION_CHECK(1, 7, 4) - static bool allowTouchWarningShown = false; - if (!allowTouchWarningShown) { - allowTouchWarningShown = true; - qWarning("Skipping XIAllowTouchEvents() due to not having libXi >= 1.7.4." - " libXi version at build time was %d.%d.%d." - " Expect issues with touch behavior.", - QT_LIBRARY_VERSION_MAJOR(xinput2), - QT_LIBRARY_VERSION_MINOR(xinput2), - QT_LIBRARY_VERSION_PATCH(xinput2)); - } -#else +#ifdef XCB_USE_XINPUT2 XIAllowTouchEvents(static_cast<Display *>(m_xlib_display), xiDeviceEvent->deviceid, xiDeviceEvent->detail, xiDeviceEvent->event, XIAcceptTouch); #endif diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index 11e0c998b1..4de4be43d1 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -359,17 +359,27 @@ void QXcbCursor::changeCursor(QCursor *cursor, QWindow *widget) return; xcb_cursor_t c = XCB_CURSOR_NONE; + bool isBitmapCursor = false; + if (cursor) { - const QXcbCursorCacheKey key(*cursor); - CursorHash::iterator it = m_cursorHash.find(key); - if (it == m_cursorHash.end()) { - const Qt::CursorShape shape = cursor->shape(); - it = m_cursorHash.insert(key, shape == Qt::BitmapCursor ? createBitmapCursor(cursor) : createFontCursor(shape)); + const Qt::CursorShape shape = cursor->shape(); + isBitmapCursor = shape == Qt::BitmapCursor; + + if (!isBitmapCursor) { + const QXcbCursorCacheKey key(*cursor); + CursorHash::iterator it = m_cursorHash.find(key); + if (it == m_cursorHash.end()) { + it = m_cursorHash.insert(key, createFontCursor(shape)); + } + c = it.value(); + } else { + // Do not cache bitmap cursors, as otherwise they have unclear + // lifetime (we effectively leak xcb_cursor_t). + c = createBitmapCursor(cursor); } - c = it.value(); } - w->setCursor(c); + w->setCursor(c, isBitmapCursor); } static int cursorIdForShape(int cshape) diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 802f7b85ce..b0c5ac79f9 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -61,13 +61,8 @@ #include <stdio.h> -//this has to be included before egl, since egl pulls in X headers #include <QtGui/private/qguiapplication_p.h> -#ifdef XCB_USE_EGL -# include <QtPlatformSupport/private/qt_egl_p.h> -#endif - #ifdef XCB_USE_XLIB #include <X11/Xlib.h> #endif diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 189ec53050..b1575cbee4 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -57,10 +57,6 @@ #include <QtPlatformHeaders/qxcbintegrationfunctions.h> #include <QtPlatformHeaders/qxcbscreenfunctions.h> -#ifndef QT_NO_DBUS -#include "QtPlatformSupport/private/qdbusmenuconnection_p.h" -#endif - #ifdef XCB_USE_XLIB # include <X11/Xlib.h> #else diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h index 8728b6e937..acecbf4116 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.h +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h @@ -53,7 +53,6 @@ class QWidget; class QXcbScreen; class QXcbConnection; class QXcbNativeInterfaceHandler; -class QDBusMenuConnection; class Q_XCB_EXPORT QXcbNativeInterface : public QPlatformNativeInterface { diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index c81858c408..ee7bfd6c53 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -258,7 +258,7 @@ static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s) free_prop = true; } -#ifndef QT_NO_TEXTCODEC +#if QT_CONFIG(textcodec) static const QTextCodec* mapper = QTextCodec::codecForLocale(); int errCode = 0; if (mapper) { @@ -274,6 +274,7 @@ static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s) mapper = QTextCodec::codecForName("latin1"); if (!mapper || !mapper->canEncode(s)) return Q_NULLPTR; +#endif static QByteArray qcs; qcs = s.toLatin1(); tp.value = (uchar*)qcs.data(); @@ -281,6 +282,7 @@ static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s) tp.format = 8; tp.nitems = qcs.length(); free_prop = false; +#if QT_CONFIG(textcodec) } #endif return &tp; @@ -326,6 +328,7 @@ QXcbWindow::QXcbWindow(QWindow *window) , m_lastWindowStateEvent(-1) , m_syncState(NoSyncNeeded) , m_pendingSyncRequest(0) + , m_currentBitmapCursor(XCB_CURSOR_NONE) { setConnection(xcbScreen()->connection()); } @@ -600,6 +603,9 @@ void QXcbWindow::create() QXcbWindow::~QXcbWindow() { + if (m_currentBitmapCursor != XCB_CURSOR_NONE) { + xcb_free_cursor(xcb_connection(), m_currentBitmapCursor); + } if (window()->type() != Qt::ForeignWindow) destroy(); else { @@ -2416,6 +2422,17 @@ static inline int fixed1616ToInt(FP1616 val) return int((qreal(val >> 16)) + (val & 0xFFFF) / (qreal)0xFFFF); } +void QXcbWindow::handleXIMouseButtonState(const xcb_ge_event_t *event) +{ + QXcbConnection *conn = connection(); + const xXIDeviceEvent *ev = reinterpret_cast<const xXIDeviceEvent *>(event); + if (ev->buttons_len > 0) { + unsigned char *buttonMask = (unsigned char *) &ev[1]; + for (int i = 1; i <= 15; ++i) + conn->setButton(conn->translateMouseButton(i), XIMaskIsSet(buttonMask, i)); + } +} + // With XI 2.2+ press/release/motion comes here instead of the above handlers. void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource source) { @@ -2431,12 +2448,6 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource const Qt::MouseButton button = conn->xiToQtMouseButton(ev->detail); - if (ev->buttons_len > 0) { - unsigned char *buttonMask = (unsigned char *) &ev[1]; - for (int i = 1; i <= 15; ++i) - conn->setButton(conn->translateMouseButton(i), XIMaskIsSet(buttonMask, i)); - } - const char *sourceName = 0; if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) { const QMetaObject *metaObject = qt_getEnumMetaObject(source); @@ -2446,18 +2457,23 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource switch (ev->evtype) { case XI_ButtonPress: + handleXIMouseButtonState(event); if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) qCDebug(lcQpaXInputEvents, "XI2 mouse press, button %d, time %d, source %s", button, ev->time, sourceName); conn->setButton(button, true); handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, source); break; case XI_ButtonRelease: + handleXIMouseButtonState(event); if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) qCDebug(lcQpaXInputEvents, "XI2 mouse release, button %d, time %d, source %s", button, ev->time, sourceName); conn->setButton(button, false); handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, source); break; case XI_Motion: + // Here we do NOT call handleXIMouseButtonState because we don't expect button state change to be bundled with motion. + // When a touchscreen is pressed, an XI_Motion event occurs in which XIMaskIsSet says the left button is pressed, + // but we don't want QGuiApplicationPrivate::processMouseEvent() to react by generating a mouse press event. if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) qCDebug(lcQpaXInputEvents, "XI2 mouse motion %d,%d, time %d, source %s", event_x, event_y, ev->time, sourceName); handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time, source); @@ -2669,10 +2685,22 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab) return result; } -void QXcbWindow::setCursor(xcb_cursor_t cursor) +void QXcbWindow::setCursor(xcb_cursor_t cursor, bool isBitmapCursor) { - xcb_change_window_attributes(xcb_connection(), m_window, XCB_CW_CURSOR, &cursor); - xcb_flush(xcb_connection()); + xcb_connection_t *conn = xcb_connection(); + + xcb_change_window_attributes(conn, m_window, XCB_CW_CURSOR, &cursor); + xcb_flush(conn); + + if (m_currentBitmapCursor != XCB_CURSOR_NONE) { + xcb_free_cursor(conn, m_currentBitmapCursor); + } + + if (isBitmapCursor) { + m_currentBitmapCursor = cursor; + } else { + m_currentBitmapCursor = XCB_CURSOR_NONE; + } } void QXcbWindow::windowEvent(QEvent *event) diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index f62938ba8a..92f3f7a67c 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -103,7 +103,7 @@ public: bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE; bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE; - void setCursor(xcb_cursor_t cursor); + void setCursor(xcb_cursor_t cursor, bool isBitmapCursor); QSurfaceFormat format() const Q_DECL_OVERRIDE; @@ -139,6 +139,7 @@ public: void handleFocusOutEvent(const xcb_focus_out_event_t *event) Q_DECL_OVERRIDE; void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) Q_DECL_OVERRIDE; #ifdef XCB_USE_XINPUT22 + void handleXIMouseButtonState(const xcb_ge_event_t *); void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized) Q_DECL_OVERRIDE; void handleXIEnterLeave(xcb_ge_event_t *) Q_DECL_OVERRIDE; #endif @@ -271,6 +272,7 @@ protected: SyncState m_syncState; QXcbSyncWindowRequest *m_pendingSyncRequest; + xcb_cursor_t m_currentBitmapCursor; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro index 20481e4834..a1dec2b0b5 100644 --- a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro +++ b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro @@ -11,8 +11,7 @@ XCB_DIR = ../../../../3rdparty/xcb INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/include/xcb $$XCB_DIR/sysinclude -QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB -QMAKE_CFLAGS += $$QMAKE_CFLAGS_XCB +QMAKE_USE += xcb/nolink # ignore compiler warnings in 3rdparty code QMAKE_CFLAGS_STATIC_LIB+=-w diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro index ec0fa68871..246bb1f118 100644 --- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro +++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro @@ -66,9 +66,6 @@ include(gl_integrations/gl_integrations.pri) CONFIG += qpa/genericunixfontdatabase -qtConfig(dbus-linked): \ - QT += dbus - !qtConfig(system-xcb) { DEFINES += XCB_USE_RENDER XCB_DIR = ../../../3rdparty/xcb |