From b9636ceeec50587d43e33eb38ca9d1120adf2073 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 11 Aug 2009 12:16:10 +0200 Subject: [PATCH] Set WM_STATE_WITHDRAWN when unmapping, unmap windows when destroying (Thanks xeen) Seems like java apps need it. Also, you probably want to use XToolkit, when you have to work with java apps: export AWT_TOOLKIT=XToolkit --- include/client.h | 12 ++++++++++++ src/client.c | 25 +++++++++++++++++++++++++ src/commands.c | 4 ++-- src/floating.c | 4 ++-- src/handlers.c | 3 +++ src/manage.c | 7 +------ src/workspace.c | 8 ++++---- 7 files changed, 49 insertions(+), 14 deletions(-) diff --git a/include/client.h b/include/client.h index 5d87b2ee..81cb5c6e 100644 --- a/include/client.h +++ b/include/client.h @@ -85,4 +85,16 @@ bool client_is_floating(Client *client); */ void client_change_border(xcb_connection_t *conn, Client *client, char border_type); +/** + * Unmap the client, correctly setting any state which is needed. + * + */ +void client_unmap(xcb_connection_t *conn, Client *client); + +/** + * Map the client, correctly restoring any state needed. + * + */ +void client_map(xcb_connection_t *conn, Client *client); + #endif diff --git a/src/client.c b/src/client.c index 5ed5cf97..a4269805 100644 --- a/src/client.c +++ b/src/client.c @@ -289,3 +289,28 @@ void client_change_border(xcb_connection_t *conn, Client *client, char border_ty redecorate_window(conn, client); } + +/* + * Unmap the client, correctly setting any state which is needed. + * + */ +void client_unmap(xcb_connection_t *conn, Client *client) { + /* Set WM_STATE_WITHDRAWN, it seems like Java apps need it */ + long data[] = { XCB_WM_STATE_WITHDRAWN, XCB_NONE }; + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, client->child, atoms[WM_STATE], atoms[WM_STATE], 32, 2, data); + + xcb_unmap_window(conn, client->frame); +} + +/* + * Map the client, correctly restoring any state needed. + * + */ +void client_map(xcb_connection_t *conn, Client *client) { + /* Set WM_STATE_NORMAL because GTK applications don’t want to drag & drop if we don’t. + * Also, xprop(1) needs that to work. */ + long data[] = { XCB_WM_STATE_NORMAL, XCB_NONE }; + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, client->child, atoms[WM_STATE], atoms[WM_STATE], 32, 2, data); + + xcb_map_window(conn, client->frame); +} diff --git a/src/commands.c b/src/commands.c index f53e4335..6472d860 100644 --- a/src/commands.c +++ b/src/commands.c @@ -530,7 +530,7 @@ static void move_floating_window_to_workspace(xcb_connection_t *conn, Client *cl /* If we’re moving it to an invisible screen, we need to unmap it */ if (!workspace_is_visible(t_ws)) { LOG("This workspace is not visible, unmapping\n"); - xcb_unmap_window(conn, client->frame); + client_unmap(conn, client); } else { /* If this is not the case, we move the window to a workspace * which is on another screen, so we also need to adjust its @@ -613,7 +613,7 @@ static void move_current_window_to_workspace(xcb_connection_t *conn, int workspa /* If we’re moving it to an invisible screen, we need to unmap it */ if (!workspace_is_visible(to_container->workspace)) { LOG("This workspace is not visible, unmapping\n"); - xcb_unmap_window(conn, current_client->frame); + client_unmap(conn, current_client); } else { if (current_client->fullscreen) { LOG("Calling client_enter_fullscreen again\n"); diff --git a/src/floating.c b/src/floating.c index 70112b57..04d99f6c 100644 --- a/src/floating.c +++ b/src/floating.c @@ -415,8 +415,8 @@ void floating_toggle_hide(xcb_connection_t *conn, Workspace *workspace) { LOG("floating_hidden is now: %d\n", workspace->floating_hidden); TAILQ_FOREACH(client, &(workspace->floating_clients), floating_clients) { if (workspace->floating_hidden) - xcb_unmap_window(conn, client->frame); - else xcb_map_window(conn, client->frame); + client_unmap(conn, client); + else client_map(conn, client); } /* If we just unmapped all floating windows we should ensure that the focus diff --git a/src/handlers.c b/src/handlers.c index 280750ba..3c13b8c4 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -696,6 +696,9 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti LOG("child of 0x%08x.\n", client->frame); xcb_reparent_window(conn, client->child, root, 0, 0); + + client_unmap(conn, client); + xcb_destroy_window(conn, client->frame); xcb_flush(conn); table_remove(&by_parent, client->frame); diff --git a/src/manage.c b/src/manage.c index 14c058fd..a5a46237 100644 --- a/src/manage.c +++ b/src/manage.c @@ -205,11 +205,6 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, /* Yo dawg, I heard you like windows, so I create a window around your window… */ new->frame = create_window(conn, framerect, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_CURSOR_LEFT_PTR, false, mask, values); - /* Set WM_STATE_NORMAL because GTK applications don’t want to drag & drop if we don’t. - * Also, xprop(1) needs that to work. */ - long data[] = { XCB_WM_STATE_NORMAL, XCB_NONE }; - xcb_change_property(conn, XCB_PROP_MODE_REPLACE, new->child, atoms[WM_STATE], atoms[WM_STATE], 32, 2, data); - /* Put the client inside the save set. Upon termination (whether killed or normal exit does not matter) of the window manager, these clients will be correctly reparented to their most closest living ancestor (= cleanup) */ @@ -442,7 +437,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, xcb_map_window(conn, child); if (map_frame) { LOG("Mapping client\n"); - xcb_map_window(conn, new->frame); + client_map(conn, new); } if (CUR_CELL->workspace->fullscreen_client == NULL && !new->dock) { /* Focus the new window if we’re not in fullscreen mode and if it is not a dock window */ diff --git a/src/workspace.c b/src/workspace.c index d9925743..e89591a2 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -275,12 +275,12 @@ void workspace_map_clients(xcb_connection_t *conn, Workspace *ws) { /* Map all clients on the new workspace */ FOR_TABLE(ws) CIRCLEQ_FOREACH(client, &(ws->table[cols][rows]->clients), clients) - xcb_map_window(conn, client->frame); + client_map(conn, client); /* Map all floating clients */ if (!ws->floating_hidden) TAILQ_FOREACH(client, &(ws->floating_clients), floating_clients) - xcb_map_window(conn, client->frame); + client_map(conn, client); /* Map all stack windows, if any */ struct Stack_Window *stack_win; @@ -312,7 +312,7 @@ void workspace_unmap_clients(xcb_connection_t *conn, Workspace *u_ws) { FOR_TABLE(u_ws) CIRCLEQ_FOREACH(client, &(u_ws->table[cols][rows]->clients), clients) { LOG("unmapping normal client %p / %p / %p\n", client, client->frame, client->child); - xcb_unmap_window(conn, client->frame); + client_unmap(conn, client); unmapped_clients++; } @@ -323,7 +323,7 @@ void workspace_unmap_clients(xcb_connection_t *conn, Workspace *u_ws) { LOG("unmapping floating client %p / %p / %p\n", client, client->frame, client->child); - xcb_unmap_window(conn, client->frame); + client_unmap(conn, client); unmapped_clients++; }