Make QWindow's windowState a QFlags of the WindowState

This reflects QWidget API, and restores some behavior from Qt4.
Some WM can have several state at the same time. On Plasma for example,
when a window is both maximized and minimized, the "maximized" checkbox
is checked from the taskbar entry.

The API of QPlatformWindow was changed to take a QFlag and the platform
plugins were adapted.

 - On XCB: Always send the full state to the WM. And read the full state.

 - On Windows: The code was originally written with '&' in Qt4, and was changed
   to == when porting. Some adaptation had to be made so the states would be
   preserved.

 - On macOS: Only a single state can be set and is reported back for now,
   with the possibly to expand this in the future.

 - Other platforms: Just do as before with the effective state.

Task-number: QTBUG-57882
Task-number: QTBUG-52616
Task-number: QTBUG-52555
Change-Id: I7a1f7cac64236bbd4c591f796374315639233dad
Reviewed-by: Gunnar Sletta <gunnar@crimson.no>
Reviewed-by: Robin Burchell <robin.burchell@crimson.no>
bb10
Olivier Goffart 2017-02-01 17:21:33 +01:00 committed by Olivier Goffart (Woboq GmbH)
parent 44f406ce95
commit a02959bb5b
35 changed files with 412 additions and 333 deletions

View File

@ -261,7 +261,7 @@ QPoint QPlatformWindow::mapFromGlobal(const QPoint &pos) const
Qt::WindowActive can be ignored.
*/
void QPlatformWindow::setWindowState(Qt::WindowState)
void QPlatformWindow::setWindowState(Qt::WindowStates)
{
}

View File

@ -89,7 +89,7 @@ public:
virtual void setVisible(bool visible);
virtual void setWindowFlags(Qt::WindowFlags flags);
virtual void setWindowState(Qt::WindowState state);
virtual void setWindowState(Qt::WindowStates state);
virtual WId winId() const;
virtual void setParent(const QPlatformWindow *window);

View File

@ -116,7 +116,7 @@ QT_BEGIN_NAMESPACE
application, isExposed() will simply return the same value as isVisible().
QWindow::Visibility queried through visibility() is a convenience API
combining the functions of visible() and windowState().
combining the functions of visible() and windowStates().
\section1 Rendering
@ -323,27 +323,16 @@ void QWindowPrivate::updateVisibility()
QWindow::Visibility old = visibility;
if (visible) {
switch (windowState) {
case Qt::WindowMinimized:
visibility = QWindow::Minimized;
break;
case Qt::WindowMaximized:
visibility = QWindow::Maximized;
break;
case Qt::WindowFullScreen:
visibility = QWindow::FullScreen;
break;
case Qt::WindowNoState:
visibility = QWindow::Windowed;
break;
default:
Q_ASSERT(false);
break;
}
} else {
if (!visible)
visibility = QWindow::Hidden;
}
else if (windowState & Qt::WindowMinimized)
visibility = QWindow::Minimized;
else if (windowState & Qt::WindowFullScreen)
visibility = QWindow::FullScreen;
else if (windowState & Qt::WindowMaximized)
visibility = QWindow::Maximized;
else
visibility = QWindow::Windowed;
if (visibility != old)
emit q->visibilityChanged(visibility);
@ -1216,6 +1205,17 @@ qreal QWindow::devicePixelRatio() const
return d->platformWindow->devicePixelRatio() * QHighDpiScaling::factor(this);
}
Qt::WindowState QWindowPrivate::effectiveState(Qt::WindowStates state)
{
if (state & Qt::WindowMinimized)
return Qt::WindowMinimized;
else if (state & Qt::WindowFullScreen)
return Qt::WindowFullScreen;
else if (state & Qt::WindowMaximized)
return Qt::WindowMaximized;
return Qt::WindowNoState;
}
/*!
\brief set the screen-occupation state of the window
@ -1224,29 +1224,67 @@ qreal QWindow::devicePixelRatio() const
The enum value Qt::WindowActive is not an accepted parameter.
\sa showNormal(), showFullScreen(), showMinimized(), showMaximized()
\sa showNormal(), showFullScreen(), showMinimized(), showMaximized(), setWindowStates()
*/
void QWindow::setWindowState(Qt::WindowState state)
{
if (state == Qt::WindowActive) {
qWarning("QWindow::setWindowState does not accept Qt::WindowActive");
return;
setWindowStates(state);
}
/*!
\brief set the screen-occupation state of the window
\since 5.10
The window \a state represents whether the window appears in the
windowing system as maximized, minimized and/or fullscreen.
The window can be in a combination of several states. For example, if
the window is both minimized and maximized, the window will appear
minimized, but clicking on the task bar entry will restore it to the
maximized state.
The enum value Qt::WindowActive should not be set.
\sa showNormal(), showFullScreen(), showMinimized(), showMaximized()
*/
void QWindow::setWindowStates(Qt::WindowStates state)
{
Q_D(QWindow);
if (state & Qt::WindowActive) {
qWarning("QWindow::setWindowStates does not accept Qt::WindowActive");
state &= ~Qt::WindowActive;
}
Q_D(QWindow);
if (d->platformWindow)
d->platformWindow->setWindowState(state);
d->windowState = state;
emit windowStateChanged(d->windowState);
emit windowStateChanged(QWindowPrivate::effectiveState(d->windowState));
d->updateVisibility();
}
/*!
\brief the screen-occupation state of the window
\sa setWindowState()
\sa setWindowState(), windowStates()
*/
Qt::WindowState QWindow::windowState() const
{
Q_D(const QWindow);
return QWindowPrivate::effectiveState(d->windowState);
}
/*!
\brief the screen-occupation state of the window
\since 5.10
The window can be in a combination of several states. For example, if
the window is both minimized and maximized, the window will appear
minimized, but clicking on the task bar entry will restore it to
the maximized state.
\sa setWindowStates()
*/
Qt::WindowStates QWindow::windowStates() const
{
Q_D(const QWindow);
return d->windowState;
@ -1256,7 +1294,7 @@ Qt::WindowState QWindow::windowState() const
\fn QWindow::windowStateChanged(Qt::WindowState windowState)
This signal is emitted when the \a windowState changes, either
by being set explicitly with setWindowState(), or automatically when
by being set explicitly with setWindowStates(), or automatically when
the user clicks one of the titlebar buttons or by other means.
*/
@ -1997,42 +2035,42 @@ void QWindow::hide()
/*!
Shows the window as minimized.
Equivalent to calling setWindowState(Qt::WindowMinimized) and then
Equivalent to calling setWindowStates(Qt::WindowMinimized) and then
setVisible(true).
\sa setWindowState(), setVisible()
\sa setWindowStates(), setVisible()
*/
void QWindow::showMinimized()
{
setWindowState(Qt::WindowMinimized);
setWindowStates(Qt::WindowMinimized);
setVisible(true);
}
/*!
Shows the window as maximized.
Equivalent to calling setWindowState(Qt::WindowMaximized) and then
Equivalent to calling setWindowStates(Qt::WindowMaximized) and then
setVisible(true).
\sa setWindowState(), setVisible()
\sa setWindowStates(), setVisible()
*/
void QWindow::showMaximized()
{
setWindowState(Qt::WindowMaximized);
setWindowStates(Qt::WindowMaximized);
setVisible(true);
}
/*!
Shows the window as fullscreen.
Equivalent to calling setWindowState(Qt::WindowFullScreen) and then
Equivalent to calling setWindowStates(Qt::WindowFullScreen) and then
setVisible(true).
\sa setWindowState(), setVisible()
\sa setWindowStates(), setVisible()
*/
void QWindow::showFullScreen()
{
setWindowState(Qt::WindowFullScreen);
setWindowStates(Qt::WindowFullScreen);
setVisible(true);
#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
// activating it here before libscreen activates it causes problems
@ -2043,14 +2081,14 @@ void QWindow::showFullScreen()
/*!
Shows the window as normal, i.e. neither maximized, minimized, nor fullscreen.
Equivalent to calling setWindowState(Qt::WindowNoState) and then
Equivalent to calling setWindowStates(Qt::WindowNoState) and then
setVisible(true).
\sa setWindowState(), setVisible()
\sa setWindowStates(), setVisible()
*/
void QWindow::showNormal()
{
setWindowState(Qt::WindowNoState);
setWindowStates(Qt::WindowNoState);
setVisible(true);
}
@ -2246,7 +2284,7 @@ bool QWindow::event(QEvent *ev)
case QEvent::WindowStateChange: {
Q_D(QWindow);
emit windowStateChanged(d->windowState);
emit windowStateChanged(QWindowPrivate::effectiveState(d->windowState));
d->updateVisibility();
break;
}

View File

@ -189,7 +189,9 @@ public:
qreal devicePixelRatio() const;
Qt::WindowState windowState() const;
Qt::WindowStates windowStates() const;
void setWindowState(Qt::WindowState state);
void setWindowStates(Qt::WindowStates states);
void setTransientParent(QWindow *parent);
QWindow *transientParent() const;

View File

@ -151,6 +151,8 @@ public:
static QWindowPrivate *get(QWindow *window) { return window->d_func(); }
static Qt::WindowState effectiveState(Qt::WindowStates);
QWindow::SurfaceType surfaceType;
Qt::WindowFlags windowFlags;
QWindow *parentWindow;
@ -163,7 +165,7 @@ public:
QString windowFilePath;
QIcon windowIcon;
QRect geometry;
Qt::WindowState windowState;
Qt::WindowStates windowState;
QWindow::Visibility visibility;
bool resizeEventPending;
bool receivedExpose;

View File

@ -241,14 +241,14 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowActivated, QWindow *window, Qt::Fo
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt::WindowState newState, int oldState)
QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt::WindowStates newState, int oldState)
{
Q_ASSERT(window);
if (oldState < Qt::WindowNoState)
oldState = window->windowState();
QWindowSystemInterfacePrivate::WindowStateChangedEvent *e =
new QWindowSystemInterfacePrivate::WindowStateChangedEvent(window, newState, Qt::WindowState(oldState));
new QWindowSystemInterfacePrivate::WindowStateChangedEvent(window, newState, Qt::WindowStates(oldState));
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}

View File

@ -176,7 +176,7 @@ public:
static void handleWindowActivated(QWindow *window, Qt::FocusReason r = Qt::OtherFocusReason);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
static void handleWindowStateChanged(QWindow *window, Qt::WindowState newState, int oldState = -1);
static void handleWindowStateChanged(QWindow *window, Qt::WindowStates newState, int oldState = -1);
static void handleWindowScreenChanged(QWindow *window, QScreen *newScreen);
static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false);

