summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/kernel/qwindow.cpp60
-rw-r--r--src/gui/kernel/qwindow.h17
-rw-r--r--src/gui/kernel/qwindow_p.h9
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp11
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp2
-rw-r--r--tests/auto/qwindow/tst_qwindow.cpp95
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);