QPlatformWindow: add startSystemMove()
It can be used by custom widgets or for example by the Breeze style from KDE, which allows to drag windows by some widgets. It's important on X11 because _NET_WM_MOVERESIZE requests induced by touch sequences require support from Qt. Task-number: QTBUG-58044 Change-Id: I31c37534555a9050cf361cad85bdef13c2808572 Reviewed-by: Johan Helsing <johan.helsing@qt.io> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
parent
a16d0074b9
commit
6f03740a19
@ -474,6 +474,25 @@ bool QPlatformWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Reimplement this method to start a system move operation if
|
||||||
|
the system supports it and return true to indicate success.
|
||||||
|
|
||||||
|
The \a pos is a position of MouseButtonPress event or TouchBegin
|
||||||
|
event from a sequence of mouse events that triggered the movement.
|
||||||
|
It must be specified in window coordinates.
|
||||||
|
|
||||||
|
The default implementation is empty and does nothing with \a pos.
|
||||||
|
|
||||||
|
\since 5.11
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool QPlatformWindow::startSystemMove(const QPoint &pos)
|
||||||
|
{
|
||||||
|
Q_UNUSED(pos)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Reimplement this method to set whether frame strut events
|
Reimplement this method to set whether frame strut events
|
||||||
should be sent to \a enabled.
|
should be sent to \a enabled.
|
||||||
|
@ -129,6 +129,7 @@ public:
|
|||||||
virtual void windowEvent(QEvent *event);
|
virtual void windowEvent(QEvent *event);
|
||||||
|
|
||||||
virtual bool startSystemResize(const QPoint &pos, Qt::Corner corner);
|
virtual bool startSystemResize(const QPoint &pos, Qt::Corner corner);
|
||||||
|
virtual bool startSystemMove(const QPoint &pos);
|
||||||
|
|
||||||
virtual void setFrameStrutEventsEnabled(bool enabled);
|
virtual void setFrameStrutEventsEnabled(bool enabled);
|
||||||
virtual bool frameStrutEventsEnabled() const;
|
virtual bool frameStrutEventsEnabled() const;
|
||||||
|
@ -523,7 +523,7 @@ public:
|
|||||||
void xi2UpdateScrollingDevices();
|
void xi2UpdateScrollingDevices();
|
||||||
#endif
|
#endif
|
||||||
#ifdef XCB_USE_XINPUT22
|
#ifdef XCB_USE_XINPUT22
|
||||||
bool startSystemResizeForTouchBegin(xcb_window_t window, const QPoint &point, Qt::Corner corner);
|
bool startSystemMoveResizeForTouchBegin(xcb_window_t window, const QPoint &point, int corner);
|
||||||
bool isTouchScreen(int id);
|
bool isTouchScreen(int id);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -676,12 +676,12 @@ private:
|
|||||||
#if QT_CONFIG(xinput2)
|
#if QT_CONFIG(xinput2)
|
||||||
QHash<int, TouchDeviceData> m_touchDevices;
|
QHash<int, TouchDeviceData> m_touchDevices;
|
||||||
#ifdef XCB_USE_XINPUT22
|
#ifdef XCB_USE_XINPUT22
|
||||||
struct StartSystemResizeInfo {
|
struct StartSystemMoveResizeInfo {
|
||||||
xcb_window_t window = XCB_NONE;
|
xcb_window_t window = XCB_NONE;
|
||||||
uint16_t deviceid;
|
uint16_t deviceid;
|
||||||
uint32_t pointid;
|
uint32_t pointid;
|
||||||
Qt::Corner corner;
|
int corner;
|
||||||
} m_startSystemResizeInfo;
|
} m_startSystemMoveResizeInfo;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
WindowMapper m_mapper;
|
WindowMapper m_mapper;
|
||||||
|
@ -784,15 +784,15 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dev->qtTouchDevice->type() == QTouchDevice::TouchScreen &&
|
if (dev->qtTouchDevice->type() == QTouchDevice::TouchScreen &&
|
||||||
xiDeviceEvent->event == m_startSystemResizeInfo.window &&
|
xiDeviceEvent->event == m_startSystemMoveResizeInfo.window &&
|
||||||
xiDeviceEvent->sourceid == m_startSystemResizeInfo.deviceid &&
|
xiDeviceEvent->sourceid == m_startSystemMoveResizeInfo.deviceid &&
|
||||||
xiDeviceEvent->detail == m_startSystemResizeInfo.pointid) {
|
xiDeviceEvent->detail == m_startSystemMoveResizeInfo.pointid) {
|
||||||
QXcbWindow *window = platformWindowFromId(m_startSystemResizeInfo.window);
|
QXcbWindow *window = platformWindowFromId(m_startSystemMoveResizeInfo.window);
|
||||||
if (window) {
|
if (window) {
|
||||||
XIAllowTouchEvents(static_cast<Display *>(m_xlib_display), xiDeviceEvent->deviceid,
|
XIAllowTouchEvents(static_cast<Display *>(m_xlib_display), xiDeviceEvent->deviceid,
|
||||||
xiDeviceEvent->detail, xiDeviceEvent->event, XIRejectTouch);
|
xiDeviceEvent->detail, xiDeviceEvent->event, XIRejectTouch);
|
||||||
window->doStartSystemResize(QPoint(x, y), m_startSystemResizeInfo.corner);
|
window->doStartSystemMoveResize(QPoint(x, y), m_startSystemMoveResizeInfo.corner);
|
||||||
m_startSystemResizeInfo.window = XCB_NONE;
|
m_startSystemMoveResizeInfo.window = XCB_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -825,7 +825,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
|
|||||||
touchPoint.state = Qt::TouchPointStationary;
|
touchPoint.state = Qt::TouchPointStationary;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QXcbConnection::startSystemResizeForTouchBegin(xcb_window_t window, const QPoint &point, Qt::Corner corner)
|
bool QXcbConnection::startSystemMoveResizeForTouchBegin(xcb_window_t window, const QPoint &point, int corner)
|
||||||
{
|
{
|
||||||
QHash<int, TouchDeviceData>::const_iterator devIt = m_touchDevices.constBegin();
|
QHash<int, TouchDeviceData>::const_iterator devIt = m_touchDevices.constBegin();
|
||||||
for (; devIt != m_touchDevices.constEnd(); ++devIt) {
|
for (; devIt != m_touchDevices.constEnd(); ++devIt) {
|
||||||
@ -834,10 +834,10 @@ bool QXcbConnection::startSystemResizeForTouchBegin(xcb_window_t window, const Q
|
|||||||
QHash<int, QPointF>::const_iterator pointIt = deviceData.pointPressedPosition.constBegin();
|
QHash<int, QPointF>::const_iterator pointIt = deviceData.pointPressedPosition.constBegin();
|
||||||
for (; pointIt != deviceData.pointPressedPosition.constEnd(); ++pointIt) {
|
for (; pointIt != deviceData.pointPressedPosition.constEnd(); ++pointIt) {
|
||||||
if (pointIt.value().toPoint() == point) {
|
if (pointIt.value().toPoint() == point) {
|
||||||
m_startSystemResizeInfo.window = window;
|
m_startSystemMoveResizeInfo.window = window;
|
||||||
m_startSystemResizeInfo.deviceid = devIt.key();
|
m_startSystemMoveResizeInfo.deviceid = devIt.key();
|
||||||
m_startSystemResizeInfo.pointid = pointIt.key();
|
m_startSystemMoveResizeInfo.pointid = pointIt.key();
|
||||||
m_startSystemResizeInfo.corner = corner;
|
m_startSystemMoveResizeInfo.corner = corner;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2639,19 +2639,29 @@ void QXcbWindow::windowEvent(QEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
|
bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
|
||||||
|
{
|
||||||
|
return startSystemMoveResize(pos, corner);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QXcbWindow::startSystemMove(const QPoint &pos)
|
||||||
|
{
|
||||||
|
return startSystemMoveResize(pos, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner)
|
||||||
{
|
{
|
||||||
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
|
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
|
||||||
if (!connection()->wmSupport()->isSupportedByWM(moveResize))
|
if (!connection()->wmSupport()->isSupportedByWM(moveResize))
|
||||||
return false;
|
return false;
|
||||||
const QPoint globalPos = QHighDpi::toNativePixels(window()->mapToGlobal(pos), window()->screen());
|
const QPoint globalPos = QHighDpi::toNativePixels(window()->mapToGlobal(pos), window()->screen());
|
||||||
#ifdef XCB_USE_XINPUT22
|
#ifdef XCB_USE_XINPUT22
|
||||||
if (connection()->startSystemResizeForTouchBegin(m_window, globalPos, corner))
|
if (connection()->startSystemMoveResizeForTouchBegin(m_window, globalPos, corner))
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
return doStartSystemResize(globalPos, corner);
|
return doStartSystemMoveResize(globalPos, corner);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QXcbWindow::doStartSystemResize(const QPoint &globalPos, Qt::Corner corner)
|
bool QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int corner)
|
||||||
{
|
{
|
||||||
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
|
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
|
||||||
xcb_client_message_event_t xev;
|
xcb_client_message_event_t xev;
|
||||||
@ -2662,12 +2672,16 @@ bool QXcbWindow::doStartSystemResize(const QPoint &globalPos, Qt::Corner corner)
|
|||||||
xev.format = 32;
|
xev.format = 32;
|
||||||
xev.data.data32[0] = globalPos.x();
|
xev.data.data32[0] = globalPos.x();
|
||||||
xev.data.data32[1] = globalPos.y();
|
xev.data.data32[1] = globalPos.y();
|
||||||
const bool bottom = corner == Qt::BottomRightCorner || corner == Qt::BottomLeftCorner;
|
if (corner == 4) {
|
||||||
const bool left = corner == Qt::BottomLeftCorner || corner == Qt::TopLeftCorner;
|
xev.data.data32[2] = 8; // move
|
||||||
if (bottom)
|
} else {
|
||||||
xev.data.data32[2] = left ? 6 : 4; // bottomleft/bottomright
|
const bool bottom = corner == Qt::BottomRightCorner || corner == Qt::BottomLeftCorner;
|
||||||
else
|
const bool left = corner == Qt::BottomLeftCorner || corner == Qt::TopLeftCorner;
|
||||||
xev.data.data32[2] = left ? 0 : 2; // topleft/topright
|
if (bottom)
|
||||||
|
xev.data.data32[2] = left ? 6 : 4; // bottomleft/bottomright
|
||||||
|
else
|
||||||
|
xev.data.data32[2] = left ? 0 : 2; // topleft/topright
|
||||||
|
}
|
||||||
xev.data.data32[3] = XCB_BUTTON_INDEX_1;
|
xev.data.data32[3] = XCB_BUTTON_INDEX_1;
|
||||||
xev.data.data32[4] = 0;
|
xev.data.data32[4] = 0;
|
||||||
xcb_ungrab_pointer(connection()->xcb_connection(), XCB_CURRENT_TIME);
|
xcb_ungrab_pointer(connection()->xcb_connection(), XCB_CURRENT_TIME);
|
||||||
|
@ -110,6 +110,7 @@ public:
|
|||||||
void windowEvent(QEvent *event) override;
|
void windowEvent(QEvent *event) override;
|
||||||
|
|
||||||
bool startSystemResize(const QPoint &pos, Qt::Corner corner) override;
|
bool startSystemResize(const QPoint &pos, Qt::Corner corner) override;
|
||||||
|
bool startSystemMove(const QPoint &pos) override;
|
||||||
|
|
||||||
void setOpacity(qreal level) override;
|
void setOpacity(qreal level) override;
|
||||||
void setMask(const QRegion ®ion) override;
|
void setMask(const QRegion ®ion) override;
|
||||||
@ -177,7 +178,8 @@ public:
|
|||||||
|
|
||||||
QXcbScreen *xcbScreen() const;
|
QXcbScreen *xcbScreen() const;
|
||||||
|
|
||||||
bool doStartSystemResize(const QPoint &globalPos, Qt::Corner corner);
|
bool startSystemMoveResize(const QPoint &pos, int corner);
|
||||||
|
bool doStartSystemMoveResize(const QPoint &globalPos, int corner);
|
||||||
|
|
||||||
virtual void create();
|
virtual void create();
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
|
Loading…
Reference in New Issue
Block a user