summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-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;