= 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="
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);
}
<< " 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.
// 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;
}
/*!
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()));
}
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);
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;
};
}
}
+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)
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
| 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);
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)));
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();
void setTransparentForMouseEvents(bool transparent);
void updateDoesNotAcceptFocus(bool doesNotAcceptFocus);
+ QRect windowToWmGeometry(QRect r) const;
+
void create();
void destroy();
Qt::WindowState m_windowState;
+ xcb_gravity_t m_gravity;
+
bool m_mapped;
bool m_transparent;
bool m_deferredActivation;
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;
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;
}
/*!
{
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);
}
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 {
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();
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();
// *************************** Cross-platform bit fields ****************************
uint opacity : 8;
- uint posFromMove : 1;
+ uint posIncludesFrame : 1;
uint sizeAdjusted : 1;
uint inTopLevelResize : 1;
uint inRepaint : 1;
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();
#include <qpa/qplatformcursor.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
+#include <QtCore/QMargins>
QT_BEGIN_NAMESPACE
}
win->setWindowFlags(data.window_flags);
+ fixPosIncludesFrame();
win->setGeometry(q->geometry());
win->setScreen(QGuiApplication::screens().value(topData()->screenIndex, 0));
}
}
- 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();
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);
return;
if (window) {
+ if (q->isWindow())
+ fixPosIncludesFrame();
QRect geomRect = q->geometry();
if (q->isWindow()) {
if (!q->testAttribute(Qt::WA_Moved))
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;
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());
winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
}
- if (winp->platformWindow)
+ if (winp->platformWindow) {
+ fixPosIncludesFrame();
winp->platformWindow->propagateSizeHints();
+ }
}
}
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)
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)
}
}
+Qt::WindowState effectiveState(Qt::WindowStates state);
+
void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event)
{
// QWindow does currently not know 'active'.
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;
#if defined(Q_OS_WINCE)
QSKIP("No real support for Qt::Tool on WinCE");
#endif
-#ifdef Q_OS_WIN
- QSKIP("QTBUG-25331 - positioning failure");
-#endif
QDialog dialog(0, Qt::Tool);
dialog.move(QPoint(100,100));
const QPoint beforeShowPosition = dialog.pos();
// QRect(0, 0, 200, 12) is the first update, expanded (-2, -2, 2, 2)
// QRect(0, 12, 102, 10) is the scroll update, expanded (-2, -2, 2, 2),
// intersected with the above update.
-#ifdef Q_OS_WIN
- QEXPECT_FAIL("", "QTBUG-24294", Abort);
-#endif
QCOMPARE(view.paintEventRegion.rects(),
QVector<QRect>() << QRect(0, 0, 200, 12) << QRect(0, 12, 102, 10));
QCOMPARE(widget->npaints, 2);
QTest::mousePress(view.viewport(), Qt::LeftButton, 0,
view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
-#ifdef Q_OS_WIN
- QEXPECT_FAIL("", "QTBUG-24294", Abort);
-#endif
QTRY_COMPARE(box->pos(), QPoint());
QCOMPARE(proxy->childItems().count(), 1);
void tst_QGraphicsProxyWidget::updateAndDelete()
{
+#ifdef Q_OS_MAC
+ QSKIP("Test case unstable on this platform, QTBUG-23700");
+#endif
QGraphicsScene scene;
QGraphicsProxyWidget *proxy = scene.addWidget(new QPushButton("Hello World"));
View view(&scene);
qt_x11_wait_for_window_manager(&view);
#endif
QTRY_VERIFY(view.npaints > 0);
+ // Wait a bit to clear all pending paint events
+ QTest::qWait(10);
const QRect itemDeviceBoundingRect = proxy->deviceTransform(view.viewportTransform())
.mapRect(proxy->boundingRect()).toRect();
// Update and hide.
proxy->update();
proxy->hide();
-#ifdef Q_OS_WIN
- QEXPECT_FAIL("", "QTBUG-24294", Abort);
-#endif
QTRY_COMPARE(view.npaints, 1);
-#ifdef Q_OS_MAC
- QEXPECT_FAIL("", "QTBUG-23700", Continue);
-#endif
QCOMPARE(view.paintEventRegion, expectedRegion);
proxy->show();
void tst_QWidget_window::tst_move_show()
{
-#ifdef Q_OS_WIN
- QSKIP("QTBUG-25331");
-#endif
QWidget w;
w.move(100, 100);
w.show();