View File

@ -168,13 +168,13 @@ public:
class WindowStateChangedEvent : public WindowSystemEvent {
public:
WindowStateChangedEvent(QWindow *_window, Qt::WindowState _newState, Qt::WindowState _oldState)
WindowStateChangedEvent(QWindow *_window, Qt::WindowStates _newState, Qt::WindowStates _oldState)
: WindowSystemEvent(WindowStateChanged), window(_window), newState(_newState), oldState(_oldState)
{ }
QPointer<QWindow> window;
Qt::WindowState newState;
Qt::WindowState oldState;
Qt::WindowStates newState;
Qt::WindowStates oldState;
};
class WindowScreenChangedEvent : public WindowSystemEvent {

View File

@ -106,7 +106,7 @@ void QFbWindow::setVisible(bool visible)
}
}
void QFbWindow::setWindowState(Qt::WindowState state)
void QFbWindow::setWindowState(Qt::WindowStates state)
{
QPlatformWindow::setWindowState(state);
mWindowState = state;

View File

@ -70,7 +70,7 @@ public:
void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
void setVisible(bool visible) Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE;
void setWindowFlags(Qt::WindowFlags type) Q_DECL_OVERRIDE;
Qt::WindowFlags windowFlags() const;
@ -93,7 +93,7 @@ protected:
QFbBackingStore *mBackingStore;
QRect mOldGeometry;
Qt::WindowFlags mWindowFlags;
Qt::WindowState mWindowState;
Qt::WindowStates mWindowState;
WId mWindowId;
};

View File

