From 02be8943dbd0e748a7cc8fc87c06bcbe9360e9f0 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 10 Jan 2015 00:04:11 +0100 Subject: [PATCH] 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 --- objects/client.c | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/objects/client.c b/objects/client.c index 347cee460..ddade972a 100644 --- a/objects/client.c +++ b/objects/client.c @@ -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);