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>
This commit is contained in:
parent
d829dd3f44
commit
2488f34ecf
@ -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 {
|
||||
|
@ -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())
|
||||
|
@ -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;
|
||||
|
@ -178,6 +178,8 @@ public:
|
||||
|
||||
QXcbScreen *xcbScreen() const;
|
||||
|
||||
bool doStartSystemResize(const QPoint &globalPos, Qt::Corner corner);
|
||||
|
||||
virtual void create();
|
||||
virtual void destroy();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user