mirror of
https://github.com/danog/patches.git
synced 2024-11-30 04:19:34 +01:00
670 lines
26 KiB
Diff
670 lines
26 KiB
Diff
|
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
|
||
|
index 835c04a5df..51c011ad79 100644
|
||
|
--- a/src/gui/kernel/qplatformwindow.cpp
|
||
|
+++ b/src/gui/kernel/qplatformwindow.cpp
|
||
|
@@ -484,19 +484,17 @@ bool QPlatformWindow::windowEvent(QEvent *event)
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
- Reimplement this method to start a system size grip drag
|
||
|
- operation if the system supports it and return true to indicate
|
||
|
- success.
|
||
|
- It is called from the mouse press event handler of the size grip.
|
||
|
+ Reimplement this method to start a system resize operation if
|
||
|
+ the system supports it and return true to indicate success.
|
||
|
+
|
||
|
+ The default implementation is empty and does nothing with \a edges.
|
||
|
|
||
|
- The default implementation is empty and does nothing with \a pos
|
||
|
- and \a corner.
|
||
|
+ \since 5.15
|
||
|
*/
|
||
|
|
||
|
-bool QPlatformWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
|
||
|
+bool QPlatformWindow::startSystemResize(Qt::Edges edges)
|
||
|
{
|
||
|
- Q_UNUSED(pos)
|
||
|
- Q_UNUSED(corner)
|
||
|
+ Q_UNUSED(edges)
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
@@ -504,18 +502,13 @@ bool QPlatformWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
|
||
|
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.
|
||
|
+ The default implementation is empty and does nothing.
|
||
|
|
||
|
- \since 5.11
|
||
|
+ \since 5.15
|
||
|
*/
|
||
|
|
||
|
-bool QPlatformWindow::startSystemMove(const QPoint &pos)
|
||
|
+bool QPlatformWindow::startSystemMove()
|
||
|
{
|
||
|
- Q_UNUSED(pos)
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
|
||
|
index 075ac0f82b..ea9d24c86c 100644
|
||
|
--- a/src/gui/kernel/qplatformwindow.h
|
||
|
+++ b/src/gui/kernel/qplatformwindow.h
|
||
|
@@ -129,8 +129,8 @@ public:
|
||
|
|
||
|
virtual bool windowEvent(QEvent *event);
|
||
|
|
||
|
- virtual bool startSystemResize(const QPoint &pos, Qt::Corner corner);
|
||
|
- virtual bool startSystemMove(const QPoint &pos);
|
||
|
+ virtual bool startSystemResize(Qt::Edges edges);
|
||
|
+ virtual bool startSystemMove();
|
||
|
|
||
|
virtual void setFrameStrutEventsEnabled(bool enabled);
|
||
|
virtual bool frameStrutEventsEnabled() const;
|
||
|
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
|
||
|
index a19df4da0f..35ebd270eb 100644
|
||
|
--- a/src/gui/kernel/qwindow.cpp
|
||
|
+++ b/src/gui/kernel/qwindow.cpp
|
||
|
@@ -1049,6 +1049,71 @@ void QWindow::lower()
|
||
|
d->platformWindow->lower();
|
||
|
}
|
||
|
|
||
|
+/*!
|
||
|
+ \brief Start a system-specific resize operation
|
||
|
+ \since 5.15
|
||
|
+
|
||
|
+ Calling this will start an interactive resize operation on the window by platforms
|
||
|
+ that support it. The actual behavior may vary depending on the platform. Usually,
|
||
|
+ it will make the window resize so that its edge follows the mouse cursor.
|
||
|
+
|
||
|
+ On platforms that support it, this method of resizing windows is preferred over
|
||
|
+ \c setGeometry, because it allows a more native look-and-feel of resizing windows, e.g.
|
||
|
+ letting the window manager snap this window against other windows, or special resizing
|
||
|
+ behavior with animations when dragged to the edge of the screen.
|
||
|
+
|
||
|
+ \a edges should either be a single edge, or two adjacent edges (a corner). Other values
|
||
|
+ are not allowed.
|
||
|
+
|
||
|
+ Returns true if the operation was supported by the system.
|
||
|
+*/
|
||
|
+bool QWindow::startSystemResize(Qt::Edges edges)
|
||
|
+{
|
||
|
+ Q_D(QWindow);
|
||
|
+ if (Q_UNLIKELY(!isVisible() || !d->platformWindow || d->maximumSize == d->minimumSize))
|
||
|
+ return false;
|
||
|
+
|
||
|
+ const bool isSingleEdge = edges == Qt::TopEdge || edges == Qt::RightEdge || edges == Qt::BottomEdge || edges == Qt::LeftEdge;
|
||
|
+ const bool isCorner =
|
||
|
+ edges == (Qt::TopEdge | Qt::LeftEdge) ||
|
||
|
+ edges == (Qt::TopEdge | Qt::RightEdge) ||
|
||
|
+ edges == (Qt::BottomEdge | Qt::RightEdge) ||
|
||
|
+ edges == (Qt::BottomEdge | Qt::LeftEdge);
|
||
|
+
|
||
|
+ if (Q_UNLIKELY(!isSingleEdge && !isCorner)) {
|
||
|
+ qWarning() << "Invalid edges" << edges << "passed to QWindow::startSystemResize, ignoring.";
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ return d->platformWindow->startSystemResize(edges);
|
||
|
+}
|
||
|
+
|
||
|
+/*!
|
||
|
+ \brief Start a system-specific move operation
|
||
|
+ \since 5.15
|
||
|
+
|
||
|
+ Calling this will start an interactive move operation on the window by platforms
|
||
|
+ that support it. The actual behavior may vary depending on the platform. Usually,
|
||
|
+ it will make the window follow the mouse cursor until a mouse button is released.
|
||
|
+
|
||
|
+ On platforms that support it, this method of moving windows is preferred over
|
||
|
+ \c setPosition, because it allows a more native look-and-feel of moving windows, e.g.
|
||
|
+ letting the window manager snap this window against other windows, or special tiling
|
||
|
+ or resizing behavior with animations when dragged to the edge of the screen.
|
||
|
+ Furthermore, on some platforms such as Wayland, \c setPosition is not supported, so
|
||
|
+ this is the only way the application can influence its position.
|
||
|
+
|
||
|
+ Returns true if the operation was supported by the system.
|
||
|
+*/
|
||
|
+bool QWindow::startSystemMove()
|
||
|
+{
|
||
|
+ Q_D(QWindow);
|
||
|
+ if (Q_UNLIKELY(!isVisible() || !d->platformWindow))
|
||
|
+ return false;
|
||
|
+
|
||
|
+ return d->platformWindow->startSystemMove();
|
||
|
+}
|
||
|
+
|
||
|
/*!
|
||
|
\property QWindow::opacity
|
||
|
\brief The opacity of the window in the windowing system.
|
||
|
@@ -1781,7 +1846,10 @@ void QWindow::setFramePosition(const QPoint &point)
|
||
|
|
||
|
The position is in relation to the virtualGeometry() of its screen.
|
||
|
|
||
|
- \sa position()
|
||
|
+ For interactively moving windows, see startSystemMove(). For interactively
|
||
|
+ resizing windows, see startSystemResize().
|
||
|
+
|
||
|
+ \sa position(), startSystemMove()
|
||
|
*/
|
||
|
void QWindow::setPosition(const QPoint &pt)
|
||
|
{
|
||
|
@@ -1818,6 +1886,8 @@ void QWindow::setPosition(int posx, int posy)
|
||
|
set the size of the window, excluding any window frame, to a QSize
|
||
|
constructed from width \a w and height \a h
|
||
|
|
||
|
+ For interactively resizing windows, see startSystemResize().
|
||
|
+
|
||
|
\sa size(), geometry()
|
||
|
*/
|
||
|
void QWindow::resize(int w, int h)
|
||
|
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
|
||
|
index 439e62d0bd..194821531c 100644
|
||
|
--- a/src/gui/kernel/qwindow.h
|
||
|
+++ b/src/gui/kernel/qwindow.h
|
||
|
@@ -291,6 +291,8 @@ public Q_SLOTS:
|
||
|
bool close();
|
||
|
void raise();
|
||
|
void lower();
|
||
|
+ bool startSystemResize(Qt::Edges edges);
|
||
|
+ bool startSystemMove();
|
||
|
|
||
|
void setTitle(const QString &);
|
||
|
|
||
|
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
|
||
|
index c6ce6e6819..118c0776af 100644
|
||
|
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
|
||
|
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
|
||
|
@@ -219,6 +219,8 @@ protected:
|
||
|
void toggleFullScreen();
|
||
|
bool isTransitioningToFullScreen() const;
|
||
|
|
||
|
+ bool startSystemMove() override;
|
||
|
+
|
||
|
// private:
|
||
|
public: // for QNSView
|
||
|
friend class QCocoaBackingStore;
|
||
|
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
|
||
|
index 3008a056a2..a8f10898d8 100644
|
||
|
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
|
||
|
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
|
||
|
@@ -298,6 +298,22 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
|
||
|
// will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm)
|
||
|
}
|
||
|
|
||
|
+bool QCocoaWindow::startSystemMove()
|
||
|
+{
|
||
|
+ switch (NSApp.currentEvent.type) {
|
||
|
+ case NSEventTypeLeftMouseDown:
|
||
|
+ case NSEventTypeRightMouseDown:
|
||
|
+ case NSEventTypeOtherMouseDown:
|
||
|
+ case NSEventTypeMouseMoved:
|
||
|
+ // The documentation only describes starting a system move
|
||
|
+ // based on mouse down events, but move events also work.
|
||
|
+ [m_view.window performWindowDragWithEvent:NSApp.currentEvent];
|
||
|
+ return true;
|
||
|
+ default:
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
void QCocoaWindow::setVisible(bool visible)
|
||
|
{
|
||
|
qCDebug(lcQpaWindow) << "QCocoaWindow::setVisible" << window() << visible;
|
||
|
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
|
||
|
index 7d511bf0d7..0b0c0fb2fc 100644
|
||
|
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
|
||
|
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
|
||
|
@@ -2523,37 +2523,41 @@ bool QWindowsWindow::setMouseGrabEnabled(bool grab)
|
||
|
return grab;
|
||
|
}
|
||
|
|
||
|
-static inline DWORD cornerToWinOrientation(Qt::Corner corner)
|
||
|
-{
|
||
|
- switch (corner) {
|
||
|
- case Qt::TopLeftCorner:
|
||
|
- return 0xf004; // SZ_SIZETOPLEFT;
|
||
|
- case Qt::TopRightCorner:
|
||
|
- return 0xf005; // SZ_SIZETOPRIGHT
|
||
|
- case Qt::BottomLeftCorner:
|
||
|
- return 0xf007; // SZ_SIZEBOTTOMLEFT
|
||
|
- case Qt::BottomRightCorner:
|
||
|
- return 0xf008; // SZ_SIZEBOTTOMRIGHT
|
||
|
- }
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
-bool QWindowsWindow::startSystemResize(const QPoint &, Qt::Corner corner)
|
||
|
-{
|
||
|
- if (!GetSystemMenu(m_data.hwnd, FALSE))
|
||
|
+static inline DWORD edgesToWinOrientation(Qt::Edges edges)
|
||
|
+{
|
||
|
+ if (edges == Qt::LeftEdge)
|
||
|
+ return 0xf001; // SC_SIZELEFT;
|
||
|
+ else if (edges == (Qt::RightEdge))
|
||
|
+ return 0xf002; // SC_SIZERIGHT
|
||
|
+ else if (edges == (Qt::TopEdge))
|
||
|
+ return 0xf003; // SC_SIZETOP
|
||
|
+ else if (edges == (Qt::TopEdge | Qt::LeftEdge))
|
||
|
+ return 0xf004; // SC_SIZETOPLEFT
|
||
|
+ else if (edges == (Qt::TopEdge | Qt::RightEdge))
|
||
|
+ return 0xf005; // SC_SIZETOPRIGHT
|
||
|
+ else if (edges == (Qt::BottomEdge))
|
||
|
+ return 0xf006; // SC_SIZEBOTTOM
|
||
|
+ else if (edges == (Qt::BottomEdge | Qt::LeftEdge))
|
||
|
+ return 0xf007; // SC_SIZEBOTTOMLEFT
|
||
|
+ else if (edges == (Qt::BottomEdge | Qt::RightEdge))
|
||
|
+ return 0xf008; // SC_SIZEBOTTOMRIGHT
|
||
|
+
|
||
|
+ return 0xf000; // SC_SIZE
|
||
|
+}
|
||
|
+
|
||
|
+bool QWindowsWindow::startSystemResize(Qt::Edges edges)
|
||
|
+{
|
||
|
+ if (Q_UNLIKELY(!(window()->flags() & Qt::MSWindowsFixedSizeDialogHint)))
|
||
|
return false;
|
||
|
|
||
|
ReleaseCapture();
|
||
|
- PostMessage(m_data.hwnd, WM_SYSCOMMAND, cornerToWinOrientation(corner), 0);
|
||
|
+ PostMessage(m_data.hwnd, WM_SYSCOMMAND, edgesToWinOrientation(edges), 0);
|
||
|
setFlag(SizeGripOperation);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
-bool QWindowsWindow::startSystemMove(const QPoint &)
|
||
|
+bool QWindowsWindow::startSystemMove()
|
||
|
{
|
||
|
- if (!GetSystemMenu(m_data.hwnd, FALSE))
|
||
|
- return false;
|
||
|
-
|
||
|
ReleaseCapture();
|
||
|
PostMessage(m_data.hwnd, WM_SYSCOMMAND, 0xF012 /*SC_DRAGMOVE*/, 0);
|
||
|
return true;
|
||
|
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
|
||
|
index ce67e46df3..740be13a72 100644
|
||
|
--- a/src/plugins/platforms/windows/qwindowswindow.h
|
||
|
+++ b/src/plugins/platforms/windows/qwindowswindow.h
|
||
|
@@ -269,8 +269,8 @@ public:
|
||
|
bool setMouseGrabEnabled(bool grab) override;
|
||
|
inline bool hasMouseCapture() const { return GetCapture() == m_data.hwnd; }
|
||
|
|
||
|
- bool startSystemResize(const QPoint &pos, Qt::Corner corner) override;
|
||
|
- bool startSystemMove(const QPoint &pos) override;
|
||
|
+ bool startSystemResize(Qt::Edges edges) override;
|
||
|
+ bool startSystemMove() override;
|
||
|
|
||
|
void setFrameStrutEventsEnabled(bool enabled) override;
|
||
|
bool frameStrutEventsEnabled() const override { return testFlag(FrameStrutEventsEnabled); }
|
||
|
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
|
||
|
index 15537fede4..402720a2de 100644
|
||
|
--- a/src/plugins/platforms/xcb/qxcbconnection.h
|
||
|
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
|
||
|
@@ -235,7 +235,7 @@ public:
|
||
|
bool xi2MouseEventsDisabled() const;
|
||
|
Qt::MouseButton xiToQtMouseButton(uint32_t b);
|
||
|
void xi2UpdateScrollingDevices();
|
||
|
- bool startSystemMoveResizeForTouchBegin(xcb_window_t window, const QPoint &point, int corner);
|
||
|
+ bool startSystemMoveResizeForTouch(xcb_window_t window, int edges);
|
||
|
void abortSystemMoveResizeForTouch();
|
||
|
bool isTouchScreen(int id);
|
||
|
#endif
|
||
|
@@ -339,7 +339,7 @@ private:
|
||
|
xcb_window_t window = XCB_NONE;
|
||
|
uint16_t deviceid;
|
||
|
uint32_t pointid;
|
||
|
- int corner;
|
||
|
+ int edges;
|
||
|
} m_startSystemMoveResizeInfo;
|
||
|
#endif // QT_CONFIG(xcb_xinput)
|
||
|
|
||
|
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
|
||
|
index 450706fc53..8f08644e3c 100644
|
||
|
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
|
||
|
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
|
||
|
@@ -753,7 +753,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
|
||
|
xcb_input_xi_allow_events(xcb_connection(), XCB_CURRENT_TIME, xiDeviceEvent->deviceid,
|
||
|
XCB_INPUT_EVENT_MODE_REJECT_TOUCH,
|
||
|
xiDeviceEvent->detail, xiDeviceEvent->event);
|
||
|
- window->doStartSystemMoveResize(QPoint(x, y), m_startSystemMoveResizeInfo.corner);
|
||
|
+ window->doStartSystemMoveResize(QPoint(x, y), m_startSystemMoveResizeInfo.edges);
|
||
|
m_startSystemMoveResizeInfo.window = XCB_NONE;
|
||
|
}
|
||
|
}
|
||
|
@@ -787,19 +787,20 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
|
||
|
touchPoint.state = Qt::TouchPointStationary;
|
||
|
}
|
||
|
|
||
|
-bool QXcbConnection::startSystemMoveResizeForTouchBegin(xcb_window_t window, const QPoint &point, int corner)
|
||
|
+bool QXcbConnection::startSystemMoveResizeForTouch(xcb_window_t window, int edges)
|
||
|
{
|
||
|
QHash<int, TouchDeviceData>::const_iterator devIt = m_touchDevices.constBegin();
|
||
|
for (; devIt != m_touchDevices.constEnd(); ++devIt) {
|
||
|
TouchDeviceData 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) {
|
||
|
+ auto pointIt = deviceData.touchPoints.constBegin();
|
||
|
+ for (; pointIt != deviceData.touchPoints.constEnd(); ++pointIt) {
|
||
|
+ Qt::TouchPointState state = pointIt.value().state;
|
||
|
+ if (state == Qt::TouchPointMoved || state == Qt::TouchPointPressed || state == Qt::TouchPointStationary) {
|
||
|
m_startSystemMoveResizeInfo.window = window;
|
||
|
m_startSystemMoveResizeInfo.deviceid = devIt.key();
|
||
|
m_startSystemMoveResizeInfo.pointid = pointIt.key();
|
||
|
- m_startSystemMoveResizeInfo.corner = corner;
|
||
|
+ m_startSystemMoveResizeInfo.edges = edges;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||
|
index 3bfcbf2adb..71774a8cde 100644
|
||
|
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||
|
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||
|
@@ -2196,6 +2196,7 @@ QXcbWindow *QXcbWindow::toWindow() { return this; }
|
||
|
void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global,
|
||
|
Qt::KeyboardModifiers modifiers, QEvent::Type type, Qt::MouseEventSource source)
|
||
|
{
|
||
|
+ m_lastPointerPosition = local;
|
||
|
connection()->setTime(time);
|
||
|
Qt::MouseButton button = type == QEvent::MouseMove ? Qt::NoButton : connection()->button();
|
||
|
QWindowSystemInterface::handleMouseEvent(window(), time, local, global,
|
||
|
@@ -2380,30 +2381,28 @@ bool QXcbWindow::windowEvent(QEvent *event)
|
||
|
return QPlatformWindow::windowEvent(event);
|
||
|
}
|
||
|
|
||
|
-bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
|
||
|
+bool QXcbWindow::startSystemResize(Qt::Edges edges)
|
||
|
{
|
||
|
- return startSystemMoveResize(pos, corner);
|
||
|
+ return startSystemMoveResize(m_lastPointerPosition, edges);
|
||
|
}
|
||
|
|
||
|
-bool QXcbWindow::startSystemMove(const QPoint &pos)
|
||
|
+bool QXcbWindow::startSystemMove()
|
||
|
{
|
||
|
- return startSystemMoveResize(pos, 4);
|
||
|
+ return startSystemMoveResize(m_lastPointerPosition, 16);
|
||
|
}
|
||
|
|
||
|
-bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner)
|
||
|
+bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int edges)
|
||
|
{
|
||
|
- return false; // ### FIXME QTBUG-69716
|
||
|
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
|
||
|
if (!connection()->wmSupport()->isSupportedByWM(moveResize))
|
||
|
return false;
|
||
|
|
||
|
- const QPoint globalPos = QHighDpi::toNativePixels(window()->mapToGlobal(pos), window()->screen());
|
||
|
#if QT_CONFIG(xcb_xinput)
|
||
|
// ### FIXME QTBUG-53389
|
||
|
- bool startedByTouch = connection()->startSystemMoveResizeForTouchBegin(m_window, globalPos, corner);
|
||
|
+ bool startedByTouch = connection()->startSystemMoveResizeForTouch(m_window, edges);
|
||
|
if (startedByTouch) {
|
||
|
- if (connection()->isUnity() || connection()->isGnome()) {
|
||
|
- // These desktops fail to move/resize via _NET_WM_MOVERESIZE (WM bug?).
|
||
|
+ if (connection()->isUnity()) {
|
||
|
+ // Unity fails to move/resize via _NET_WM_MOVERESIZE (WM bug?).
|
||
|
connection()->abortSystemMoveResizeForTouch();
|
||
|
return false;
|
||
|
}
|
||
|
@@ -2414,13 +2413,37 @@ bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner)
|
||
|
if (connection()->isUnity())
|
||
|
return false; // _NET_WM_MOVERESIZE on this WM is bouncy (WM bug?).
|
||
|
|
||
|
- doStartSystemMoveResize(globalPos, corner);
|
||
|
+ const QPoint globalPos = QHighDpi::toNativePixels(window()->mapToGlobal(pos), window()->screen());
|
||
|
+ doStartSystemMoveResize(globalPos, edges);
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
-void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int corner)
|
||
|
+static uint qtEdgesToXcbMoveResizeDirection(Qt::Edges edges)
|
||
|
+{
|
||
|
+ if (edges == (Qt::TopEdge | Qt::LeftEdge))
|
||
|
+ return 0;
|
||
|
+ if (edges == Qt::TopEdge)
|
||
|
+ return 1;
|
||
|
+ if (edges == (Qt::TopEdge | Qt::RightEdge))
|
||
|
+ return 2;
|
||
|
+ if (edges == Qt::RightEdge)
|
||
|
+ return 3;
|
||
|
+ if (edges == (Qt::RightEdge | Qt::BottomEdge))
|
||
|
+ return 4;
|
||
|
+ if (edges == Qt::BottomEdge)
|
||
|
+ return 5;
|
||
|
+ if (edges == (Qt::BottomEdge | Qt::LeftEdge))
|
||
|
+ return 6;
|
||
|
+ if (edges == Qt::LeftEdge)
|
||
|
+ return 7;
|
||
|
+
|
||
|
+ qWarning() << "Cannot convert " << edges << "to _NET_WM_MOVERESIZE direction.";
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int edges)
|
||
|
{
|
||
|
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
|
||
|
xcb_client_message_event_t xev;
|
||
|
@@ -2431,16 +2454,10 @@ void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int corner)
|
||
|
xev.format = 32;
|
||
|
xev.data.data32[0] = globalPos.x();
|
||
|
xev.data.data32[1] = globalPos.y();
|
||
|
- if (corner == 4) {
|
||
|
+ if (edges == 16)
|
||
|
xev.data.data32[2] = 8; // move
|
||
|
- } else {
|
||
|
- const bool bottom = corner == Qt::BottomRightCorner || corner == Qt::BottomLeftCorner;
|
||
|
- const bool left = corner == Qt::BottomLeftCorner || corner == Qt::TopLeftCorner;
|
||
|
- if (bottom)
|
||
|
- xev.data.data32[2] = left ? 6 : 4; // bottomleft/bottomright
|
||
|
- else
|
||
|
- xev.data.data32[2] = left ? 0 : 2; // topleft/topright
|
||
|
- }
|
||
|
+ else
|
||
|
+ xev.data.data32[2] = qtEdgesToXcbMoveResizeDirection(Qt::Edges(edges));
|
||
|
xev.data.data32[3] = XCB_BUTTON_INDEX_1;
|
||
|
xev.data.data32[4] = 0;
|
||
|
xcb_ungrab_pointer(connection()->xcb_connection(), XCB_CURRENT_TIME);
|
||
|
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
|
||
|
index 8258cc2dfa..a5f6a0bc50 100644
|
||
|
--- a/src/plugins/platforms/xcb/qxcbwindow.h
|
||
|
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
|
||
|
@@ -107,8 +107,8 @@ public:
|
||
|
|
||
|
bool windowEvent(QEvent *event) override;
|
||
|
|
||
|
- bool startSystemResize(const QPoint &pos, Qt::Corner corner) override;
|
||
|
- bool startSystemMove(const QPoint &pos) override;
|
||
|
+ bool startSystemResize(Qt::Edges edges) override;
|
||
|
+ bool startSystemMove() override;
|
||
|
|
||
|
void setOpacity(qreal level) override;
|
||
|
void setMask(const QRegion ®ion) override;
|
||
|
@@ -170,8 +170,8 @@ public:
|
||
|
|
||
|
QXcbScreen *xcbScreen() const;
|
||
|
|
||
|
- bool startSystemMoveResize(const QPoint &pos, int corner);
|
||
|
- void doStartSystemMoveResize(const QPoint &globalPos, int corner);
|
||
|
+ bool startSystemMoveResize(const QPoint &pos, int edges);
|
||
|
+ void doStartSystemMoveResize(const QPoint &globalPos, int edges);
|
||
|
|
||
|
static bool isTrayIconWindow(QWindow *window)
|
||
|
{
|
||
|
@@ -266,6 +266,7 @@ protected:
|
||
|
|
||
|
QRegion m_exposeRegion;
|
||
|
QSize m_oldWindowSize;
|
||
|
+ QPoint m_lastPointerPosition;
|
||
|
|
||
|
xcb_visualid_t m_visualId = 0;
|
||
|
// Last sent state. Initialized to an invalid state, on purpose.
|
||
|
diff --git a/src/widgets/widgets/qsizegrip.cpp b/src/widgets/widgets/qsizegrip.cpp
|
||
|
index dc5a7158dd..d94360fdeb 100644
|
||
|
--- a/src/widgets/widgets/qsizegrip.cpp
|
||
|
+++ b/src/widgets/widgets/qsizegrip.cpp
|
||
|
@@ -280,6 +280,17 @@ void QSizeGrip::paintEvent(QPaintEvent *event)
|
||
|
parameter.
|
||
|
*/
|
||
|
|
||
|
+static Qt::Edges edgesFromCorner(Qt::Corner corner)
|
||
|
+{
|
||
|
+ switch (corner) {
|
||
|
+ case Qt::TopLeftCorner: return Qt::TopEdge | Qt::LeftEdge;
|
||
|
+ case Qt::TopRightCorner: return Qt::TopEdge | Qt::RightEdge;
|
||
|
+ case Qt::BottomLeftCorner: return Qt::BottomEdge | Qt::LeftEdge;
|
||
|
+ case Qt::BottomRightCorner: return Qt::BottomEdge | Qt::RightEdge;
|
||
|
+ }
|
||
|
+ return Qt::Edges{};
|
||
|
+}
|
||
|
+
|
||
|
void QSizeGrip::mousePressEvent(QMouseEvent * e)
|
||
|
{
|
||
|
if (e->button() != Qt::LeftButton) {
|
||
|
@@ -301,8 +312,9 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e)
|
||
|
&& !tlw->testAttribute(Qt::WA_DontShowOnScreen)
|
||
|
&& !tlw->hasHeightForWidth()) {
|
||
|
QPlatformWindow *platformWindow = tlw->windowHandle()->handle();
|
||
|
- const QPoint topLevelPos = mapTo(tlw, e->pos());
|
||
|
- d->m_platformSizeGrip = platformWindow && platformWindow->startSystemResize(topLevelPos, d->m_corner);
|
||
|
+ const Qt::Edges edges = edgesFromCorner(d->m_corner);
|
||
|
+ if (!QGuiApplication::platformName().contains(QStringLiteral("xcb"))) // ### FIXME QTBUG-69716
|
||
|
+ d->m_platformSizeGrip = platformWindow && platformWindow->startSystemResize(edges);
|
||
|
}
|
||
|
|
||
|
if (d->m_platformSizeGrip)
|
||
|
diff --git a/tests/manual/startsystemmove/main.cpp b/tests/manual/startsystemmove/main.cpp
|
||
|
new file mode 100644
|
||
|
index 0000000000..a121d1ed86
|
||
|
--- /dev/null
|
||
|
+++ b/tests/manual/startsystemmove/main.cpp
|
||
|
@@ -0,0 +1,111 @@
|
||
|
+/****************************************************************************
|
||
|
+**
|
||
|
+** Copyright (C) 2020 The Qt Company Ltd.
|
||
|
+** Contact: https://www.qt.io/licensing/
|
||
|
+**
|
||
|
+** This file is part of the test suite of the Qt Toolkit.
|
||
|
+**
|
||
|
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||
|
+** Commercial License Usage
|
||
|
+** Licensees holding valid commercial Qt licenses may use this file in
|
||
|
+** accordance with the commercial license agreement provided with the
|
||
|
+** Software or, alternatively, in accordance with the terms contained in
|
||
|
+** a written agreement between you and The Qt Company. For licensing terms
|
||
|
+** and conditions see https://www.qt.io/terms-conditions. For further
|
||
|
+** information use the contact form at https://www.qt.io/contact-us.
|
||
|
+**
|
||
|
+** GNU General Public License Usage
|
||
|
+** Alternatively, this file may be used under the terms of the GNU
|
||
|
+** General Public License version 3 as published by the Free Software
|
||
|
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||
|
+** included in the packaging of this file. Please review the following
|
||
|
+** information to ensure the GNU General Public License requirements will
|
||
|
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||
|
+**
|
||
|
+** $QT_END_LICENSE$
|
||
|
+**
|
||
|
+****************************************************************************/
|
||
|
+
|
||
|
+#include <QtGui>
|
||
|
+
|
||
|
+constexpr qreal border = 20;
|
||
|
+
|
||
|
+class Window : public QRasterWindow
|
||
|
+{
|
||
|
+public:
|
||
|
+ explicit Window(QWindow *parent = nullptr) : QRasterWindow(parent)
|
||
|
+ {
|
||
|
+ resize(300, 200);
|
||
|
+ setMinimumSize(QSize(border*2, border*2));
|
||
|
+ }
|
||
|
+protected:
|
||
|
+ void resizeOrMove(const QPointF &p);
|
||
|
+ bool event(QEvent *event) override;
|
||
|
+ void paintEvent(QPaintEvent *event) override;
|
||
|
+};
|
||
|
+
|
||
|
+void Window::resizeOrMove(const QPointF &p)
|
||
|
+{
|
||
|
+ Qt::Edges edges;
|
||
|
+ if (p.x() > width() - border)
|
||
|
+ edges |= Qt::RightEdge;
|
||
|
+ if (p.x() < border)
|
||
|
+ edges |= Qt::LeftEdge;
|
||
|
+ if (p.y() < border)
|
||
|
+ edges |= Qt::TopEdge;
|
||
|
+ if (p.y() > height() - border)
|
||
|
+ edges |= Qt::BottomEdge;
|
||
|
+
|
||
|
+ if (edges != 0) {
|
||
|
+ qDebug() << "startSystemResize" << edges;
|
||
|
+ if (startSystemResize(edges))
|
||
|
+ qDebug() << " -> supported";
|
||
|
+ else
|
||
|
+ qDebug() << " -> not supported";
|
||
|
+ } else {
|
||
|
+ qDebug() << "startSystemMove";
|
||
|
+ if (startSystemMove())
|
||
|
+ qDebug() << " -> supported";
|
||
|
+ else
|
||
|
+ qDebug() << " -> not supported";
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+bool Window::event(QEvent *event)
|
||
|
+{
|
||
|
+ switch (event->type()) {
|
||
|
+ case QEvent::MouseButtonPress:
|
||
|
+ qDebug() << "Mouse press";
|
||
|
+ resizeOrMove(static_cast<QMouseEvent *>(event)->localPos());
|
||
|
+ return true;
|
||
|
+ case QEvent::TouchUpdate:
|
||
|
+ qDebug() << "Touch update";
|
||
|
+ resizeOrMove(static_cast<QTouchEvent *>(event)->touchPoints().first().pos());
|
||
|
+ return true;
|
||
|
+ case QEvent::TouchBegin:
|
||
|
+ qDebug() << "Touch begin";
|
||
|
+ resizeOrMove(static_cast<QTouchEvent *>(event)->touchPoints().first().pos());
|
||
|
+ return true;
|
||
|
+ default:
|
||
|
+ return QRasterWindow::event(event);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+void Window::paintEvent(QPaintEvent *event)
|
||
|
+{
|
||
|
+ Q_UNUSED(event);
|
||
|
+ QPainter painter(this);
|
||
|
+ QRect fullRect(0, 0, width(), height());
|
||
|
+ QRect innerRect = fullRect.marginsRemoved(QMargins(border, border, border, border));
|
||
|
+ painter.fillRect(fullRect, QGradient::WarmFlame);
|
||
|
+ painter.fillRect(innerRect, QGradient::NightFade);
|
||
|
+ painter.drawText(QRectF(0, 0, width(), height()), Qt::AlignCenter, QStringLiteral("Click mouse or touch to move window\nDrag along the sides to resize."));
|
||
|
+}
|
||
|
+
|
||
|
+int main(int argc, char **argv)
|
||
|
+{
|
||
|
+ QGuiApplication app(argc, argv);
|
||
|
+ Window window;
|
||
|
+ window.show();
|
||
|
+ return app.exec();
|
||
|
+}
|
||
|
diff --git a/tests/manual/startsystemmove/startsystemmove.pro b/tests/manual/startsystemmove/startsystemmove.pro
|
||
|
new file mode 100644
|
||
|
index 0000000000..568bda343b
|
||
|
--- /dev/null
|
||
|
+++ b/tests/manual/startsystemmove/startsystemmove.pro
|
||
|
@@ -0,0 +1,4 @@
|
||
|
+TEMPLATE = app
|
||
|
+QT = core gui
|
||
|
+SOURCES += main.cpp
|
||
|
+CONFIG += console
|