Unmap minimized clients

Because ICCCM pretty much mandates that minimized (aka "iconic") clients are
unmapped. In detail: To go back to normal state, the client should map its
window and for this to work, the window needs to be unmapped.

Thanks to Oleg Shparber for reporting some issue he had with a self-written Qt
program and for providing a simple and short test case.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2015-01-10 00:04:11 +01:00
parent a44b3a2daf
commit 02be8943db
1 changed files with 32 additions and 16 deletions

View File

@ -550,22 +550,7 @@ HANDLE_GEOM(height)
/* Push client in stack */
stack_client_push(c);
/* Always stay in NORMAL_STATE. Even though iconified seems more
* appropriate sometimes. The only possible loss is that clients not using
* visibility events may continue to process data (when banned).
* Without any exposes or other events the cost should be fairly limited though.
*
* Some clients may expect the window to be unmapped when STATE_ICONIFIED.
* Two conflicting parts of the ICCCM v2.0 (section 4.1.4):
*
* "Normal -> Iconic - The client should send a ClientMessage event as described later in this section."
* (note no explicit mention of unmapping, while Normal->Widthdrawn does mention that)
*
* "Once a client's window has left the Withdrawn state, the window will be mapped
* if it is in the Normal state and the window will be unmapped if it is in the Iconic state."
*
* At this stage it's just safer to keep it in normal state and avoid confusion.
*/
/* Put the window in normal state. */
xwindow_set_state(c->window, XCB_ICCCM_WM_STATE_NORMAL);
if(!startup)
@ -875,9 +860,40 @@ client_set_minimized(lua_State *L, int cidx, bool s)
c->minimized = s;
banning_need_update();
if(s)
{
/* ICCCM: To transition from ICONIC to NORMAL state, the client
* should just map the window. Thus, iconic clients need to be
* unmapped, else the MapWindow request doesn't have any effect.
*/
xwindow_set_state(c->window, XCB_ICCCM_WM_STATE_ICONIC);
uint32_t no_event[] = { 0 };
const uint32_t select_input_val[] = { CLIENT_SELECT_INPUT_EVENT_MASK };
xcb_grab_server(globalconf.connection);
xcb_change_window_attributes(globalconf.connection,
globalconf.screen->root,
XCB_CW_EVENT_MASK,
no_event);
xcb_change_window_attributes(globalconf.connection,
c->window,
XCB_CW_EVENT_MASK,
no_event);
xcb_unmap_window(globalconf.connection, c->window);
xcb_change_window_attributes(globalconf.connection,
globalconf.screen->root,
XCB_CW_EVENT_MASK,
ROOT_WINDOW_EVENT_MASK);
xcb_change_window_attributes(globalconf.connection,
c->window,
XCB_CW_EVENT_MASK,
select_input_val);
xcb_ungrab_server(globalconf.connection);
}
else
{
xwindow_set_state(c->window, XCB_ICCCM_WM_STATE_NORMAL);
xcb_map_window(globalconf.connection, c->window);
}
if(strut_has_value(&c->strut))
screen_emit_signal(globalconf.L, c->screen, "property::workarea", 0);
luaA_object_emit_signal(L, cidx, "property::minimized", 0);