xcb: Fix logic for minimized state

When _NET_WM_STATE_HIDDEN is not contains in the _NET_WM_STATE
window property, the window should not be considered to be minimized

According to
https://specifications.freedesktop.org/wm-spec/1.3/ar01s05.html
_NET_WM_STATE_HIDDEN should be set by the Window Manager to indicate
that a window would not be visible on the screen if its desktop/viewport
were active and its coordinates were within the screen bounds. The
canonical example is that minimized windows should be in the
_NET_WM_STATE_HIDDEN state. Pagers and similar applications should use
_NET_WM_STATE_HIDDEN instead of WM_STATE to decide whether to display a
window in miniature representations of the windows on a desktop.

For mutter/GNOME Shell, without _NET_WM_STATE_HIDDEN, window manager
will not reply XCB_ICCCM_WM_STATE_ICONIC settings in WM_CHANGE_STATE
client message.

Task-number: QTBUG-76147
Task-number: QTBUG-76354
Task-number: QTBUG-68864
Done-With: Liang Qi <liang.qi@qt.io>
Change-Id: Ic9d26d963979b7f0ef4d1cf322c54ef8c40fa004
Reviewed-by: Uli Schlachter <psychon@znc.in>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
JiDe Zhang 2019-06-01 16:56:49 +08:00 committed by Liang Qi
parent 3f7d087d33
commit 4f370d36ec
5 changed files with 19 additions and 7 deletions

View File

@ -122,6 +122,7 @@ static const char *xcb_atomnames = {
"_NET_WM_STATE_MODAL\0" "_NET_WM_STATE_MODAL\0"
"_NET_WM_STATE_STAYS_ON_TOP\0" "_NET_WM_STATE_STAYS_ON_TOP\0"
"_NET_WM_STATE_DEMANDS_ATTENTION\0" "_NET_WM_STATE_DEMANDS_ATTENTION\0"
"_NET_WM_STATE_HIDDEN\0"
"_NET_WM_USER_TIME\0" "_NET_WM_USER_TIME\0"
"_NET_WM_USER_TIME_WINDOW\0" "_NET_WM_USER_TIME_WINDOW\0"

View File

@ -123,6 +123,7 @@ public:
_NET_WM_STATE_MODAL, _NET_WM_STATE_MODAL,
_NET_WM_STATE_STAYS_ON_TOP, _NET_WM_STATE_STAYS_ON_TOP,
_NET_WM_STATE_DEMANDS_ATTENTION, _NET_WM_STATE_DEMANDS_ATTENTION,
_NET_WM_STATE_HIDDEN,
_NET_WM_USER_TIME, _NET_WM_USER_TIME,
_NET_WM_USER_TIME_WINDOW, _NET_WM_USER_TIME_WINDOW,

View File

@ -907,6 +907,8 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates()
result |= NetWmStateStaysOnTop; result |= NetWmStateStaysOnTop;
if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION))) if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)))
result |= NetWmStateDemandsAttention; result |= NetWmStateDemandsAttention;
if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_HIDDEN)))
result |= NetWmStateHidden;
} else { } else {
qCDebug(lcQpaXcb, "getting net wm state (%x), empty\n", m_window); qCDebug(lcQpaXcb, "getting net wm state (%x), empty\n", m_window);
} }
@ -1078,6 +1080,9 @@ void QXcbWindow::setNetWmStateOnUnmappedWindow()
states |= NetWmStateBelow; states |= NetWmStateBelow;
} }
if (window()->windowStates() & Qt::WindowMinimized)
states |= NetWmStateHidden;
if (window()->windowStates() & Qt::WindowFullScreen) if (window()->windowStates() & Qt::WindowFullScreen)
states |= NetWmStateFullScreen; states |= NetWmStateFullScreen;
@ -1111,6 +1116,8 @@ void QXcbWindow::setNetWmStateOnUnmappedWindow()
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE)); atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW))) if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW)))
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW)); atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW));
if (states & NetWmStateHidden && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_HIDDEN)))
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_HIDDEN));
if (states & NetWmStateFullScreen && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN))) if (states & NetWmStateFullScreen && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)))
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
if (states & NetWmStateMaximizedHorz && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ))) if (states & NetWmStateMaximizedHorz && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)))
@ -2219,10 +2226,16 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
|| (data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN && m_minimized)); || (data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN && m_minimized));
} }
} }
if (m_minimized)
newState = Qt::WindowMinimized;
const NetWmStates states = netWmStates(); const NetWmStates states = netWmStates();
// _NET_WM_STATE_HIDDEN should be set by the Window Manager to indicate that a window would
// not be visible on the screen if its desktop/viewport were active and its coordinates were
// within the screen bounds. The canonical example is that minimized windows should be in
// the _NET_WM_STATE_HIDDEN state.
if (m_minimized && (!connection()->wmSupport()->isSupportedByWM(NetWmStateHidden)
|| states.testFlag(NetWmStateHidden)))
newState = Qt::WindowMinimized;
if (states & NetWmStateFullScreen) if (states & NetWmStateFullScreen)
newState |= Qt::WindowFullScreen; newState |= Qt::WindowFullScreen;
if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert)) if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert))

View File

@ -68,7 +68,8 @@ public:
NetWmStateMaximizedVert = 0x10, NetWmStateMaximizedVert = 0x10,
NetWmStateModal = 0x20, NetWmStateModal = 0x20,
NetWmStateStaysOnTop = 0x40, NetWmStateStaysOnTop = 0x40,
NetWmStateDemandsAttention = 0x80 NetWmStateDemandsAttention = 0x80,
NetWmStateHidden = 0x100
}; };
Q_DECLARE_FLAGS(NetWmStates, NetWmState) Q_DECLARE_FLAGS(NetWmStates, NetWmState)

View File

@ -2,7 +2,3 @@
# QTBUG-66345 # QTBUG-66345
opensuse-42.3 opensuse-42.3
ubuntu-16.04 ubuntu-16.04
[setWindowState]
ubuntu-18.04
rhel-7.6