@ -56,7 +56,7 @@ QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
m_windowState = Qt::WindowNoState;
static QAtomicInt winIdGenerator(1);
m_windowId = winIdGenerator.fetchAndAddRelaxed(1);
setWindowState(window->windowState());
setWindowState(window->windowStates());
}
void QAndroidPlatformWindow::lower()
@ -103,7 +103,7 @@ void QAndroidPlatformWindow::setVisible(bool visible)
QtAndroid::setApplicationActive();
}
void QAndroidPlatformWindow::setWindowState(Qt::WindowState state)
void QAndroidPlatformWindow::setWindowState(Qt::WindowStates state)
{
if (m_windowState == state)
return;

View File

@ -59,7 +59,7 @@ public:
void setVisible(bool visible) override;
void setWindowState(Qt::WindowState state) override;
void setWindowState(Qt::WindowStates state) override;
void setWindowFlags(Qt::WindowFlags flags) override;
Qt::WindowFlags windowFlags() const;
void setParent(const QPlatformWindow *window) override;
@ -91,7 +91,7 @@ protected:
protected:
Qt::WindowFlags m_windowFlags;
Qt::WindowState m_windowState;
Qt::WindowStates m_windowState;
WId m_windowId;

View File

@ -168,7 +168,7 @@ public:
void hide(bool becauseOfAncestor = false);
void setVisible(bool visible) Q_DECL_OVERRIDE;
void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE;
void setWindowTitle(const QString &title) Q_DECL_OVERRIDE;
void setWindowFilePath(const QString &filePath) Q_DECL_OVERRIDE;
void setWindowIcon(const QIcon &icon) Q_DECL_OVERRIDE;
@ -292,7 +292,7 @@ protected:
void removeChildWindow(QCocoaWindow *child);
Qt::WindowState windowState() const;
void applyWindowState(Qt::WindowState newState);
void applyWindowState(Qt::WindowStates newState);
void toggleMaximized();
void toggleFullScreen();
bool isTransitioningToFullScreen() const;
@ -313,7 +313,7 @@ public: // for QNSView
bool m_viewIsToBeEmbedded; // true if the m_view is intended to be embedded in a "foreign" NSView hiearchy
Qt::WindowFlags m_windowFlags;
Qt::WindowState m_lastReportedWindowState;
Qt::WindowStates m_lastReportedWindowState;
Qt::WindowModality m_windowModality;
QPointer<QWindow> m_enterLeaveTargetWindow;
bool m_windowUnderMouse;

View File

@ -762,7 +762,7 @@ void QCocoaWindow::setVisible(bool visible)
// setWindowState might have been called while the window was hidden and
// will not change the NSWindow state in that case. Sync up here:
applyWindowState(window()->windowState());
applyWindowState(window()->windowStates());
if (window()->windowState() != Qt::WindowMinimized) {
if ((window()->modality() == Qt::WindowModal
@ -1010,7 +1010,7 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
m_windowFlags = flags;
}
void QCocoaWindow::setWindowState(Qt::WindowState state)
void QCocoaWindow::setWindowState(Qt::WindowStates state)
{
if (window()->isVisible())
applyWindowState(state); // Window state set for hidden windows take effect when show() is called
@ -1812,9 +1812,11 @@ QRect QCocoaWindow::nativeWindowGeometry() const
updated yet, so window()->windowState() will reflect the previous state that was
reported to QtGui.
*/
void QCocoaWindow::applyWindowState(Qt::WindowState newState)
void QCocoaWindow::applyWindowState(Qt::WindowStates requestedState)
{
const Qt::WindowState currentState = windowState();
const Qt::WindowState newState = QWindowPrivate::effectiveState(requestedState);
if (newState == currentState)
return;

View File

@ -205,26 +205,23 @@ void QHaikuWindow::requestActivateWindow()
m_window->Activate(true);
}
void QHaikuWindow::setWindowState(Qt::WindowState state)
void QHaikuWindow::setWindowState(Qt::WindowStates state)
{
if (m_windowState == state)
return;
const Qt::WindowState oldState = m_windowState;
const Qt::WindowStates oldState = m_windowState;
m_windowState = state;
if (m_windowState == Qt::WindowMaximized) {
m_window->zoomByQt();
} else if (m_windowState == Qt::WindowMinimized) {
if (m_windowState & Qt::WindowMinimized)
m_window->Minimize(true);
} else if (m_windowState == Qt::WindowNoState) {
if (oldState == Qt::WindowMaximized)
m_window->zoomByQt(); // undo zoom
if (oldState == Qt::WindowMinimized)
m_window->Minimize(false); // undo minimize
}
else if (m_windowState & Qt::WindowMaximized)
m_window->zoomByQt();
else if (oldState & Qt::WindowMinimized)
m_window->Minimize(false); // undo minimize
else if (oldState & Qt::WindowMaximized)
m_window->zoomByQt(); // undo zoom
}
void QHaikuWindow::setWindowFlags(Qt::WindowFlags flags)

View File

@ -94,7 +94,7 @@ public:
BWindow* nativeHandle() const;
void requestActivateWindow() Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE;
void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
void setWindowTitle(const QString &title) Q_DECL_OVERRIDE;
@ -120,7 +120,7 @@ private Q_SLOTS:
void haikuDrawRequest(const QRect &rect);
private:
Qt::WindowState m_windowState;
Qt::WindowStates m_windowState;
};
QT_END_NAMESPACE

View File

@ -176,8 +176,8 @@
return;
// Re-apply window states to update geometry
if (window->windowState() & (Qt::WindowFullScreen | Qt::WindowMaximized))
window->handle()->setWindowState(window->windowState());
if (window->windowStates() & (Qt::WindowFullScreen | Qt::WindowMaximized))
window->handle()->setWindowState(window->windowStates());
}
// Even if the root view controller has both wantsFullScreenLayout and

View File

@ -62,7 +62,7 @@ public:
void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE;
void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE;
void handleContentOrientationChange(Qt::ScreenOrientation orientation) Q_DECL_OVERRIDE;
void setVisible(bool visible) Q_DECL_OVERRIDE;

View File

@ -73,7 +73,7 @@ QIOSWindow::QIOSWindow(QWindow *window)
m_normalGeometry = initialGeometry(window, QPlatformWindow::geometry(),
screen()->availableGeometry().width(), screen()->availableGeometry().height());
setWindowState(window->windowState());
setWindowState(window->windowStates());
setOpacity(window->opacity());
Qt::ScreenOrientation initialOrientation = window->contentOrientation();
@ -229,7 +229,7 @@ bool QIOSWindow::isExposed() const
&& window()->isVisible() && !window()->geometry().isEmpty();
}
void QIOSWindow::setWindowState(Qt::WindowState state)
void QIOSWindow::setWindowState(Qt::WindowStates state)
{
// Update the QWindow representation straight away, so that
// we can update the statusbar visibility based on the new
@ -239,25 +239,15 @@ void QIOSWindow::setWindowState(Qt::WindowState state)
if (window()->isTopLevel() && window()->isVisible() && window()->isActive())
[m_view.qtViewController updateProperties];
switch (state) {
case Qt::WindowNoState:
applyGeometry(m_normalGeometry);
break;
case Qt::WindowMaximized:
if (state & Qt::WindowMinimized)
applyGeometry(QRect());
else if (state & Qt::WindowFullScreen)
applyGeometry(screen()->geometry());
else if (state & Qt::WindowMaximized)
applyGeometry(window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint ?
screen()->geometry() : screen()->availableGeometry());
break;
case Qt::WindowFullScreen:
applyGeometry(screen()->geometry());
break;
case Qt::WindowMinimized:
applyGeometry(QRect());
break;
case Qt::WindowActive:
Q_UNREACHABLE();
default:
Q_UNREACHABLE();
}
else
applyGeometry(m_normalGeometry);
}
void QIOSWindow::setParent(const QPlatformWindow *parentWindow)

View File

@ -785,8 +785,16 @@ void QMirClientWindow::handleSurfaceStateChanged(Qt::WindowState state)
QWindowSystemInterface::handleWindowStateChanged(window(), state);
}
void QMirClientWindow::setWindowState(Qt::WindowState state)
void QMirClientWindow::setWindowState(Qt::WindowStates states)
{
Qt::WindowState state = Qt::WindowNoState;
if (states & Qt::WindowMinimized)
state = Qt::WindowMinimized;
else if (states & Qt::WindowFullScreen)
state = Qt::WindowFullScreen;
else if (states & Qt::WindowMaximized)
state = Qt::WindowMaximized;
QMutexLocker lock(&mMutex);
qCDebug(mirclient, "setWindowState(window=%p, %s)", this, qtWindowStateToStr(state));

View File

@ -73,7 +73,7 @@ public:
WId winId() const override;
QRect geometry() const override;
void setGeometry(const QRect&) override;
void setWindowState(Qt::WindowState state) override;
void setWindowState(Qt::WindowStates state) override;
void setWindowFlags(Qt::WindowFlags flags) override;
void setVisible(bool visible) override;
void setWindowTitle(const QString &title) override;

View File

@ -56,7 +56,7 @@ QOffscreenWindow::QOffscreenWindow(QWindow *window)
if (window->windowState() == Qt::WindowNoState)
setGeometry(window->geometry());
else
setWindowState(window->windowState());
setWindowState(window->windowStates());
QWindowSystemInterface::flushWindowSystemEvents();
@ -163,26 +163,19 @@ void QOffscreenWindow::setFrameMarginsEnabled(bool enabled)
m_margins = QMargins(0, 0, 0, 0);
}
void QOffscreenWindow::setWindowState(Qt::WindowState state)
void QOffscreenWindow::setWindowState(Qt::WindowStates state)
{
setFrameMarginsEnabled(state != Qt::WindowFullScreen);
setFrameMarginsEnabled(!(state & Qt::WindowFullScreen));
m_positionIncludesFrame = false;
switch (state) {
case Qt::WindowFullScreen:
if (state & Qt::WindowMinimized)
; // nothing to do
else if (state & Qt::WindowFullScreen)
setGeometryImpl(screen()->geometry());
break;
case Qt::WindowMaximized:
else if (state & Qt::WindowMaximized)
setGeometryImpl(screen()->availableGeometry().adjusted(m_margins.left(), m_margins.top(), -m_margins.right(), -m_margins.bottom()));
break;
case Qt::WindowMinimized:
break;
case Qt::WindowNoState:
else
setGeometryImpl(m_normalGeometry);
break;
default:
break;
}
QWindowSystemInterface::handleWindowStateChanged(window(), state);
}

