diff options
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 71 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 10 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 46 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbnativeinterface.h | 11 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 86 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.h | 3 |
6 files changed, 161 insertions, 66 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 4c4df137a3..1192894693 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -257,6 +257,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char , has_shape_extension(false) , has_randr_extension(false) , has_input_shape(false) + , m_buttons(0) { #ifdef XCB_USE_XLIB Display *dpy = XOpenDisplay(m_displayName.constData()); @@ -312,6 +313,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char initializeAllAtoms(); m_time = XCB_CURRENT_TIME; + m_netWmUserTime = XCB_CURRENT_TIME; initializeXRandr(); updateScreens(); @@ -662,6 +664,73 @@ void QXcbConnection::handleXcbError(xcb_generic_error_t *error) #endif } +static Qt::MouseButtons translateMouseButtons(int s) +{ + Qt::MouseButtons ret = 0; + if (s & XCB_BUTTON_MASK_1) + ret |= Qt::LeftButton; + if (s & XCB_BUTTON_MASK_2) + ret |= Qt::MidButton; + if (s & XCB_BUTTON_MASK_3) + ret |= Qt::RightButton; + return ret; +} + +static Qt::MouseButton translateMouseButton(xcb_button_t s) +{ + switch (s) { + case 1: return Qt::LeftButton; + case 2: return Qt::MidButton; + case 3: return Qt::RightButton; + // Button values 4-7 were already handled as Wheel events, and won't occur here. + case 8: return Qt::BackButton; // Also known as Qt::ExtraButton1 + case 9: return Qt::ForwardButton; // Also known as Qt::ExtraButton2 + case 10: return Qt::ExtraButton3; + case 11: return Qt::ExtraButton4; + case 12: return Qt::ExtraButton5; + case 13: return Qt::ExtraButton6; + case 14: return Qt::ExtraButton7; + case 15: return Qt::ExtraButton8; + case 16: return Qt::ExtraButton9; + case 17: return Qt::ExtraButton10; + case 18: return Qt::ExtraButton11; + case 19: return Qt::ExtraButton12; + case 20: return Qt::ExtraButton13; + case 21: return Qt::ExtraButton14; + case 22: return Qt::ExtraButton15; + case 23: return Qt::ExtraButton16; + case 24: return Qt::ExtraButton17; + case 25: return Qt::ExtraButton18; + case 26: return Qt::ExtraButton19; + case 27: return Qt::ExtraButton20; + case 28: return Qt::ExtraButton21; + case 29: return Qt::ExtraButton22; + case 30: return Qt::ExtraButton23; + case 31: return Qt::ExtraButton24; + default: return Qt::NoButton; + } +} + +void QXcbConnection::handleButtonPress(xcb_generic_event_t *ev) +{ + xcb_button_press_event_t *event = (xcb_button_press_event_t *)ev; + + // the event explicitly contains the state of the three first buttons, + // the rest we need to manage ourselves + m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state); + m_buttons |= translateMouseButton(event->detail); +} + +void QXcbConnection::handleButtonRelease(xcb_generic_event_t *ev) +{ + xcb_button_release_event_t *event = (xcb_button_release_event_t *)ev; + + // the event explicitly contains the state of the three first buttons, + // the rest we need to manage ourselves + m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state); + m_buttons &= ~translateMouseButton(event->detail); +} + void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) { #ifdef Q_XCB_DEBUG @@ -686,8 +755,10 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) case XCB_EXPOSE: HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); case XCB_BUTTON_PRESS: + handleButtonPress(event); HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); case XCB_BUTTON_RELEASE: + handleButtonRelease(event); HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); case XCB_MOTION_NOTIFY: HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index c67acb3218..464d918adf 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -370,6 +370,9 @@ public: inline xcb_timestamp_t time() const { return m_time; } inline void setTime(xcb_timestamp_t t) { if (t > m_time) m_time = t; } + inline xcb_timestamp_t netWmUserTime() const { return m_netWmUserTime; } + inline void setNetWmUserTime(xcb_timestamp_t t) { if (t > m_netWmUserTime) m_netWmUserTime = t; } + bool hasGLX() const { return has_glx_extension; } bool hasXFixes() const { return xfixes_first_event > 0; } bool hasXShape() const { return has_shape_extension; } @@ -380,6 +383,8 @@ public: xcb_timestamp_t getTimestamp(); + Qt::MouseButtons buttons() const { return m_buttons; } + private slots: void processXcbEvents(); @@ -400,6 +405,8 @@ private: QXcbScreen* findOrCreateScreen(QList<QXcbScreen *>& newScreens, int screenNumber, xcb_screen_t* xcbScreen, xcb_randr_get_output_info_reply_t *output = NULL); void updateScreens(); + void handleButtonPress(xcb_generic_event_t *event); + void handleButtonRelease(xcb_generic_event_t *event); bool m_xi2Enabled; int m_xi2Minor; @@ -448,6 +455,7 @@ private: xcb_atom_t m_allAtoms[QXcbAtom::NAtoms]; xcb_timestamp_t m_time; + xcb_timestamp_t m_netWmUserTime; QByteArray m_displayName; @@ -501,6 +509,8 @@ private: bool has_shape_extension; bool has_randr_extension; bool has_input_shape; + + Qt::MouseButtons m_buttons; }; #define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display())) diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index a44e7fb959..9c360df900 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -71,6 +71,8 @@ public: insert("screen",QXcbNativeInterface::Screen); insert("eglcontext",QXcbNativeInterface::EglContext); insert("glxcontext",QXcbNativeInterface::GLXContext); + insert("apptime",QXcbNativeInterface::AppTime); + insert("appusertime",QXcbNativeInterface::AppUserTime); } }; @@ -109,18 +111,24 @@ void *QXcbNativeInterface::nativeResourceForScreen(const QByteArray &resource, Q const QXcbResourceMap::const_iterator it = qXcbResourceMap()->constFind(resource.toLower()); if (it == qXcbResourceMap()->constEnd() || !screen->handle()) return 0; + void *result = 0; const QXcbScreen *xcbScreen = static_cast<QXcbScreen *>(screen->handle()); switch (it.value()) { case Display: #ifdef XCB_USE_XLIB - return xcbScreen->connection()->xlib_display(); -#else - break; + result = xcbScreen->connection()->xlib_display(); #endif + break; + case AppTime: + result = appTime(xcbScreen); + break; + case AppUserTime: + result = appUserTime(xcbScreen); + break; default: break; } - return 0; + return result; } void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) @@ -151,6 +159,36 @@ void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceStr return result; } +QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::nativeResourceFunctionForScreen(const QByteArray &resource) +{ + const QByteArray lowerCaseResource = resource.toLower(); + if (lowerCaseResource == "setapptime") + return NativeResourceForScreenFunction(setAppTime); + else if (lowerCaseResource == "setappusertime") + return NativeResourceForScreenFunction(setAppUserTime); + return 0; +} + +void *QXcbNativeInterface::appTime(const QXcbScreen *screen) +{ + return reinterpret_cast<void *>(quintptr(screen->connection()->time())); +} + +void *QXcbNativeInterface::appUserTime(const QXcbScreen *screen) +{ + return reinterpret_cast<void *>(quintptr(screen->connection()->netWmUserTime())); +} + +void QXcbNativeInterface::setAppTime(QScreen* screen, xcb_timestamp_t time) +{ + static_cast<QXcbScreen *>(screen->handle())->connection()->setTime(time); +} + +void QXcbNativeInterface::setAppUserTime(QScreen* screen, xcb_timestamp_t time) +{ + static_cast<QXcbScreen *>(screen->handle())->connection()->setNetWmUserTime(time); +} + QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::nativeResourceFunctionForContext(const QByteArray &resource) { QByteArray lowerCaseResource = resource.toLower(); diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h index a7e0a207cb..e2e03fce8f 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.h +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h @@ -43,11 +43,13 @@ #define QXCBNATIVEINTERFACE_H #include <qpa/qplatformnativeinterface.h> +#include <xcb/xcb.h> QT_BEGIN_NAMESPACE class QWidget; class QXcbScreen; +class QXcbConnection; class QXcbNativeInterface : public QPlatformNativeInterface { @@ -59,7 +61,9 @@ public: Screen, GraphicsDevice, EglContext, - GLXContext + GLXContext, + AppTime, + AppUserTime }; QXcbNativeInterface(); @@ -69,6 +73,7 @@ public: void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window); NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource); + NativeResourceForScreenFunction nativeResourceFunctionForScreen(const QByteArray &resource) Q_DECL_OVERRIDE; inline const QByteArray &genericEventFilterType() const { return m_genericEventFilterType; } @@ -77,6 +82,10 @@ public: void *connectionForWindow(QWindow *window); void *screenForWindow(QWindow *window); void *graphicsDeviceForWindow(QWindow *window); + void *appTime(const QXcbScreen *screen); + void *appUserTime(const QXcbScreen *screen); + static void setAppTime(QScreen *screen, xcb_timestamp_t time); + static void setAppUserTime(QScreen *screen, xcb_timestamp_t time); static void *eglContextForContext(QOpenGLContext *context); static void *glxContextForContext(QOpenGLContext *context); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 0db4176607..528c4c6580 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -385,6 +385,10 @@ void QXcbWindow::create() #ifndef QT_NO_DRAGANDDROP connection()->drag()->dndEnable(this, true); #endif + + const qreal opacity = qt_window_private(window())->opacity; + if (!qFuzzyCompare(opacity, qreal(1.0))) + setOpacity(opacity); } QXcbWindow::~QXcbWindow() @@ -1024,6 +1028,7 @@ void QXcbWindow::updateNetWmStateBeforeMap() void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp) { xcb_window_t wid = m_window; + connection()->setNetWmUserTime(timestamp); const bool isSupportedByWM = connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW)); if (m_netWmUserTimeWindow || isSupportedByWM) { @@ -1112,7 +1117,18 @@ void QXcbWindow::setParent(const QPlatformWindow *parent) void QXcbWindow::setWindowTitle(const QString &title) { - QByteArray ba = title.toUtf8(); + QString fullTitle = title; + if (QGuiApplicationPrivate::displayName) { + // Append display name, if set. + if (!fullTitle.isEmpty()) + fullTitle += QString::fromUtf8(" \xe2\x80\x94 "); // unicode character U+2014, EM DASH + fullTitle += *QGuiApplicationPrivate::displayName; + } else if (fullTitle.isEmpty()) { + // Don't let the window title be completely empty, use the app name as fallback. + fullTitle = QCoreApplication::applicationName(); + } + const QByteArray ba = fullTitle.toUtf8(); + Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, @@ -1460,53 +1476,6 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event) } } -static Qt::MouseButtons translateMouseButtons(int s) -{ - Qt::MouseButtons ret = 0; - if (s & XCB_BUTTON_MASK_1) - ret |= Qt::LeftButton; - if (s & XCB_BUTTON_MASK_2) - ret |= Qt::MidButton; - if (s & XCB_BUTTON_MASK_3) - ret |= Qt::RightButton; - return ret; -} - -static Qt::MouseButton translateMouseButton(xcb_button_t s) -{ - switch (s) { - case 1: return Qt::LeftButton; - case 2: return Qt::MidButton; - case 3: return Qt::RightButton; - // Button values 4-7 were already handled as Wheel events, and won't occur here. - case 8: return Qt::BackButton; // Also known as Qt::ExtraButton1 - case 9: return Qt::ForwardButton; // Also known as Qt::ExtraButton2 - case 10: return Qt::ExtraButton3; - case 11: return Qt::ExtraButton4; - case 12: return Qt::ExtraButton5; - case 13: return Qt::ExtraButton6; - case 14: return Qt::ExtraButton7; - case 15: return Qt::ExtraButton8; - case 16: return Qt::ExtraButton9; - case 17: return Qt::ExtraButton10; - case 18: return Qt::ExtraButton11; - case 19: return Qt::ExtraButton12; - case 20: return Qt::ExtraButton13; - case 21: return Qt::ExtraButton14; - case 22: return Qt::ExtraButton15; - case 23: return Qt::ExtraButton16; - case 24: return Qt::ExtraButton17; - case 25: return Qt::ExtraButton18; - case 26: return Qt::ExtraButton19; - case 27: return Qt::ExtraButton20; - case 28: return Qt::ExtraButton21; - case 29: return Qt::ExtraButton22; - case 30: return Qt::ExtraButton23; - case 31: return Qt::ExtraButton24; - default: return Qt::NoButton; - } -} - void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) { updateNetWmUserTime(event->time); @@ -1528,7 +1497,7 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) return; } - handleMouseEvent(event->detail, event->state, event->time, local, global, modifiers); + handleMouseEvent(event->time, local, global, modifiers); } void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *event) @@ -1537,7 +1506,12 @@ void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *even QPoint global(event->root_x, event->root_y); Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); - handleMouseEvent(event->detail, event->state, event->time, local, global, modifiers); + if (event->detail >= 4 && event->detail <= 7) { + // mouse wheel, handled in handleButtonPressEvent() + return; + } + + handleMouseEvent(event->time, local, global, modifiers); } void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event) @@ -1546,19 +1520,13 @@ void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event) QPoint global(event->root_x, event->root_y); Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); - handleMouseEvent(event->detail, event->state, event->time, local, global, modifiers); + handleMouseEvent(event->time, local, global, modifiers); } -void QXcbWindow::handleMouseEvent(xcb_button_t detail, uint16_t state, xcb_timestamp_t time, const QPoint &local, const QPoint &global, Qt::KeyboardModifiers modifiers) +void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global, Qt::KeyboardModifiers modifiers) { connection()->setTime(time); - - Qt::MouseButtons buttons = translateMouseButtons(state); - Qt::MouseButton button = translateMouseButton(detail); - - buttons ^= button; // X event uses state *before*, Qt uses state *after* - - QWindowSystemInterface::handleMouseEvent(window(), time, local, global, buttons, modifiers); + QWindowSystemInterface::handleMouseEvent(window(), time, local, global, connection()->buttons(), modifiers); } class EnterEventChecker diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 07ac0e0fcb..b2c637281d 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -134,11 +134,10 @@ public: void handleFocusOutEvent(const xcb_focus_out_event_t *event); void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event); - void handleMouseEvent(xcb_button_t detail, uint16_t state, xcb_timestamp_t time, const QPoint &local, const QPoint &global, Qt::KeyboardModifiers modifiers); + void handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global, Qt::KeyboardModifiers modifiers); void updateSyncRequestCounter(); void updateNetWmUserTime(xcb_timestamp_t timestamp); - void netWmUserTime() const; #if defined(XCB_USE_EGL) QXcbEGLSurface *eglSurface() const; |