diff options
-rw-r--r-- | src/gui/kernel/qwindow.cpp | 60 | ||||
-rw-r--r-- | src/gui/kernel/qwindow.h | 17 | ||||
-rw-r--r-- | src/gui/kernel/qwindow_p.h | 9 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 11 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget_qpa.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qwindow/tst_qwindow.cpp | 95 |
6 files changed, 185 insertions, 9 deletions
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 759ee8dbc4..118844a0a2 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -412,9 +412,13 @@ void QWindow::setSizeIncrement(const QSize &size) d->platformWindow->propagateSizeHints(); } +/*! + Sets the geometry of the window excluding its window frame. +*/ void QWindow::setGeometry(const QRect &rect) { Q_D(QWindow); + d->positionPolicy = QWindowPrivate::WindowFrameExclusive; if (d->platformWindow) { d->platformWindow->setGeometry(rect); } else { @@ -422,6 +426,9 @@ void QWindow::setGeometry(const QRect &rect) } } +/*! + Returns the geometry of the window excluding its window frame. +*/ QRect QWindow::geometry() const { Q_D(const QWindow); @@ -430,6 +437,9 @@ QRect QWindow::geometry() const return d->geometry; } +/*! + Returns the window frame margins surrounding the window. +*/ QMargins QWindow::frameMargins() const { Q_D(const QWindow); @@ -438,6 +448,56 @@ QMargins QWindow::frameMargins() const return QMargins(); } +/*! + Returns the geometry of the window including its window frame. +*/ +QRect QWindow::frameGeometry() const +{ + Q_D(const QWindow); + if (d->platformWindow) { + QMargins m = frameMargins(); + return d->platformWindow->geometry().adjusted(-m.left(), -m.top(), m.right(), m.bottom()); + } + return d->geometry; +} + +/*! + Returns the top left position of the window including its window frame. +*/ +QPoint QWindow::framePos() const +{ + Q_D(const QWindow); + if (d->platformWindow) { + QMargins margins = frameMargins(); + return d->platformWindow->geometry().topLeft() - QPoint(margins.left(), margins.top()); + } + return d->geometry.topLeft(); +} + +/*! + Sets the upper left position of the window including its window frame. +*/ +void QWindow::setFramePos(const QPoint &point) +{ + Q_D(QWindow); + d->positionPolicy = QWindowPrivate::WindowFrameInclusive; + if (d->platformWindow) { + d->platformWindow->setGeometry(QRect(point, size())); + } else { + d->geometry.setTopLeft(point); + } +} + +void QWindow::resize(const QSize &newSize) +{ + Q_D(QWindow); + if (d->platformWindow) { + d->platformWindow->setGeometry(QRect(pos(), newSize)); + } else { + d->geometry.setSize(newSize); + } +} + void QWindow::setWindowIcon(const QImage &icon) const { Q_UNUSED(icon); diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h index 4bb1ff77a5..7a075e624d 100644 --- a/src/gui/kernel/qwindow.h +++ b/src/gui/kernel/qwindow.h @@ -142,6 +142,12 @@ public: void setGeometry(const QRect &rect); QRect geometry() const; + QMargins frameMargins() const; + QRect frameGeometry() const; + + QPoint framePos() const; + void setFramePos(const QPoint &point); + inline int width() const { return geometry().width(); } inline int height() const { return geometry().height(); } inline int x() const { return geometry().x(); } @@ -150,13 +156,14 @@ public: inline QSize size() const { return geometry().size(); } inline QPoint pos() const { return geometry().topLeft(); } - inline void move(const QPoint &pt) { setGeometry(QRect(pt, size())); } - inline void move(int posx, int posy) { move(QPoint(posx, posy)); } + QT_DEPRECATED inline void move(const QPoint &pt) { setPos(pt); } + QT_DEPRECATED inline void move(int posx, int posy) { setPos(posx, posy); } - inline void resize(const QSize &newsize) { setGeometry(QRect(pos(), newsize)); } - inline void resize(int w, int h) { setGeometry(QRect(x(), y(), w, h)); } + inline void setPos(const QPoint &pt) { setGeometry(QRect(pt, size())); } + inline void setPos(int posx, int posy) { setPos(QPoint(posx, posy)); } - QMargins frameMargins() const; + void resize(const QSize &newSize); + inline void resize(int w, int h) { setGeometry(QRect(x(), y(), w, h)); } void setWindowIcon(const QImage &icon) const; diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index 8a3bc0d7fe..1ef8f59d33 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -43,6 +43,7 @@ #define QWINDOW_QPA_P_H #include <QtGui/qwindow.h> +#include <QtGui/qplatformwindow_qpa.h> #include <QtCore/private/qobject_p.h> @@ -59,6 +60,12 @@ class Q_GUI_EXPORT QWindowPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QWindow) public: + enum PositionPolicy + { + WindowFrameInclusive, + WindowFrameExclusive + }; + QWindowPrivate() : QObjectPrivate() , surfaceType(QWindow::RasterSurface) @@ -68,6 +75,7 @@ public: , visible(false) , windowState(Qt::WindowNoState) , resizeEventPending(true) + , positionPolicy(WindowFrameExclusive) , maximumSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX) , modality(Qt::NonModal) , transientParent(0) @@ -101,6 +109,7 @@ public: QRect geometry; Qt::WindowState windowState; bool resizeEventPending; + PositionPolicy positionPolicy; QSize minimumSize; QSize maximumSize; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index bf882bdf84..4169ba5e4f 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -246,6 +246,8 @@ void QXcbWindow::create() Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values)); + propagateSizeHints(); + xcb_atom_t properties[4]; int propertyCount = 0; properties[propertyCount++] = atom(QXcbAtom::WM_DELETE_WINDOW); @@ -335,6 +337,8 @@ void QXcbWindow::setGeometry(const QRect &rect) { QPlatformWindow::setGeometry(rect); + propagateSizeHints(); + const quint32 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; const quint32 values[] = { rect.x(), rect.y(), @@ -1062,11 +1066,12 @@ void QXcbWindow::propagateSizeHints() QRect rect = geometry(); + QWindow *win = window(); + xcb_size_hints_set_position(&hints, true, rect.x(), rect.y()); xcb_size_hints_set_size(&hints, true, rect.width(), rect.height()); - xcb_size_hints_set_win_gravity(&hints, XCB_GRAVITY_STATIC); - - QWindow *win = window(); + xcb_size_hints_set_win_gravity(&hints, qt_window_private(win)->positionPolicy == QWindowPrivate::WindowFrameInclusive + ? XCB_GRAVITY_NORTH_WEST : XCB_GRAVITY_STATIC); QSize minimumSize = win->minimumSize(); QSize maximumSize = win->maximumSize(); diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index 4c65d08b6a..65ba0fcb5a 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -126,6 +126,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } } + qt_window_private(win)->positionPolicy = topData()->posFromMove ? QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive; win->create(); data.window_flags = win->windowFlags(); @@ -661,6 +662,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) { if (q->windowHandle()) { if (q->isWindow()) { + qt_window_private(q->windowHandle())->positionPolicy = topData()->posFromMove ? QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive; q->windowHandle()->setGeometry(q->geometry()); } else { QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint()); diff --git a/tests/auto/qwindow/tst_qwindow.cpp b/tests/auto/qwindow/tst_qwindow.cpp index 77e3d5f88c..3eedd7cf6f 100644 --- a/tests/auto/qwindow/tst_qwindow.cpp +++ b/tests/auto/qwindow/tst_qwindow.cpp @@ -40,7 +40,10 @@ ****************************************************************************/ #include <qwindow.h> -#include <qtest.h> + +#include <QtTest/QtTest> + +#include "../../shared/util.h" class tst_QWindow: public QObject { @@ -48,6 +51,7 @@ class tst_QWindow: public QObject private slots: void mapGlobal(); + void positioning(); }; @@ -70,5 +74,94 @@ void tst_QWindow::mapGlobal() QCOMPARE(c.mapFromGlobal(QPoint(100, 100)), QPoint(30, 30)); } +class Window : public QWindow +{ +public: + Window() + : gotResizeEvent(false) + , gotMapEvent(false) + , gotMoveEvent(false) + { + setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); + } + + bool event(QEvent *event) + { + switch (event->type()) { + case QEvent::Map: + gotMapEvent = true; + break; + case QEvent::Resize: + gotResizeEvent = true; + break; + case QEvent::Move: + gotMoveEvent = true; + break; + default: + break; + } + + return QWindow::event(event); + } + + bool gotResizeEvent; + bool gotMapEvent; + bool gotMoveEvent; +}; + +void tst_QWindow::positioning() +{ + QRect geometry(80, 80, 40, 40); + + Window window; + window.setGeometry(geometry); + QCOMPARE(window.geometry(), geometry); + window.show(); + + QTRY_VERIFY(window.gotResizeEvent && window.gotMapEvent); + + QMargins originalMargins = window.frameMargins(); + + QCOMPARE(window.pos(), window.framePos() + QPoint(originalMargins.left(), originalMargins.top())); + QVERIFY(window.frameGeometry().contains(window.geometry())); + + QPoint originalPos = window.pos(); + QPoint originalFramePos = window.framePos(); + + window.gotResizeEvent = false; + + window.setWindowState(Qt::WindowFullScreen); + QTRY_VERIFY(window.gotResizeEvent); + + window.gotResizeEvent = false; + window.setWindowState(Qt::WindowNoState); + QTRY_VERIFY(window.gotResizeEvent); + + QTRY_COMPARE(originalPos, window.pos()); + QTRY_COMPARE(originalFramePos, window.framePos()); + QTRY_COMPARE(originalMargins, window.frameMargins()); + + // if our positioning is actually fully respected by the window manager + // test whether it correctly handles frame positioning as well + if (originalPos == geometry.topLeft() && (originalMargins.top() != 0 || originalMargins.left() != 0)) { + QPoint framePos(40, 40); + + window.gotMoveEvent = false; + window.setFramePos(framePos); + + QTRY_VERIFY(window.gotMoveEvent); + QTRY_COMPARE(framePos, window.framePos()); + QTRY_COMPARE(originalMargins, window.frameMargins()); + QCOMPARE(window.pos(), window.framePos() + QPoint(originalMargins.left(), originalMargins.top())); + + // and back to regular positioning + + window.gotMoveEvent = false; + window.setPos(originalPos); + QTRY_VERIFY(window.gotMoveEvent); + QTRY_COMPARE(originalPos, window.pos()); + } +} + #include <tst_qwindow.moc> QTEST_MAIN(tst_QWindow); |