View File

@ -54,7 +54,7 @@ public:
~QOffscreenWindow();
void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowStates states) Q_DECL_OVERRIDE;
QMargins frameMargins() const Q_DECL_OVERRIDE;

View File

@ -586,7 +586,7 @@ void QQnxWindow::setFocus(screen_window_t newFocusWindow)
}
}
void QQnxWindow::setWindowState(Qt::WindowState state)
void QQnxWindow::setWindowState(Qt::WindowStates state)
{
qWindowDebug() << "state =" << state;
@ -749,32 +749,19 @@ void QQnxWindow::updateZorder(screen_window_t window, int &topZorder)
void QQnxWindow::applyWindowState()
{
switch (m_windowState) {
// WindowActive is not an accepted parameter according to the docs
case Qt::WindowActive:
return;
case Qt::WindowMinimized:
if (m_windowState & Qt::WindowMinimized) {
minimize();
if (m_unmaximizedGeometry.isValid())
setGeometry(m_unmaximizedGeometry);
else
setGeometry(m_screen->geometry());
break;
case Qt::WindowMaximized:
case Qt::WindowFullScreen:
} else if (m_windowState & (Qt::WindowMaximized | Qt::WindowFullScreen)) {
m_unmaximizedGeometry = geometry();
setGeometry(m_windowState == Qt::WindowMaximized ? m_screen->availableGeometry() : m_screen->geometry());
break;
case Qt::WindowNoState:
if (m_unmaximizedGeometry.isValid())
setGeometry(m_unmaximizedGeometry);
break;
setGeometry(m_windowState & Qt::WindowFullScreen ? m_screen->geometry()
: m_screen->availableGeometry());
} else if (m_unmaximizedGeometry.isValid()) {
setGeometry(m_unmaximizedGeometry);
}
}

View File

@ -85,7 +85,7 @@ public:
void raise() override;
void lower() override;
void requestActivateWindow() override;
void setWindowState(Qt::WindowState state) override;
void setWindowState(Qt::WindowStates state) override;
void setExposed(bool exposed);
void propagateSizeHints() override;
@ -141,7 +141,7 @@ private:
bool m_visible;
bool m_exposed;
QRect m_unmaximizedGeometry;
Qt::WindowState m_windowState;
Qt::WindowStates m_windowState;
QString m_mmRendererWindowName;
screen_window_t m_mmRendererWindow;

View File

@ -1071,7 +1071,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
updateDropSite(window()->isTopLevel());
registerTouchWindow();
setWindowState(aWindow->windowState());
setWindowState(aWindow->windowStates());
const qreal opacity = qt_window_private(aWindow)->opacity;
if (!qFuzzyCompare(opacity, qreal(1.0)))
setOpacity(opacity);
@ -1338,20 +1338,48 @@ static inline bool testShowWithoutActivating(const QWindow *window)
return showWithoutActivating.isValid() && showWithoutActivating.toBool();
}
static void setMinimizedGeometry(HWND hwnd, const QRect &r)
{
WINDOWPLACEMENT windowPlacement;
windowPlacement.length = sizeof(WINDOWPLACEMENT);
if (GetWindowPlacement(hwnd, &windowPlacement)) {
windowPlacement.showCmd = SW_SHOWMINIMIZED;
windowPlacement.rcNormalPosition = RECTfromQRect(r);
SetWindowPlacement(hwnd, &windowPlacement);
}
}
static void setRestoreMaximizedFlag(HWND hwnd, bool set = true)
{
// Let Windows know that we need to restore as maximized
WINDOWPLACEMENT windowPlacement;
windowPlacement.length = sizeof(WINDOWPLACEMENT);
if (GetWindowPlacement(hwnd, &windowPlacement)) {
if (set)
windowPlacement.flags |= WPF_RESTORETOMAXIMIZED;
else
windowPlacement.flags &= ~WPF_RESTORETOMAXIMIZED;
SetWindowPlacement(hwnd, &windowPlacement);
}
}
// partially from QWidgetPrivate::show_sys()
void QWindowsWindow::show_sys() const
{
int sm = SW_SHOWNORMAL;
bool fakedMaximize = false;
bool restoreMaximize = false;
const QWindow *w = window();
const Qt::WindowFlags flags = w->flags();
const Qt::WindowType type = w->type();
if (w->isTopLevel()) {
const Qt::WindowState state = w->windowState();
const Qt::WindowStates state = w->windowStates();
if (state & Qt::WindowMinimized) {
sm = SW_SHOWMINIMIZED;
if (!isVisible())
sm = SW_SHOWMINNOACTIVE;
if (state & Qt::WindowMaximized)
restoreMaximize = true;
} else {
updateTransientParent();
if (state & Qt::WindowMaximized) {
@ -1372,7 +1400,7 @@ void QWindowsWindow::show_sys() const
if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool || testShowWithoutActivating(w))
sm = SW_SHOWNOACTIVATE;
if (w->windowState() & Qt::WindowMaximized)
if (w->windowStates() & Qt::WindowMaximized)
setFlag(WithinMaximize); // QTBUG-8361
ShowWindow(m_data.hwnd, sm);
@ -1385,6 +1413,8 @@ void QWindowsWindow::show_sys() const
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER
| SWP_FRAMECHANGED);
}
if (restoreMaximize)
setRestoreMaximizedFlag(m_data.hwnd);
}
void QWindowsWindow::setParent(const QPlatformWindow *newParent)
@ -1458,7 +1488,8 @@ static QRect normalFrameGeometry(HWND hwnd)
QRect QWindowsWindow::normalGeometry() const
{
// Check for fake 'fullscreen' mode.
const bool fakeFullScreen = m_savedFrameGeometry.isValid() && window()->windowState() == Qt::WindowFullScreen;
const bool fakeFullScreen =
m_savedFrameGeometry.isValid() && (window()->windowStates() & Qt::WindowFullScreen);
const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd);
const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : frameMargins();
return frame.isValid() ? frame.marginsRemoved(margins) : frame;
@ -1473,13 +1504,15 @@ void QWindowsWindow::setGeometry(const QRect &rectIn)
const QMargins margins = frameMargins();
rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
}
if (m_windowState == Qt::WindowMinimized)
if (m_windowState & Qt::WindowMinimized)
m_data.geometry = rect; // Otherwise set by handleGeometryChange() triggered by event.
if (m_data.hwnd) {
// A ResizeEvent with resulting geometry will be sent. If we cannot
// achieve that size (for example, window title minimal constraint),
// notify and warn.
setFlag(WithinSetGeometry);
setGeometry_sys(rect);
clearFlag(WithinSetGeometry);
if (m_data.geometry != rect) {
qWarning("%s: Unable to set geometry %dx%d+%d+%d on %s/'%s'."
" Resulting geometry: %dx%d+%d+%d "
@ -1516,18 +1549,21 @@ void QWindowsWindow::handleResized(int wParam)
case SIZE_MAXSHOW:
return;
case SIZE_MINIMIZED: // QTBUG-53577, prevent state change events during programmatic state change
if (!testFlag(WithinSetStyle))
handleWindowStateChange(Qt::WindowMinimized);
if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry))
handleWindowStateChange(m_windowState | Qt::WindowMinimized);
return;
case SIZE_MAXIMIZED:
if (!testFlag(WithinSetStyle))
handleWindowStateChange(Qt::WindowMaximized);
if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry))
handleWindowStateChange(Qt::WindowMaximized | (isFullScreen_sys() ? Qt::WindowFullScreen
: Qt::WindowNoState));
handleGeometryChange();
break;
case SIZE_RESTORED:
if (!testFlag(WithinSetStyle)) {
if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry)) {
if (isFullScreen_sys())
handleWindowStateChange(Qt::WindowFullScreen);
handleWindowStateChange(
Qt::WindowFullScreen
| (testFlag(MaximizeToFullScreen) ? Qt::WindowMaximized : Qt::WindowNoState));
else if (m_windowState != Qt::WindowNoState && !testFlag(MaximizeToFullScreen))
handleWindowStateChange(Qt::WindowNoState);
}
@ -1714,20 +1750,16 @@ QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
return result;
}
void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
{
qCDebug(lcQpaWindows) << __FUNCTION__ << this << window()
<< "\n from " << m_windowState << " to " << state;
m_windowState = state;
QWindowSystemInterface::handleWindowStateChanged(window(), state);
switch (state) {
case Qt::WindowMinimized:
if (state & Qt::WindowMinimized) {
handleHidden();
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); // Tell QQuickWindow to stop rendering now.
break;
case Qt::WindowMaximized:
case Qt::WindowFullScreen:
case Qt::WindowNoState: {
} else {
// QTBUG-17548: We send expose events when receiving WM_Paint, but for
// layered windows and transient children, we won't receive any WM_Paint.
QWindow *w = window();
@ -1748,13 +1780,9 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
if (exposeEventsSent && !QWindowsContext::instance()->asyncExpose())
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
}
break;
default:
break;
}
}
void QWindowsWindow::setWindowState(Qt::WindowState state)
void QWindowsWindow::setWindowState(Qt::WindowStates state)
{
if (m_data.hwnd) {
setWindowState_sys(state);
@ -1783,18 +1811,19 @@ bool QWindowsWindow::isFullScreen_sys() const
to ShowWindow.
*/
void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
{
const Qt::WindowState oldState = m_windowState;
const Qt::WindowStates oldState = m_windowState;
if (oldState == newState)
return;
qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << this << window()
<< " from " << oldState << " to " << newState;
const bool visible = isVisible();
auto stateChange = oldState ^ newState;
if ((oldState == Qt::WindowFullScreen) != (newState == Qt::WindowFullScreen)) {
if (newState == Qt::WindowFullScreen) {
if (stateChange & Qt::WindowFullScreen) {
if (newState & Qt::WindowFullScreen) {
#ifndef Q_FLATTEN_EXPOSE
UINT newStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
#else
@ -1805,7 +1834,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
// Window state but emulated by changing geometry and style.
if (!m_savedStyle) {
m_savedStyle = style();
if (oldState == Qt::WindowMinimized || oldState == Qt::WindowMaximized) {
if ((oldState & Qt::WindowMinimized) || (oldState & Qt::WindowMaximized)) {
const QRect nf = normalFrameGeometry(m_data.hwnd);
if (nf.isValid())
m_savedFrameGeometry = nf;
@ -1813,6 +1842,8 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
m_savedFrameGeometry = frameGeometry_sys();
}
}
if (newState & Qt::WindowMaximized)
setFlag(MaximizeToFullScreen);
if (m_savedStyle & WS_SYSMENU)
newStyle |= WS_SYSMENU;
if (visible)
@ -1826,15 +1857,23 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
if (!screen)
screen = QGuiApplication::primaryScreen();
const QRect r = screen ? QHighDpi::toNativePixels(screen->geometry(), window()) : m_savedFrameGeometry;
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent);
SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
if (!wasSync)
clearFlag(SynchronousGeometryChangeEvent);
QWindowSystemInterface::handleGeometryChange(window(), r);
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
} else if (newState != Qt::WindowMinimized) {
if (newState & Qt::WindowMinimized) {
setMinimizedGeometry(m_data.hwnd, r);
if (stateChange & Qt::WindowMaximized)
setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
} else {
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent);
SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
if (!wasSync)
clearFlag(SynchronousGeometryChangeEvent);
clearFlag(MaximizeToFullScreen);
QWindowSystemInterface::handleGeometryChange(window(), r);
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
}
} else {
// Restore saved state.
unsigned newStyle = m_savedStyle ? m_savedStyle : style();
if (visible)
@ -1848,43 +1887,58 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
if (!screen->geometry().intersects(m_savedFrameGeometry))
m_savedFrameGeometry.moveTo(screen->geometry().topLeft());
UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE;
if (!m_savedFrameGeometry.isValid())
swpf |= SWP_NOSIZE | SWP_NOMOVE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent);
// After maximized/fullscreen; the window can be in a maximized state. Clear
// it before applying the normal geometry.
if (windowVisibility_sys(m_data.hwnd) == QWindow::Maximized)
ShowWindow(m_data.hwnd, SW_SHOWNOACTIVATE);
SetWindowPos(m_data.hwnd, 0, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(),
m_savedFrameGeometry.width(), m_savedFrameGeometry.height(), swpf);
if (!wasSync)
clearFlag(SynchronousGeometryChangeEvent);
// preserve maximized state
if (visible) {
setFlag(WithinMaximize);
ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA);
clearFlag(WithinMaximize);
if (newState & Qt::WindowMinimized) {
setMinimizedGeometry(m_data.hwnd, m_savedFrameGeometry);
if (stateChange & Qt::WindowMaximized)
setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
} else {
UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE;
if (!m_savedFrameGeometry.isValid())
swpf |= SWP_NOSIZE | SWP_NOMOVE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent);
// After maximized/fullscreen; the window can be in a maximized state. Clear
// it before applying the normal geometry.
if (windowVisibility_sys(m_data.hwnd) == QWindow::Maximized)
ShowWindow(m_data.hwnd, SW_SHOWNOACTIVATE);
SetWindowPos(m_data.hwnd, 0, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(),
m_savedFrameGeometry.width(), m_savedFrameGeometry.height(), swpf);
if (!wasSync)
clearFlag(SynchronousGeometryChangeEvent);
// preserve maximized state
if (visible) {
setFlag(WithinMaximize);
ShowWindow(m_data.hwnd,
(newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA);
clearFlag(WithinMaximize);
}
}
m_savedStyle = 0;
m_savedFrameGeometry = QRect();
}
} else if ((oldState == Qt::WindowMaximized) != (newState == Qt::WindowMaximized)) {
if (visible && !(newState == Qt::WindowMinimized)) {
} else if ((oldState & Qt::WindowMaximized) != (newState & Qt::WindowMaximized)) {
if (visible && !(newState & Qt::WindowMinimized)) {
setFlag(WithinMaximize);
if (newState == Qt::WindowFullScreen)
if (newState & Qt::WindowFullScreen)
setFlag(MaximizeToFullScreen);
ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
ShowWindow(m_data.hwnd,
(newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
clearFlag(WithinMaximize);
clearFlag(MaximizeToFullScreen);
} else if (visible && (oldState & newState & Qt::WindowMinimized)) {
// change of the maximized state while keeping minimized
setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
}
}
if ((oldState == Qt::WindowMinimized) != (newState == Qt::WindowMinimized)) {
if (visible)
ShowWindow(m_data.hwnd, (newState == Qt::WindowMinimized) ? SW_MINIMIZE :
(newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNORMAL);
if (stateChange & Qt::WindowMinimized) {
if (visible) {
ShowWindow(m_data.hwnd,
(newState & Qt::WindowMinimized) ? SW_MINIMIZE :
(newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNORMAL);
if ((newState & Qt::WindowMinimized) && (oldState ^ newState & Qt::WindowMaximized))
setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
}
}
qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << this << window() << newState;
}
@ -2145,7 +2199,7 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
hint.applyToMinMaxInfo(m_data.hwnd, mmi);
}
if ((testFlag(WithinMaximize) || (window()->windowState() == Qt::WindowMinimized))
if ((testFlag(WithinMaximize) || (window()->windowStates() & Qt::WindowMinimized))
&& (m_data.flags & Qt::FramelessWindowHint)) {
// This block fixes QTBUG-8361: Frameless windows shouldn't cover the
// taskbar when maximized
@ -2175,7 +2229,7 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re
// QTBUG-32663, suppress resize cursor for fixed size windows.
const QWindow *w = window();
if (!w->isTopLevel() // Task 105852, minimized windows need to respond to user input.
|| (m_windowState != Qt::WindowNoState && m_windowState != Qt::WindowActive)
|| !(m_windowState & ~Qt::WindowActive)
|| (m_data.flags & Qt::FramelessWindowHint)) {
return false;
}

View File

@ -188,6 +188,7 @@ public:
{
AutoMouseCapture = 0x1, //! Automatic mouse capture on button press.
WithinSetParent = 0x2,
WithinSetGeometry = 0x8,
OpenGLSurface = 0x10,
OpenGL_ES2 = 0x20,
OpenGLDoubleBuffered = 0x40,
@ -230,7 +231,7 @@ public:
QPoint mapFromGlobal(const QPoint &pos) const override;
void setWindowFlags(Qt::WindowFlags flags) override;
void setWindowState(Qt::WindowState state) override;
void setWindowState(Qt::WindowStates state) override;
void setParent(const QPlatformWindow *window) override;
@ -323,7 +324,7 @@ private:
inline void show_sys() const;
inline QWindowsWindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const;
inline bool isFullScreen_sys() const;
inline void setWindowState_sys(Qt::WindowState newState);
inline void setWindowState_sys(Qt::WindowStates newState);
inline void setParent_sys(const QPlatformWindow *parent);
inline void updateTransientParent() const;
void destroyWindow();
@ -331,14 +332,14 @@ private:
void setDropSiteEnabled(bool enabled);
void updateDropSite(bool topLevel);
void handleGeometryChange();
void handleWindowStateChange(Qt::WindowState state);
void handleWindowStateChange(Qt::WindowStates state);
inline void destroyIcon();
void fireExpose(const QRegion &region, bool force=false);
mutable QWindowsWindowData m_data;
mutable unsigned m_flags = WithinCreate;
HDC m_hdc = 0;
Qt::WindowState m_windowState = Qt::WindowNoState;
Qt::WindowStates m_windowState = Qt::WindowNoState;
qreal m_opacity = 1;
#ifndef QT_NO_CURSOR
CursorHandlePtr m_cursor;

View File

@ -91,7 +91,7 @@ public:
QSurfaceFormat surfaceFormat;
QString windowTitle;
Qt::WindowState state;
Qt::WindowStates state;
EGLDisplay display;
EGLSurface surface;
@ -158,7 +158,7 @@ QWinRTWindow::QWinRTWindow(QWindow *window)
Q_ASSERT_SUCCEEDED(hr);
setWindowFlags(window->flags());
setWindowState(window->windowState());
setWindowState(window->windowStates());
setWindowTitle(window->title());
setGeometry(window->geometry());
@ -323,7 +323,7 @@ qreal QWinRTWindow::devicePixelRatio() const
return screen()->devicePixelRatio();
}
void QWinRTWindow::setWindowState(Qt::WindowState state)
void QWinRTWindow::setWindowState(Qt::WindowStates state)
{
Q_D(QWinRTWindow);
qCDebug(lcQpaWindows) << __FUNCTION__ << this << state;
@ -331,7 +331,13 @@ void QWinRTWindow::setWindowState(Qt::WindowState state)
if (d->state == state)
return;
if (state == Qt::WindowFullScreen) {
if (state & Qt::WindowMinimized) {
setUIElementVisibility(d->uiElement.Get(), false);
d->state = state;
return;
}
if (state & Qt::WindowFullScreen) {
HRESULT hr;
boolean success;
hr = QEventDispatcherWinRT::runOnXamlThread([&hr, &success]() {
@ -356,7 +362,7 @@ void QWinRTWindow::setWindowState(Qt::WindowState state)
return;
}
if (d->state == Qt::WindowFullScreen) {
if (d->state & Qt::WindowFullScreen) {
HRESULT hr;
hr = QEventDispatcherWinRT::runOnXamlThread([&hr]() {
ComPtr<IApplicationViewStatics2> applicationViewStatics;
@ -378,10 +384,7 @@ void QWinRTWindow::setWindowState(Qt::WindowState state)
}
}
if (state == Qt::WindowMinimized)
setUIElementVisibility(d->uiElement.Get(), false);
if (d->state == Qt::WindowMinimized || state == Qt::WindowNoState || state == Qt::WindowActive)
if (d->state & Qt::WindowMinimized || state == Qt::WindowNoState || state == Qt::WindowActive)
setUIElementVisibility(d->uiElement.Get(), true);
d->state = state;

View File

@ -68,7 +68,7 @@ public:
WId winId() const override;
qreal devicePixelRatio() const override;
void setWindowState(Qt::WindowState state) override;
void setWindowState(Qt::WindowStates state) override;
bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE;
bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE;

View File

@ -552,7 +552,7 @@ void QXcbWindow::create()
connection()->xi2Select(m_window);
#endif
setWindowState(window()->windowState());
setWindowState(window()->windowStates());
setWindowFlags(window()->flags());
setWindowTitle(window()->title());
@ -762,7 +762,7 @@ void QXcbWindow::show()
xcb_wm_hints_t hints;
xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, NULL);
if (window()->windowState() & Qt::WindowMinimized)
if (window()->windowStates() & Qt::WindowMinimized)
xcb_wm_hints_set_iconic(&hints);
else
xcb_wm_hints_set_normal(&hints);
@ -1215,66 +1215,43 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
(const char *)&event);
}
void QXcbWindow::setWindowState(Qt::WindowState state)
void QXcbWindow::setWindowState(Qt::WindowStates state)
{
if (state == m_windowState)
return;
// unset old state
switch (m_windowState) {
case Qt::WindowMinimized:
if ((m_windowState & Qt::WindowMinimized) && !(state & Qt::WindowMinimized)) {
xcb_map_window(xcb_connection(), m_window);
break;
case Qt::WindowMaximized:
changeNetWmState(false,
atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
break;
case Qt::WindowFullScreen:
changeNetWmState(false, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
break;
default:
break;
} else if (!(m_windowState & Qt::WindowMinimized) && (state & Qt::WindowMinimized)) {
xcb_client_message_event_t event;
event.response_type = XCB_CLIENT_MESSAGE;
event.format = 32;
event.sequence = 0;
event.window = m_window;
event.type = atom(QXcbAtom::WM_CHANGE_STATE);
event.data.data32[0] = XCB_WM_STATE_ICONIC;
event.data.data32[1] = 0;
event.data.data32[2] = 0;
event.data.data32[3] = 0;
event.data.data32[4] = 0;
xcb_send_event(xcb_connection(), 0, xcbScreen()->root(),
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
(const char *)&event);
m_minimized = true;
}
// set new state
switch (state) {
case Qt::WindowMinimized:
{
xcb_client_message_event_t event;
event.response_type = XCB_CLIENT_MESSAGE;
event.format = 32;
event.sequence = 0;
event.window = m_window;
event.type = atom(QXcbAtom::WM_CHANGE_STATE);
event.data.data32[0] = XCB_WM_STATE_ICONIC;
event.data.data32[1] = 0;
event.data.data32[2] = 0;
event.data.data32[3] = 0;
event.data.data32[4] = 0;
xcb_send_event(xcb_connection(), 0, xcbScreen()->root(),
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
(const char *)&event);
}
break;
case Qt::WindowMaximized:
changeNetWmState(true,
atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
if ((m_windowState ^ state) & Qt::WindowMaximized) {
changeNetWmState(state & Qt::WindowMaximized, atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
break;
case Qt::WindowFullScreen:
changeNetWmState(true, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
break;
case Qt::WindowNoState:
break;
default:
break;
}
if ((m_windowState ^ state) & Qt::WindowFullScreen) {
changeNetWmState(state & Qt::WindowFullScreen, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
}
connection()->sync();
m_windowState = state;
}
@ -1346,10 +1323,10 @@ void QXcbWindow::updateNetWmStateBeforeMap()
states |= NetWmStateBelow;
}
if (window()->windowState() & Qt::WindowFullScreen)
if (window()->windowStates() & Qt::WindowFullScreen)
states |= NetWmStateFullScreen;
if (window()->windowState() & Qt::WindowMaximized) {
if (window()->windowStates() & Qt::WindowMaximized) {
states |= NetWmStateMaximizedHorz;
states |= NetWmStateMaximizedVert;
}
@ -2486,39 +2463,33 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
if (propertyDeleted)
return;
Qt::WindowState newState = Qt::WindowNoState;
Qt::WindowStates newState = Qt::WindowNoState;
if (event->atom == atom(QXcbAtom::WM_STATE)) { // WM_STATE: Quick check for 'Minimize'.
auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
0, m_window, atom(QXcbAtom::WM_STATE),
XCB_ATOM_ANY, 0, 1024);
if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) {
const quint32 *data = (const quint32 *)xcb_get_property_value(reply.get());
if (reply->length != 0) {
if (data[0] == XCB_WM_STATE_ICONIC
|| (data[0] == XCB_WM_STATE_WITHDRAWN
&& m_lastWindowStateEvent == Qt::WindowMinimized)) {
newState = Qt::WindowMinimized;
}
}
if (reply->length != 0)
m_minimized = (data[0] == XCB_WM_STATE_ICONIC
|| (data[0] == XCB_WM_STATE_WITHDRAWN && m_minimized));
}
} else { // _NET_WM_STATE can't change minimized state
if (m_lastWindowStateEvent == Qt::WindowMinimized)
newState = Qt::WindowMinimized;
}
if (m_minimized)
newState = Qt::WindowMinimized;
if (newState != Qt::WindowMinimized) { // Something else changed, get _NET_WM_STATE.
const NetWmStates states = netWmStates();
if (states & NetWmStateFullScreen)
newState = Qt::WindowFullScreen;
else if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert))
newState = Qt::WindowMaximized;
}
const NetWmStates states = netWmStates();
if (states & NetWmStateFullScreen)
newState |= Qt::WindowFullScreen;
if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert))
newState |= Qt::WindowMaximized;
// Send Window state, compress events in case other flags (modality, etc) are changed.
if (m_lastWindowStateEvent != newState) {
QWindowSystemInterface::handleWindowStateChanged(window(), newState);
m_lastWindowStateEvent = newState;
m_windowState = newState;
if (m_windowState == Qt::WindowMinimized && connection()->mouseGrabber() == this)
if ((m_windowState & Qt::WindowMinimized) && connection()->mouseGrabber() == this)
connection()->setMouseGrabber(Q_NULLPTR);
}
return;

View File

@ -82,7 +82,7 @@ public:
void setVisible(bool visible) override;
void setWindowFlags(Qt::WindowFlags flags) override;
void setWindowState(Qt::WindowState state) override;
void setWindowState(Qt::WindowStates state) override;
WId winId() const override;
void setParent(const QPlatformWindow *window) override;
@ -243,7 +243,7 @@ protected:
xcb_sync_int64_t m_syncValue;
xcb_sync_counter_t m_syncCounter = 0;
Qt::WindowState m_windowState = Qt::WindowNoState;
Qt::WindowStates m_windowState = Qt::WindowNoState;
xcb_gravity_t m_gravity = XCB_GRAVITY_STATIC;
@ -253,6 +253,7 @@ protected:
bool m_deferredActivation = false;
bool m_embedded = false;
bool m_alertState = false;
bool m_minimized = false;
xcb_window_t m_netWmUserTimeWindow = XCB_NONE;
QSurfaceFormat m_format;
@ -264,7 +265,8 @@ protected:
QSize m_oldWindowSize;
xcb_visualid_t m_visualId = 0;
int m_lastWindowStateEvent = -1;
// Last sent state. Initialized to an invalid state, on purpose.
Qt::WindowStates m_lastWindowStateEvent = Qt::WindowActive;
enum SyncState {
NoSyncNeeded,

View File

@ -3037,17 +3037,6 @@ void QWidget::overrideWindowState(Qt::WindowStates newstate)
QApplication::sendEvent(this, &e);
}
Qt::WindowState effectiveState(Qt::WindowStates state)
{
if (state & Qt::WindowMinimized)
return Qt::WindowMinimized;
else if (state & Qt::WindowFullScreen)
return Qt::WindowFullScreen;
else if (state & Qt::WindowMaximized)
return Qt::WindowMaximized;
return Qt::WindowNoState;
}
/*!
\fn void QWidget::setWindowState(Qt::WindowStates windowState)
@ -3089,19 +3078,17 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
data->window_state = newstate;
data->in_set_window_state = 1;
Qt::WindowState newEffectiveState = effectiveState(newstate);
Qt::WindowState oldEffectiveState = effectiveState(oldstate);
if (isWindow() && newEffectiveState != oldEffectiveState) {
if (isWindow()) {
// Ensure the initial size is valid, since we store it as normalGeometry below.
if (!testAttribute(Qt::WA_Resized) && !isVisible())
adjustSize();
d->createTLExtra();
if (oldEffectiveState == Qt::WindowNoState)
if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
d->topData()->normalGeometry = geometry();
Q_ASSERT(windowHandle());
windowHandle()->setWindowState(newEffectiveState);
windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
}
data->in_set_window_state = 0;

View File

@ -726,8 +726,6 @@ void QWidgetWindow::repaintWindow()
QWidgetBackingStore::UpdateNow, QWidgetBackingStore::BufferInvalid);
}
Qt::WindowState effectiveState(Qt::WindowStates state);
// Store normal geometry used for saving application settings.
void QWidgetWindow::updateNormalGeometry()
{
@ -738,7 +736,7 @@ void QWidgetWindow::updateNormalGeometry()
QRect normalGeometry;
if (const QPlatformWindow *pw = handle())
normalGeometry = QHighDpi::fromNativePixels(pw->normalGeometry(), this);
if (!normalGeometry.isValid() && effectiveState(m_widget->windowState()) == Qt::WindowNoState)
if (!normalGeometry.isValid() && !(m_widget->windowState() & ~Qt::WindowActive))
normalGeometry = m_widget->geometry();
if (normalGeometry.isValid())
tle->normalGeometry = normalGeometry;
@ -930,30 +928,18 @@ void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event
// QWindow does currently not know 'active'.
Qt::WindowStates eventState = event->oldState();
Qt::WindowStates widgetState = m_widget->windowState();
Qt::WindowStates windowState = windowStates();
if (widgetState & Qt::WindowActive)
eventState |= Qt::WindowActive;
// Determine the new widget state, remember maximized/full screen
// during minimized.
switch (windowState()) {
case Qt::WindowNoState:
widgetState &= ~(Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen);
break;
case Qt::WindowMinimized:
if (windowState & Qt::WindowMinimized) {
widgetState |= Qt::WindowMinimized;
break;
case Qt::WindowMaximized:
updateNormalGeometry();
widgetState |= Qt::WindowMaximized;
widgetState &= ~(Qt::WindowMinimized | Qt::WindowFullScreen);
break;
case Qt::WindowFullScreen:
updateNormalGeometry();
widgetState |= Qt::WindowFullScreen;
widgetState &= ~(Qt::WindowMinimized);
break;
case Qt::WindowActive: // Not handled by QWindow
break;
} else {
widgetState = windowState | (widgetState & Qt::WindowActive);
if (windowState) // Maximized or FullScreen
updateNormalGeometry();
}
// Sent event if the state changed (that is, it is not triggered by

View File

@ -1781,9 +1781,11 @@ void tst_QWidget::windowState()
QCOMPARE(widget1.pos(), pos);
QCOMPARE(widget1.size(), size);
#define VERIFY_STATE(s) QCOMPARE(int(widget1.windowState() & stateMask), int(s))
#define VERIFY_STATE(s) \
QCOMPARE(int(widget1.windowState() & stateMask), int(s)); \
QCOMPARE(int(widget1.windowHandle()->windowStates() & stateMask), int(s))
const int stateMask = Qt::WindowMaximized|Qt::WindowMinimized|Qt::WindowFullScreen;
const auto stateMask = Qt::WindowMaximized | Qt::WindowMinimized | Qt::WindowFullScreen;
widget1.setWindowState(Qt::WindowMaximized);
QTest::qWait(100);

View File

@ -99,6 +99,9 @@ private slots:
void tst_eventfilter_on_toplevel();
void QTBUG_50561_QCocoaBackingStore_paintDevice_crash();
void setWindowState_data();
void setWindowState();
};
void tst_QWidget_window::initTestCase()
@ -861,5 +864,56 @@ void tst_QWidget_window::QTBUG_50561_QCocoaBackingStore_paintDevice_crash()
w.close();
}
void tst_QWidget_window::setWindowState_data()
{
QString platformName = QGuiApplication::platformName().toLower();
QTest::addColumn<Qt::WindowStates>("state");
QTest::newRow("0") << Qt::WindowStates();
QTest::newRow("Qt::WindowMaximized") << Qt::WindowStates(Qt::WindowMaximized);
QTest::newRow("Qt::WindowMinimized") << Qt::WindowStates(Qt::WindowMinimized);
QTest::newRow("Qt::WindowFullScreen") << Qt::WindowStates(Qt::WindowFullScreen);
if (platformName != "xcb" && platformName != "windows" && !platformName.startsWith("wayland")
&& platformName != "offscreen")
return; // Combination of states is not preserved on all platforms.
if (platformName == "xcb" && qgetenv("XDG_CURRENT_DESKTOP") != "KDE"
&& qgetenv("XDG_CURRENT_DESKTOP") != "Unity")
return; // Not all window managers support state combinations.
QTest::newRow("Qt::WindowMaximized|Qt::WindowMinimized")
<< (Qt::WindowMaximized | Qt::WindowMinimized);
QTest::newRow("Qt::WindowFullScreen|Qt::WindowMinimized")
<< (Qt::WindowFullScreen | Qt::WindowMinimized);
QTest::newRow("Qt::WindowMaximized|Qt::WindowFullScreen")
<< (Qt::WindowMaximized | Qt::WindowFullScreen);
QTest::newRow("Qt::WindowMaximized|Qt::WindowFullScreen|Qt::WindowMinimized")
<< (Qt::WindowMaximized | Qt::WindowFullScreen | Qt::WindowMinimized);
}
void tst_QWidget_window::setWindowState()
{
QFETCH(Qt::WindowStates, state);
// This tests make sure that the states are preserved when the window is shown.
QWidget w;
w.setWindowState(state);
QCOMPARE(w.windowState(), state);
w.show();
QCOMPARE(w.windowState(), state);
QCOMPARE(w.windowHandle()->windowStates(), state);
QTest::qWaitForWindowExposed(&w);
QTRY_COMPARE(w.windowState(), state);
QCOMPARE(w.windowHandle()->windowStates(), state);
// Minimizing keeps other states
w.showMinimized();
QCOMPARE(w.windowState(), state | Qt::WindowMinimized);
QTest::qWait(100);
QCOMPARE(w.windowState(), state | Qt::WindowMinimized);
QCOMPARE(w.windowHandle()->windowStates(), state | Qt::WindowMinimized);
}
QTEST_MAIN(tst_QWidget_window)
#include "tst_qwidget_window.moc"