summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
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/plugins/platforms
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/plugins/platforms')
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp42
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp45
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h4
5 files changed, 80 insertions, 21 deletions
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 69ae653f5b..255cf1454c 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -244,8 +244,10 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
= QWindowsWindow::WindowData::create(window, requested, window->windowTitle());
if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
qDebug().nospace()
- << __FUNCTION__ << ' ' << window << '\n'
- << " Requested: " << requested.geometry << " Flags="
+ << __FUNCTION__ << '<' << window << '\n'
+ << " Requested: " << requested.geometry << "frame incl.: "
+ << QWindowsGeometryHint::positionIncludesFrame(window)
+ << " Flags="
<< QWindowsWindow::debugWindowFlags(requested.flags) << '\n'
<< " Obtained : " << obtained.geometry << " Margins "
<< obtained.frame << " Flags="
@@ -255,8 +257,6 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
return 0;
if (requested.flags != obtained.flags)
window->setWindowFlags(obtained.flags);
- if (requested.geometry != obtained.geometry)
- QWindowSystemInterface::handleGeometryChange(window, obtained.geometry);
return new QWindowsWindow(window, obtained);
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 87980487b7..c300f0f5a9 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -542,6 +542,12 @@ void QWindowsGeometryHint::applyToMinMaxInfo(DWORD style, DWORD exStyle, MINMAXI
<< " out " << *mmi;
}
+bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w)
+{
+ return qt_window_private(const_cast<QWindow *>(w))->positionPolicy
+ == QWindowPrivate::WindowFrameInclusive;
+}
+
/*!
\class QWindowCreationContext
\brief Active Context for creating windows.
@@ -576,17 +582,24 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
// CW_USEDEFAULT unless set. For now, assume that 0,0 means 'default'
// for toplevels.
if (geometry.isValid()) {
- if (!w->isTopLevel() || geometry.y() >= margins.top()) {
- frameX = geometry.x() - margins.left();
- frameY = geometry.y() - margins.top();
+ frameX = geometry.x();
+ frameY = geometry.y();
+ frameWidth = margins.left() + geometry.width() + margins.right();
+ frameHeight = margins.top() + geometry.height() + margins.bottom();
+ const bool isDefaultPosition = !frameX && !frameY && w->isTopLevel();
+ if (!QWindowsGeometryHint::positionIncludesFrame(w) && !isDefaultPosition) {
+ frameX -= margins.left();
+ frameY -= margins.top();
}
- frameWidth = geometry.width() + margins.left() + margins.right();
- frameHeight = geometry.height() + margins.top() + margins.bottom();
}
if (QWindowsContext::verboseWindows)
qDebug().nospace()
- << __FUNCTION__ << ' ' << w << " min" << geometryHint.minimumSize
- << " min" << geometryHint.maximumSize;
+ << __FUNCTION__ << ' ' << w << geometry
+ << " pos incl. frame" << QWindowsGeometryHint::positionIncludesFrame(w)
+ << " frame: " << frameWidth << 'x' << frameHeight << '+'
+ << frameX << '+' << frameY
+ << " min" << geometryHint.minimumSize
+ << " max" << geometryHint.maximumSize;
}
/*!
@@ -819,7 +832,7 @@ void QWindowsWindow::setGeometry(const QRect &rectIn)
QRect rect = rectIn;
// This means it is a call from QWindow::setFramePos() and
// the coordinates include the frame (size is still the contents rectangle).
- if (qt_window_private(window())->positionPolicy == QWindowPrivate::WindowFrameInclusive) {
+ if (QWindowsGeometryHint::positionIncludesFrame(window())) {
const QMargins margins = frameMargins();
rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
}
@@ -1004,21 +1017,30 @@ Qt::WindowFlags QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
qDebug() << '>' << __FUNCTION__ << this << window() << "\n from: "
<< QWindowsWindow::debugWindowFlags(m_data.flags)
<< "\n to: " << QWindowsWindow::debugWindowFlags(flags);
+ const QRect oldGeometry = geometry();
if (m_data.flags != flags) {
m_data.flags = flags;
if (m_data.hwnd)
m_data = setWindowFlags_sys(flags);
}
+ // When switching to a frameless window, geometry
+ // may change without a WM_MOVE. Report change manually.
+ // Do not send synchronously as not to clobber the widget
+ // geometry in a sequence of setting flags and geometry.
+ const QRect newGeometry = geometry_sys();
+ if (oldGeometry != newGeometry)
+ handleGeometryChange();
+
if (QWindowsContext::verboseWindows)
qDebug() << '<' << __FUNCTION__ << "\n returns: "
- << QWindowsWindow::debugWindowFlags(m_data.flags);
+ << QWindowsWindow::debugWindowFlags(m_data.flags)
+ << " geometry " << oldGeometry << "->" << newGeometry;
return m_data.flags;
}
QWindowsWindow::WindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
unsigned flags) const
{
- // Geometry changes have not been observed here. Frames change, though.
WindowCreationData creationData;
creationData.fromWindow(window(), wt, flags);
creationData.applyWindowFlags(m_data.hwnd);
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 87c22c76d1..64fd78d1ce 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -66,6 +66,8 @@ struct QWindowsGeometryHint
static inline QPoint mapFromGlobal(const HWND hwnd, const QPoint &);
static inline QPoint mapFromGlobal(const QWindow *w, const QPoint &);
+ static bool positionIncludesFrame(const QWindow *w);
+
QSize minimumSize;
QSize maximumSize;
};
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 2355043c56..93f1159546 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -138,10 +138,16 @@ static inline QImage::Format imageFormatForDepth(int depth)
}
}
+static inline bool positionIncludesFrame(QWindow *w)
+{
+ return qt_window_private(w)->positionPolicy == QWindowPrivate::WindowFrameInclusive;
+}
+
QXcbWindow::QXcbWindow(QWindow *window)
: QPlatformWindow(window)
, m_window(0)
, m_syncCounter(0)
+ , m_gravity(XCB_GRAVITY_STATIC)
, m_mapped(false)
, m_transparent(false)
, m_deferredActivation(false)
@@ -176,6 +182,11 @@ void QXcbWindow::create()
return;
}
+ // Determine gravity from initial position. Do not change
+ // later as it will cause the window to move uncontrollably.
+ m_gravity = positionIncludesFrame(window()) ?
+ XCB_GRAVITY_NORTH_WEST : XCB_GRAVITY_STATIC;
+
const quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER | XCB_CW_EVENT_MASK;
const quint32 values[] = {
// XCB_CW_BACK_PIXMAP
@@ -199,6 +210,9 @@ void QXcbWindow::create()
| XCB_EVENT_MASK_FOCUS_CHANGE
};
+ // Parameters to XCreateWindow() are frame corner + inner size.
+ // This fits in case position policy is frame inclusive. There is
+ // currently no way to implement it for frame-exclusive geometries.
QRect rect = window()->geometry();
QPlatformWindow::setGeometry(rect);
@@ -398,13 +412,14 @@ void QXcbWindow::setGeometry(const QRect &rect)
QPlatformWindow::setGeometry(rect);
propagateSizeHints();
+ const QRect wmGeometry = windowToWmGeometry(rect);
const quint32 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
const qint32 values[] = {
- qBound<qint32>(-XCOORD_MAX, rect.x(), XCOORD_MAX),
- qBound<qint32>(-XCOORD_MAX, rect.y(), XCOORD_MAX),
- qBound<qint32>(1, rect.width(), XCOORD_MAX),
- qBound<qint32>(1, rect.height(), XCOORD_MAX),
+ qBound<qint32>(-XCOORD_MAX, wmGeometry.x(), XCOORD_MAX),
+ qBound<qint32>(-XCOORD_MAX, wmGeometry.y(), XCOORD_MAX),
+ qBound<qint32>(1, wmGeometry.width(), XCOORD_MAX),
+ qBound<qint32>(1, wmGeometry.height(), XCOORD_MAX),
};
Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values)));
@@ -1118,20 +1133,36 @@ void QXcbWindow::lower()
Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values));
}
+// Adapt the geometry to match the WM expection with regards
+// to gravity.
+QRect QXcbWindow::windowToWmGeometry(QRect r) const
+{
+ if (m_dirtyFrameMargins || m_frameMargins.isNull())
+ return r;
+ const bool frameInclusive = positionIncludesFrame(window());
+ // XCB_GRAVITY_STATIC requires the inner geometry, whereas
+ // XCB_GRAVITY_NORTH_WEST requires the frame geometry
+ if (frameInclusive && m_gravity == XCB_GRAVITY_STATIC) {
+ r.translate(m_frameMargins.left(), m_frameMargins.top());
+ } else if (!frameInclusive && m_gravity == XCB_GRAVITY_NORTH_WEST) {
+ r.translate(-m_frameMargins.left(), -m_frameMargins.top());
+ }
+ return r;
+}
+
void QXcbWindow::propagateSizeHints()
{
// update WM_NORMAL_HINTS
xcb_size_hints_t hints;
memset(&hints, 0, sizeof(hints));
- QRect rect = geometry();
+ const QRect rect = windowToWmGeometry(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, qt_window_private(win)->positionPolicy == QWindowPrivate::WindowFrameInclusive
- ? XCB_GRAVITY_NORTH_WEST : XCB_GRAVITY_STATIC);
+ xcb_size_hints_set_win_gravity(&hints, m_gravity);
QSize minimumSize = win->minimumSize();
QSize maximumSize = win->maximumSize();
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 0b82196c27..43eb9e8639 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -148,6 +148,8 @@ private:
void setTransparentForMouseEvents(bool transparent);
void updateDoesNotAcceptFocus(bool doesNotAcceptFocus);
+ QRect windowToWmGeometry(QRect r) const;
+
void create();
void destroy();
@@ -166,6 +168,8 @@ private:
Qt::WindowState m_windowState;
+ xcb_gravity_t m_gravity;
+
bool m_mapped;
bool m_transparent;
bool m_deferredActivation;