From 6977700bed929c7f1a20192d07a06abc2fdca278 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 10 Apr 2014 15:51:56 +0200 Subject: Disable threaded rendering if Mesa is used Mesa and xcb show some bad interaction which leads to frequent crashed on multithreaded access. Also, the selective approach to blacklisting only specific chipsets isn't feasible, given the resources available. The client glx vendor string is used to identify mesa instead of the server GL vendor and/or renderer string as that is much more reliable. Task-number: QTBUG-38221 Change-Id: I2d8c037aa4fd9c38eb9537452a5e7e62f72a081d Reviewed-by: Gunnar Sletta --- src/plugins/platforms/xcb/qglxintegration.cpp | 28 +++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index c183deb3b8..f78d3bcc4e 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -449,12 +449,32 @@ bool QGLXContext::m_supportsThreading = true; // binary search. static const char *qglx_threadedgl_blacklist_renderer[] = { "Chromium", // QTBUG-32225 (initialization fails) - "Mesa DRI Intel(R) Sandybridge Mobile", // QTBUG-34492 (flickering in fullscreen) 0 }; +// This disables threaded rendering on anything using mesa, e.g. +// - nvidia/nouveau +// - amd/gallium +// - intel +// - some software opengl implementations +// +// The client glx vendor string is used to identify those setups as that seems to show the least +// variance between the bad configurations. It's always "Mesa Project and SGI". There are some +// configurations which don't use mesa and which can do threaded rendering (amd and nvidia chips +// with their own proprietary drivers). +// +// This, of course, is very broad and disables threaded rendering on a lot of devices which would +// be able to use it. However, the bugs listed below don't follow any easily recognizable pattern +// and we should rather be safe. +// +// http://cgit.freedesktop.org/xcb/libxcb/commit/?id=be0fe56c3bcad5124dcc6c47a2fad01acd16f71a will +// fix some of the issues. Basically, the proprietary drivers seem to have a way of working around +// a fundamental flaw with multithreaded access to xcb, but mesa doesn't. The blacklist should be +// reevaluated once that patch is released in some version of xcb. static const char *qglx_threadedgl_blacklist_vendor[] = { - "nouveau", // QTCREATORBUG-10875 (crash in creator) + "Mesa Project and SGI", // QTCREATORBUG-10875 (crash in creator) + // QTBUG-34492 (flickering in fullscreen) + // QTBUG-38221 0 }; @@ -502,9 +522,9 @@ void QGLXContext::queryDummyContext() } } - if (const char *vendor = (const char *) glGetString(GL_VENDOR)) { + if (glxvendor) { for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) { - if (strstr(vendor, qglx_threadedgl_blacklist_vendor[i]) != 0) { + if (strstr(glxvendor, qglx_threadedgl_blacklist_vendor[i]) != 0) { m_supportsThreading = false; break; } -- cgit v1.2.3 From 53a5dd28c728fba49b01adbcaba610d12cfcde4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Tue, 8 Apr 2014 10:18:18 +0200 Subject: Handle parent is None from query_tree_reply in QxcbWindow::frameMargins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit None is a valid return value for parent in xcb_query_tree_reply_t. If that is used as the new parent the next call to xcb_query_tree_unchecked will fail with a BadWindow error. Change-Id: Iafe29b223ca65c86ecfd40fe51e67d4bd7abc1ce Reviewed-by: Jørgen Lind Reviewed-by: Uli Schlachter --- src/plugins/platforms/xcb/qxcbwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 5a2002f1d4..193e75c1d6 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -554,7 +554,7 @@ QMargins QXcbWindow::frameMargins() const xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, NULL); if (reply) { - if (reply->root == reply->parent || virtualRoots.indexOf(reply->parent) != -1) { + if (reply->root == reply->parent || virtualRoots.indexOf(reply->parent) != -1 || reply->parent == XCB_WINDOW_NONE) { foundRoot = true; } else { window = parent; -- cgit v1.2.3 From fb7da5cc8c13bbf9a134306c1d290d34373687b0 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 11 Apr 2014 12:09:59 +0200 Subject: Reload lastScrollPosition on window enter We need the lastScrollPosition position to calculated scrolling deltas on scroll events. Since the position is tied to the device and might have changed while scroll events were send to other applications we need to reload the value when mouse focus reenters our application. Task-number: QTBUG-38274 Change-Id: Ic166648f8e7ae486288cbed339a057e3faa1ef2d Reviewed-by: Laszlo Agocs Reviewed-by: Daniel Teske Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.h | 4 ++++ src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 29 ++++++++++++++++++++++++ src/plugins/platforms/xcb/qxcbwindow.cpp | 3 +++ 3 files changed, 36 insertions(+) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index a994c51c7d..13a0280baf 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -454,6 +454,10 @@ public: QXcbSystemTrayTracker *systemTrayTracker(); +#ifdef XCB_USE_XINPUT2 + void handleEnterEvent(const xcb_enter_notify_event_t *); +#endif + private slots: void processXcbEvents(); diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index d80b49ccbb..d7b3c75aee 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -524,6 +524,35 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) } } +void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *) +{ +#ifdef XCB_USE_XINPUT21 + QHash::iterator it = m_scrollingDevices.begin(); + const QHash::iterator end = m_scrollingDevices.end(); + while (it != end) { + ScrollingDevice& scrollingDevice = it.value(); + int nrDevices = 0; + XIDeviceInfo* xiDeviceInfo = XIQueryDevice(static_cast(m_xlib_display), scrollingDevice.deviceId, &nrDevices); + if (nrDevices <= 0) { + it = m_scrollingDevices.erase(it); + continue; + } + for (int c = 0; c < xiDeviceInfo->num_classes; ++c) { + if (xiDeviceInfo->classes[c]->type == XIValuatorClass) { + XIValuatorClassInfo *vci = reinterpret_cast(xiDeviceInfo->classes[c]); + const int valuatorAtom = qatom(vci->label); + if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel) + scrollingDevice.lastScrollPosition.setX(vci->value); + else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel) + scrollingDevice.lastScrollPosition.setY(vci->value); + } + } + XIFreeDeviceInfo(xiDeviceInfo); + ++it; + } +#endif +} + void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice) { #ifdef XCB_USE_XINPUT21 diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 5a2002f1d4..ad7e99bd49 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1778,6 +1778,9 @@ public: void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event) { connection()->setTime(event->time); +#ifdef XCB_USE_XINPUT2 + connection()->handleEnterEvent(event); +#endif if ((event->mode != XCB_NOTIFY_MODE_NORMAL && event->mode != XCB_NOTIFY_MODE_UNGRAB) || event->detail == XCB_NOTIFY_DETAIL_VIRTUAL -- cgit v1.2.3 From 50b8506eaccc3c9bc3d717b241193bc8be9708b0 Mon Sep 17 00:00:00 2001 From: Jorgen Lind Date: Thu, 3 Apr 2014 13:11:59 +0200 Subject: XCB: fix that modal dialogs can go behind other process windows Task-number: QTBUG-35302 Change-Id: I1ad7a66e530710d5338a15057254360dae676451 Reviewed-by: Friedemann Kleint Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbwindow.cpp | 104 +++++++++++++++++++++---------- src/plugins/platforms/xcb/qxcbwindow.h | 4 ++ 2 files changed, 75 insertions(+), 33 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 193e75c1d6..dbffd577c1 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -485,7 +485,7 @@ QXcbWindow::~QXcbWindow() void QXcbWindow::destroy() { if (connection()->focusWindow() == this) - connection()->setFocusWindow(0); + doFocusOut(); if (m_syncCounter && m_usingSyncProtocol) Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter)); @@ -671,6 +671,9 @@ void QXcbWindow::show() Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); + if (QGuiApplication::modalWindow() == window()) + requestActivateWindow(); + m_screen->windowShown(this); connection()->sync(); @@ -694,6 +697,68 @@ void QXcbWindow::hide() m_mapped = false; } +static QWindow *tlWindow(QWindow *window) +{ + if (window && window->parent()) + return tlWindow(window->parent()); + return window; +} + +bool QXcbWindow::relayFocusToModalWindow() const +{ + QWindow *w = tlWindow(static_cast(QObjectPrivate::get(window()))->eventReceiver()); + QWindow *modal_window = 0; + if (QGuiApplicationPrivate::instance()->isWindowBlocked(w,&modal_window) && modal_window != w) { + modal_window->requestActivate(); + connection()->flush(); + return true; + } + + return false; +} + +void QXcbWindow::doFocusIn() +{ + if (relayFocusToModalWindow()) + return; + QWindow *w = static_cast(QObjectPrivate::get(window()))->eventReceiver(); + connection()->setFocusWindow(static_cast(w->handle())); + QWindowSystemInterface::handleWindowActivated(w, Qt::ActiveWindowFocusReason); +} + +static bool focusInPeeker(QXcbConnection *connection, xcb_generic_event_t *event) +{ + if (!event) { + // FocusIn event is not in the queue, proceed with FocusOut normally. + QWindowSystemInterface::handleWindowActivated(0, Qt::ActiveWindowFocusReason); + return true; + } + uint response_type = event->response_type & ~0x80; + if (response_type == XCB_FOCUS_IN) + return true; + + /* We are also interested in XEMBED_FOCUS_IN events */ + if (response_type == XCB_CLIENT_MESSAGE) { + xcb_client_message_event_t *cme = (xcb_client_message_event_t *)event; + if (cme->type == connection->atom(QXcbAtom::_XEMBED) + && cme->data.data32[1] == XEMBED_FOCUS_IN) + return true; + } + + return false; +} + +void QXcbWindow::doFocusOut() +{ + if (relayFocusToModalWindow()) + return; + connection()->setFocusWindow(0); + // Do not set the active window to 0 if there is a FocusIn coming. + // There is however no equivalent for XPutBackEvent so register a + // callback for QXcbConnection instead. + connection()->addPeekFunc(focusInPeeker); +} + struct QtMotifWmHints { quint32 flags, functions, decorations; qint32 input_mode; @@ -1514,6 +1579,8 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even QWindowSystemInterface::handleCloseEvent(window()); } else if (event->data.data32[0] == atom(QXcbAtom::WM_TAKE_FOCUS)) { connection()->setTime(event->data.data32[1]); + relayFocusToModalWindow(); + return; } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_PING)) { if (event->window == m_screen->root()) return; @@ -1549,8 +1616,7 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even } else if (event->type == atom(QXcbAtom::_XEMBED)) { handleXEmbedMessage(event); } else if (event->type == atom(QXcbAtom::_NET_ACTIVE_WINDOW)) { - connection()->setFocusWindow(this); - QWindowSystemInterface::handleWindowActivated(window(), Qt::ActiveWindowFocusReason); + doFocusIn(); } else if (event->type == atom(QXcbAtom::MANAGER) || event->type == atom(QXcbAtom::_NET_WM_STATE) || event->type == atom(QXcbAtom::WM_CHANGE_STATE)) { @@ -1865,41 +1931,13 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *) { - QWindow *w = window(); - w = static_cast(QObjectPrivate::get(w))->eventReceiver(); - connection()->setFocusWindow(static_cast(w->handle())); - QWindowSystemInterface::handleWindowActivated(w, Qt::ActiveWindowFocusReason); + doFocusIn(); } -static bool focusInPeeker(QXcbConnection *connection, xcb_generic_event_t *event) -{ - if (!event) { - // FocusIn event is not in the queue, proceed with FocusOut normally. - QWindowSystemInterface::handleWindowActivated(0, Qt::ActiveWindowFocusReason); - return true; - } - uint response_type = event->response_type & ~0x80; - if (response_type == XCB_FOCUS_IN) - return true; - - /* We are also interested in XEMBED_FOCUS_IN events */ - if (response_type == XCB_CLIENT_MESSAGE) { - xcb_client_message_event_t *cme = (xcb_client_message_event_t *)event; - if (cme->type == connection->atom(QXcbAtom::_XEMBED) - && cme->data.data32[1] == XEMBED_FOCUS_IN) - return true; - } - - return false; -} void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *) { - connection()->setFocusWindow(0); - // Do not set the active window to 0 if there is a FocusIn coming. - // There is however no equivalent for XPutBackEvent so register a - // callback for QXcbConnection instead. - connection()->addPeekFunc(focusInPeeker); + doFocusOut(); } void QXcbWindow::updateSyncRequestCounter() diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index a90ad7b5ed..12d17023fb 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -176,6 +176,10 @@ private: void show(); void hide(); + bool relayFocusToModalWindow() const; + void doFocusIn(); + void doFocusOut(); + QXcbScreen *m_screen; xcb_window_t m_window; -- cgit v1.2.3 From bbcdccd6768f999a49717dfc78efd4bb9d880412 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 16 Apr 2014 21:18:27 +0200 Subject: deprecate import_qpa_plugin and qpa_minimal_plugin they have been fully superseded by 4255ba40ab073afcf2a095b135883612859af4c2. Change-Id: If7ac14c8b7d3cf00fb0cb916036b62eb86c9cee0 Reviewed-by: Joerg Bornemann Reviewed-by: Oswald Buddenhagen --- src/plugins/platforms/xcb/xcb-plugin.pro | 1 + 1 file changed, 1 insertion(+) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro index 9e4e997f55..a52aaa4a2e 100644 --- a/src/plugins/platforms/xcb/xcb-plugin.pro +++ b/src/plugins/platforms/xcb/xcb-plugin.pro @@ -2,6 +2,7 @@ TARGET = qxcb PLUGIN_TYPE = platforms PLUGIN_CLASS_NAME = QXcbIntegrationPlugin +!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = - load(qt_plugin) QT += core-private gui-private platformsupport-private -- cgit v1.2.3 From 55d1aa3121063fcb41f8f4500c4319b64ca8ee67 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 24 Apr 2014 14:53:50 +0200 Subject: Use runtime detection of XInput 2.1 to disable legacy wheel events Ensure we fall back to using wheel button events if xinput 2.1 scroll events are not available. Handles lack of xinput 2.1 support in the server or in the input devices drivers. Task-number: QTBUG-38169 Change-Id: Ie4ad9069f648d0ab02d8f9540ed01ad58fd9e9d8 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbconnection.cpp | 13 +++++++ src/plugins/platforms/xcb/qxcbconnection.h | 10 +++++- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 46 ++++++++++++++++++++++-- src/plugins/platforms/xcb/qxcbwindow.cpp | 20 +++++------ 4 files changed, 76 insertions(+), 13 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index f5f6c712c5..e3b81c2b40 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1791,6 +1791,19 @@ bool QXcbConnection::xi2GetValuatorValueIfSet(void *event, int valuatorNum, doub return true; } +bool QXcbConnection::xi2GetButtonState(void *event, int buttonNum) +{ + xXIDeviceEvent *xideviceevent = static_cast(event); + unsigned char *buttonsMaskAddr = (unsigned char*)&xideviceevent[1]; + + for (int i = 0; i < (xideviceevent->buttons_len * 4); i++) { + if (buttonNum < 8) + return (buttonsMaskAddr[i] & (1 << buttonNum)); + buttonNum -= 8; + } + return false; +} + // Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed: // - "pad0" became "extension" // - "pad1" and "pad" became "pad0" diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 13a0280baf..1933b89a19 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -402,6 +402,12 @@ public: #elif defined(XCB_USE_XINPUT2) void xi2Select(xcb_window_t window); #endif +#ifdef XCB_USE_XINPUT21 + bool isUsingXInput21() { return m_xi2Enabled && m_xi2Minor >= 1; } +#else + bool isUsingXInput21() { return false; } +#endif + void sync(); void flush() { xcb_flush(m_connection); } @@ -511,11 +517,12 @@ private: QVector m_tabletData; #endif struct ScrollingDevice { - ScrollingDevice() : deviceId(0), verticalIndex(0), horizontalIndex(0), orientations(0) { } + ScrollingDevice() : deviceId(0), verticalIndex(0), horizontalIndex(0), orientations(0), legacyOrientations(0) { } int deviceId; int verticalIndex, horizontalIndex; double verticalIncrement, horizontalIncrement; Qt::Orientations orientations; + Qt::Orientations legacyOrientations; QPointF lastScrollPosition; }; void xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice); @@ -525,6 +532,7 @@ private: #if defined(XCB_USE_XINPUT2) || defined(XCB_USE_XINPUT2_MAEMO) static bool xi2GetValuatorValueIfSet(void *event, int valuatorNum, double *value); static bool xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event, int opCode); + static bool xi2GetButtonState(void *event, int buttonNum); #endif xcb_connection_t *m_connection; diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index d7b3c75aee..831ccba6f6 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -134,7 +134,6 @@ void QXcbConnection::initializeXInput2() #ifdef XCB_USE_XINPUT21 case XIScrollClass: { XIScrollClassInfo *sci = reinterpret_cast(devices[i].classes[c]); - scrollingDevice.deviceId = devices[i].deviceid; if (sci->scroll_type == XIScrollTypeVertical) { scrollingDevice.orientations |= Qt::Vertical; scrollingDevice.verticalIndex = sci->number; @@ -147,6 +146,20 @@ void QXcbConnection::initializeXInput2() } break; } + case XIButtonClass: { + XIButtonClassInfo *bci = reinterpret_cast(devices[i].classes[c]); + for (int i=0; i < bci->num_buttons; ++i) { + const int buttonAtom = qatom(bci->labels[i]); + if (buttonAtom == QXcbAtom::ButtonWheelUp + || buttonAtom == QXcbAtom::ButtonWheelDown) { + scrollingDevice.legacyOrientations |= Qt::Vertical; + } else if (buttonAtom == QXcbAtom::ButtonHorizWheelLeft + || buttonAtom == QXcbAtom::ButtonHorizWheelRight) { + scrollingDevice.legacyOrientations |= Qt::Horizontal; + } + } + break; + } #endif default: break; @@ -170,7 +183,10 @@ void QXcbConnection::initializeXInput2() #endif // QT_NO_TABLETEVENT #ifdef XCB_USE_XINPUT21 - if (scrollingDevice.orientations) { + if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) { + scrollingDevice.deviceId = devices[i].deviceid; + // Only use legacy wheel button events when we don't have real scroll valuators. + scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations; m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice); if (Q_UNLIKELY(debug_xinput_devices)) qDebug() << " it's a scrolling device"; @@ -256,6 +272,7 @@ void QXcbConnection::xi2Select(xcb_window_t window) if (!m_scrollingDevices.isEmpty()) { QVector xiEventMask(m_scrollingDevices.size()); bitMask = XI_MotionMask; + bitMask |= XI_ButtonReleaseMask; int i=0; Q_FOREACH (const ScrollingDevice& scrollingDevice, m_scrollingDevices) { xiEventMask[i].deviceid = scrollingDevice.deviceId; @@ -595,6 +612,31 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiEvent->time, local, global, rawDelta, angleDelta, modifiers); } } + } else if (xiEvent->evtype == XI_ButtonRelease) { + xXIDeviceEvent* xiDeviceEvent = reinterpret_cast(event); + if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) { + QPoint angleDelta; + if (scrollingDevice.legacyOrientations & Qt::Vertical) { + if (xi2GetButtonState(xiDeviceEvent, 4)) + angleDelta.setY(120); + else if (xi2GetButtonState(xiDeviceEvent, 5)) + angleDelta.setY(-120); + } + if (scrollingDevice.legacyOrientations & Qt::Horizontal) { + if (xi2GetButtonState(xiDeviceEvent, 6)) + angleDelta.setX(120); + if (xi2GetButtonState(xiDeviceEvent, 7)) + angleDelta.setX(-120); + } + if (!angleDelta.isNull()) { + QPoint local(fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y)); + QPoint global(fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y)); + Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective_mods); + if (modifiers & Qt::AltModifier) + std::swap(angleDelta.rx(), angleDelta.ry()); + QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiEvent->time, local, global, QPoint(), angleDelta, modifiers); + } + } } #else Q_UNUSED(event); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index ad7e99bd49..386bf16c16 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1705,16 +1705,16 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); if (isWheel) { -#ifndef XCB_USE_XINPUT21 - // Logic borrowed from qapplication_x11.cpp - int delta = 120 * ((event->detail == 4 || event->detail == 6) ? 1 : -1); - bool hor = (((event->detail == 4 || event->detail == 5) - && (modifiers & Qt::AltModifier)) - || (event->detail == 6 || event->detail == 7)); - - QWindowSystemInterface::handleWheelEvent(window(), event->time, - local, global, delta, hor ? Qt::Horizontal : Qt::Vertical, modifiers); -#endif + if (!connection()->isUsingXInput21()) { + // Logic borrowed from qapplication_x11.cpp + int delta = 120 * ((event->detail == 4 || event->detail == 6) ? 1 : -1); + bool hor = (((event->detail == 4 || event->detail == 5) + && (modifiers & Qt::AltModifier)) + || (event->detail == 6 || event->detail == 7)); + + QWindowSystemInterface::handleWheelEvent(window(), event->time, + local, global, delta, hor ? Qt::Horizontal : Qt::Vertical, modifiers); + } return; } -- cgit v1.2.3