summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@nokia.com>2012-04-17 17:30:06 +0200
committerQt by Nokia <qt-info@nokia.com>2012-05-09 13:40:16 +0200
commitb316c3ac5e4acac75505bfd77677cecc181599af (patch)
treef51ac1f01bed8c1bf3987f1dfee1080056ac3503 /src/widgets
parent465c9f4a7e89883ebe3d473b4cd4e36310884173 (diff)
Improve widget geometry.
- Rename posFromMove to posIncludesFrame in Widgets and make the handling more fine-grained; try to clean it up as soon as the frame margins are known in QWidgetPrivate::fixPosIncludesFrame(). - Implement QWidgetPrivate::updateFrameStrut(). - Windows: Handle posIncludesFrame in window creation, notify changed geometry after setting window flags. - XCB: Do not change the window gravity in propagateSizeHint() as this causes the window to jump around. Determine the gravity in window creation, leave it constant and fix the geometry when setting instead. - Store the normal geometry when maximize/fullscreen state change events are received. - Remove xfails from fixed tests Task-number: QTBUG-25331 Task-number: QTBUG-24905 Task-number: QTBUG-24294 Change-Id: I89c7229d86aaf88f02247d63915da7905e4a27ea Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/kernel/qwidget.cpp26
-rw-r--r--src/widgets/kernel/qwidget_p.h3
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp54
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa.cpp15
4 files changed, 79 insertions, 19 deletions
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index dcd052a94e..2a8a25e4fc 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -1530,7 +1530,7 @@ void QWidgetPrivate::createTLExtra()
x->normalGeometry = QRect(0,0,-1,-1);
x->savedFlags = 0;
x->opacity = 255;
- x->posFromMove = false;
+ x->posIncludesFrame = 0;
x->sizeAdjusted = false;
x->inTopLevelResize = false;
x->inRepaint = false;
@@ -3242,11 +3242,11 @@ int QWidget::y() const
QPoint QWidget::pos() const
{
Q_D(const QWidget);
- if (isWindow() && ! (windowType() == Qt::Popup)) {
- QRect fs = d->frameStrut();
- return QPoint(data->crect.x() - fs.left(), data->crect.y() - fs.top());
- }
- return data->crect.topLeft();
+ QPoint result = data->crect.topLeft();
+ if (isWindow() && ! (windowType() == Qt::Popup))
+ if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
+ result -= d->frameStrut().topLeft();
+ return result;
}
/*!
@@ -6475,14 +6475,17 @@ void QWidget::move(const QPoint &p)
{
Q_D(QWidget);
setAttribute(Qt::WA_Moved);
- if (isWindow())
- d->topData()->posFromMove = true;
if (testAttribute(Qt::WA_WState_Created)) {
+ if (isWindow())
+ d->topData()->posIncludesFrame = false;
d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
p.y() + geometry().y() - QWidget::y(),
width(), height(), true);
d->setDirtyOpaqueRegion();
} else {
+ // no frame yet: see also QWidgetPrivate::fixPosIncludesFrame(), QWindowPrivate::PositionPolicy.
+ if (isWindow())
+ d->topData()->posIncludesFrame = true;
data->crect.moveTopLeft(p); // no frame yet
setAttribute(Qt::WA_PendingMoveEvent);
}
@@ -6499,6 +6502,7 @@ void QWidget::resize(const QSize &s)
Q_D(QWidget);
setAttribute(Qt::WA_Resized);
if (testAttribute(Qt::WA_WState_Created)) {
+ d->fixPosIncludesFrame();
d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
d->setDirtyOpaqueRegion();
} else {
@@ -6513,7 +6517,7 @@ void QWidget::setGeometry(const QRect &r)
setAttribute(Qt::WA_Resized);
setAttribute(Qt::WA_Moved);
if (isWindow())
- d->topData()->posFromMove = false;
+ d->topData()->posIncludesFrame = 0;
if (testAttribute(Qt::WA_WState_Created)) {
d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
d->setDirtyOpaqueRegion();
@@ -6681,11 +6685,11 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
restoredNormalGeometry.moveTop(qMax(restoredNormalGeometry.top(), availableGeometry.top() + frameHeight));
if (maximized || fullScreen) {
- // set geomerty before setting the window state to make
+ // set geometry before setting the window state to make
// sure the window is maximized to the right screen.
// Skip on windows: the window is restored into a broken
// half-maximized state.
-#ifndef Q_WS_WIN
+#ifndef Q_OS_WIN
setGeometry(restoredNormalGeometry);
#endif
Qt::WindowStates ws = windowState();
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index d7c0ec75b0..4b3216c6f0 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -157,7 +157,7 @@ struct QTLWExtra {
// *************************** Cross-platform bit fields ****************************
uint opacity : 8;
- uint posFromMove : 1;
+ uint posIncludesFrame : 1;
uint sizeAdjusted : 1;
uint inTopLevelResize : 1;
uint inRepaint : 1;
@@ -432,6 +432,7 @@ public:
void scroll_sys(int dx, int dy, const QRect &r);
void deactivateWidgetCleanup();
void setGeometry_sys(int, int, int, int, bool);
+ void fixPosIncludesFrame();
void sendPendingMoveAndResizeEvents(bool recursive = false, bool disableUpdates = false);
void activateChildLayoutsRecursively();
void show_recursive();
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
index 97cf921691..3666764e94 100644
--- a/src/widgets/kernel/qwidget_qpa.cpp
+++ b/src/widgets/kernel/qwidget_qpa.cpp
@@ -55,6 +55,7 @@
#include <qpa/qplatformcursor.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
+#include <QtCore/QMargins>
QT_BEGIN_NAMESPACE
@@ -105,6 +106,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
}
win->setWindowFlags(data.window_flags);
+ fixPosIncludesFrame();
win->setGeometry(q->geometry());
win->setScreen(QGuiApplication::screens().value(topData()->screenIndex, 0));
@@ -126,7 +128,8 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
}
}
- qt_window_private(win)->positionPolicy = topData()->posFromMove ? QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
+ qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
+ QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
win->create();
data.window_flags = win->windowFlags();
@@ -438,6 +441,31 @@ static inline QRect positionTopLevelWindow(QRect geometry, const QScreen *screen
return geometry;
}
+// move() was invoked with Qt::WA_WState_Created not set (frame geometry
+// unknown), that is, crect has a position including the frame.
+// If we can determine the frame strut, fix that and clear the flag.
+void QWidgetPrivate::fixPosIncludesFrame()
+{
+ Q_Q(QWidget);
+ if (QTLWExtra *te = maybeTopData()) {
+ if (te->posIncludesFrame) {
+ // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
+ // example, in QGraphicsProxyWidget).
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ te->posIncludesFrame = 0;
+ } else {
+ if (q->windowHandle()) {
+ updateFrameStrut();
+ if (!q->data->fstrut_dirty) {
+ data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
+ te->posIncludesFrame = 0;
+ }
+ } // windowHandle()
+ } // !WA_DontShowOnScreen
+ } // posIncludesFrame
+ } // QTLWExtra
+}
+
void QWidgetPrivate::show_sys()
{
Q_Q(QWidget);
@@ -460,6 +488,8 @@ void QWidgetPrivate::show_sys()
return;
if (window) {
+ if (q->isWindow())
+ fixPosIncludesFrame();
QRect geomRect = q->geometry();
if (q->isWindow()) {
if (!q->testAttribute(Qt::WA_Moved))
@@ -545,7 +575,7 @@ void QWidgetPrivate::setFullScreenSize_helper()
data.in_set_window_state = old_state;
}
-static Qt::WindowState effectiveState(Qt::WindowStates state)
+Qt::WindowState effectiveState(Qt::WindowStates state)
{
if (state & Qt::WindowMinimized)
return Qt::WindowMinimized;
@@ -707,7 +737,6 @@ 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());
@@ -763,8 +792,10 @@ void QWidgetPrivate::setConstraints_sys()
winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
}
- if (winp->platformWindow)
+ if (winp->platformWindow) {
+ fixPosIncludesFrame();
winp->platformWindow->propagateSizeHints();
+ }
}
}
@@ -895,7 +926,20 @@ void QWidgetPrivate::setMask_sys(const QRegion &region)
void QWidgetPrivate::updateFrameStrut()
{
- // XXX
+ Q_Q(QWidget);
+ if (q->data->fstrut_dirty) {
+ if (QTLWExtra *te = maybeTopData()) {
+ if (te->window) {
+ if (const QPlatformWindow *pw = te->window->handle()) {
+ const QMargins margins = pw->frameMargins();
+ if (!margins.isNull()) {
+ te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
+ q->data->fstrut_dirty = false;
+ }
+ }
+ }
+ }
+ }
}
void QWidgetPrivate::setWindowOpacity_sys(qreal level)
diff --git a/src/widgets/kernel/qwidgetwindow_qpa.cpp b/src/widgets/kernel/qwidgetwindow_qpa.cpp
index 0a45cce62e..34b56b7954 100644
--- a/src/widgets/kernel/qwidgetwindow_qpa.cpp
+++ b/src/widgets/kernel/qwidgetwindow_qpa.cpp
@@ -327,10 +327,13 @@ void QWidgetWindow::updateGeometry()
if (m_widget->testAttribute(Qt::WA_OutsideWSRange))
return;
- QMargins margins = frameMargins();
+ const QMargins margins = frameMargins();
m_widget->data->crect = geometry();
- m_widget->d_func()->topData()->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
+ QTLWExtra *te = m_widget->d_func()->topData();
+ te->posIncludesFrame= false;
+ te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
+ m_widget->data->fstrut_dirty = false;
}
void QWidgetWindow::handleMoveEvent(QMoveEvent *event)
@@ -447,6 +450,8 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
}
}
+Qt::WindowState effectiveState(Qt::WindowStates state);
+
void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event)
{
// QWindow does currently not know 'active'.
@@ -465,10 +470,16 @@ void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event
widgetState |= Qt::WindowMinimized;
break;
case Qt::WindowMaximized:
+ if (effectiveState(widgetState) == Qt::WindowNoState)
+ if (QTLWExtra *tle = m_widget->d_func()->maybeTopData())
+ tle->normalGeometry = m_widget->geometry();
widgetState &= ~Qt::WindowFullScreen;
widgetState |= Qt::WindowMaximized;
break;
case Qt::WindowFullScreen:
+ if (effectiveState(widgetState) == Qt::WindowNoState)
+ if (QTLWExtra *tle = m_widget->d_func()->maybeTopData())
+ tle->normalGeometry = m_widget->geometry();
widgetState &= ~Qt::WindowMaximized;
widgetState |= Qt::WindowFullScreen;
break;