diff options
author | Alexander Volkov <a.volkov@rusbitech.ru> | 2016-02-25 14:39:51 +0300 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2016-12-08 12:41:04 +0000 |
commit | 2488f34ecfd68702b5508c50cca3fb8e967ac8ea (patch) | |
tree | 244cca0542cb34f8bd731e3af703013e3d09b241 /src/plugins | |
parent | d829dd3f445afae8c74630c4c8b93347b4a7c7bd (diff) | |
download | qtbase-2488f34ecfd68702b5508c50cca3fb8e967ac8ea.tar.gz |
xcb: Adapt QXcbWindow::startSystemResize() for touch events
Window managers typically grab the pointer after receiving
the _NET_WM_MOVERESIZE event. But they fail to do it for
touch sequences which have a receiver. So we should reject
the touch sequence before sending _NET_WM_MOVERESIZE event.
QSizeGrip calls startSystemResize() on MouseButtonPress event
which is synthesized by Qt on TouchBegin. We can find the id
of the touch point by comparing coordinates of the synthesized
MouseButtonPress event with coordinates of all TouchBegin events.
Then we use this id to reject the touch sequence (it's possible
only after receiving XI_TouchUpdate).
Change-Id: I26519840cd221e28b0be7854e4617c9aba4b0817
Task-number: QTBUG-51385
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 9 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 40 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 12 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.h | 2 |
4 files changed, 60 insertions, 3 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index cb337ea0da..60f0f487c5 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -504,6 +504,7 @@ public: #endif #ifdef XCB_USE_XINPUT22 + bool startSystemResizeForTouchBegin(xcb_window_t window, const QPoint &point, Qt::Corner corner); bool xi2SetMouseGrabEnabled(xcb_window_t w, bool grab); #endif Qt::MouseButton xiToQtMouseButton(uint32_t b); @@ -639,6 +640,14 @@ private: QXcbEventReader *m_reader; #if defined(XCB_USE_XINPUT2) QHash<int, XInput2TouchDeviceData*> m_touchDevices; +#ifdef XCB_USE_XINPUT22 + struct StartSystemResizeInfo { + xcb_window_t window; + uint16_t deviceid; + uint32_t pointid; + Qt::Corner corner; + } m_startSystemResizeInfo; +#endif #endif #ifdef Q_XCB_DEBUG struct CallInfo { diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 93f8db92bf..0ace79a4f5 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -61,9 +61,9 @@ struct XInput2TouchDeviceData { XIDeviceInfo *xiDeviceInfo; QTouchDevice *qtTouchDevice; QHash<int, QWindowSystemInterface::TouchPoint> touchPoints; + QHash<int, QPointF> pointPressedPosition; // in screen coordinates where each point was pressed // Stuff that is relevant only for touchpads - QHash<int, QPointF> pointPressedPosition; // in screen coordinates where each point was pressed QPointF firstPressedPosition; // in screen coordinates where the first point was pressed QPointF firstPressedNormalPosition; // device coordinates (0 to 1, 0 to 1) where the first point was pressed QSizeF size; // device size in mm @@ -93,6 +93,7 @@ void QXcbConnection::initializeXInput2() if (m_xi2Enabled) { #ifdef XCB_USE_XINPUT22 qCDebug(lcQpaXInputDevices, "XInput version %d.%d is available and Qt supports 2.2 or greater", xiMajor, m_xi2Minor); + m_startSystemResizeInfo.window = XCB_NONE; #else qCDebug(lcQpaXInputDevices, "XInput version %d.%d is available and Qt supports 2.0", xiMajor, m_xi2Minor); #endif @@ -714,7 +715,21 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo touchPoint.state = Qt::TouchPointMoved; } else if (touchPoint.area.center() != QPoint(x, y)) { touchPoint.state = Qt::TouchPointMoved; - dev->pointPressedPosition[touchPoint.id] = QPointF(x, y); + if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad) + dev->pointPressedPosition[touchPoint.id] = QPointF(x, y); + } + + if (dev->qtTouchDevice->type() == QTouchDevice::TouchScreen && + xiDeviceEvent->event == m_startSystemResizeInfo.window && + xiDeviceEvent->sourceid == m_startSystemResizeInfo.deviceid && + xiDeviceEvent->detail == m_startSystemResizeInfo.pointid) { + QXcbWindow *window = platformWindowFromId(m_startSystemResizeInfo.window); + if (window) { + XIAllowTouchEvents(static_cast<Display *>(m_xlib_display), xiDeviceEvent->deviceid, + xiDeviceEvent->detail, xiDeviceEvent->event, XIRejectTouch); + window->doStartSystemResize(QPoint(x, y), m_startSystemResizeInfo.corner); + m_startSystemResizeInfo.window = XCB_NONE; + } } break; case XI_TouchEnd: @@ -745,6 +760,27 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo touchPoint.state = Qt::TouchPointStationary; } +bool QXcbConnection::startSystemResizeForTouchBegin(xcb_window_t window, const QPoint &point, Qt::Corner corner) +{ + QHash<int, XInput2TouchDeviceData*>::const_iterator devIt = m_touchDevices.constBegin(); + for (; devIt != m_touchDevices.constEnd(); ++devIt) { + XInput2TouchDeviceData *deviceData = devIt.value(); + if (deviceData->qtTouchDevice->type() == QTouchDevice::TouchScreen) { + QHash<int, QPointF>::const_iterator pointIt = deviceData->pointPressedPosition.constBegin(); + for (; pointIt != deviceData->pointPressedPosition.constEnd(); ++pointIt) { + if (pointIt.value().toPoint() == point) { + m_startSystemResizeInfo.window = window; + m_startSystemResizeInfo.deviceid = devIt.key(); + m_startSystemResizeInfo.pointid = pointIt.key(); + m_startSystemResizeInfo.corner = corner; + return true; + } + } + } + } + return false; +} + bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab) { if (grab && !canGrab()) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 0c8e78491e..5fa8541f26 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2738,13 +2738,23 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE); if (!connection()->wmSupport()->isSupportedByWM(moveResize)) return false; + const QPoint globalPos = window()->mapToGlobal(pos); +#ifdef XCB_USE_XINPUT22 + if (connection()->startSystemResizeForTouchBegin(m_window, globalPos, corner)) + return true; +#endif + return doStartSystemResize(globalPos, corner); +} + +bool QXcbWindow::doStartSystemResize(const QPoint &globalPos, Qt::Corner corner) +{ + const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE); xcb_client_message_event_t xev; xev.response_type = XCB_CLIENT_MESSAGE; xev.type = moveResize; xev.sequence = 0; xev.window = xcb_window(); xev.format = 32; - const QPoint globalPos = window()->mapToGlobal(pos); xev.data.data32[0] = globalPos.x(); xev.data.data32[1] = globalPos.y(); const bool bottom = corner == Qt::BottomRightCorner || corner == Qt::BottomLeftCorner; diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 3d8d21be6b..089df8f3f6 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -178,6 +178,8 @@ public: QXcbScreen *xcbScreen() const; + bool doStartSystemResize(const QPoint &globalPos, Qt::Corner corner); + virtual void create(); virtual void destroy(); |