From a15ce8cb8dddf118ed27deb79eb5d1b4103e8303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Tue, 27 Sep 2016 07:39:17 +0200 Subject: [PATCH] Assign the sticky value for _NET_WM_DESKTOP on scratchpad windows. (#2457) fixes #2456 --- src/ewmh.c | 23 ++++++++++++++++------- src/manage.c | 5 ++++- testcases/t/529-net-wm-desktop.t | 20 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/ewmh.c b/src/ewmh.c index c4ae844e..5459c7e9 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -124,11 +124,13 @@ void ewmh_update_desktop_viewport(void) { } static void ewmh_update_wm_desktop_recursively(Con *con, const uint32_t desktop) { - /* Recursively call this to descend through the entire subtree. */ Con *child; + + /* Recursively call this to descend through the entire subtree. */ TAILQ_FOREACH(child, &(con->nodes_head), nodes) { ewmh_update_wm_desktop_recursively(child, desktop); } + /* If con is a workspace, we also need to go through the floating windows on it. */ if (con->type == CT_WORKSPACE) { TAILQ_FOREACH(child, &(con->floating_head), floating_windows) { @@ -139,8 +141,6 @@ static void ewmh_update_wm_desktop_recursively(Con *con, const uint32_t desktop) if (!con_has_managed_window(con)) return; - const xcb_window_t window = con->window->id; - uint32_t wm_desktop = desktop; /* Sticky windows are only actually sticky when they are floating or inside * a floating container. This is technically still slightly wrong, since @@ -151,11 +151,20 @@ static void ewmh_update_wm_desktop_recursively(Con *con, const uint32_t desktop) wm_desktop = NET_WM_DESKTOP_ALL; } + /* If the window is on the scratchpad we assign the sticky value to it + * since showing it works on any workspace. We cannot remove the property + * as per specification. */ + Con *ws = con_get_workspace(con); + if (ws != NULL && con_is_internal(ws)) { + wm_desktop = NET_WM_DESKTOP_ALL; + } + /* If this is the cached value, we don't need to do anything. */ if (con->window->wm_desktop == wm_desktop) return; con->window->wm_desktop = wm_desktop; + const xcb_window_t window = con->window->id; if (wm_desktop != NET_WM_DESKTOP_NONE) { DLOG("Setting _NET_WM_DESKTOP = %d for window 0x%08x.\n", wm_desktop, window); xcb_change_property(conn, XCB_PROP_MODE_REPLACE, window, A__NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, &wm_desktop); @@ -179,11 +188,11 @@ void ewmh_update_wm_desktop(void) { TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { Con *workspace; TAILQ_FOREACH(workspace, &(output_get_content(output)->nodes_head), nodes) { - if (con_is_internal(workspace)) - continue; - ewmh_update_wm_desktop_recursively(workspace, desktop); - ++desktop; + + if (!con_is_internal(workspace)) { + ++desktop; + } } } } diff --git a/src/manage.c b/src/manage.c index 37d50e7b..bbd84007 100644 --- a/src/manage.c +++ b/src/manage.c @@ -430,7 +430,10 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki if (xcb_reply_contains_atom(state_reply, A__NET_WM_STATE_STICKY)) nc->sticky = true; - if (cwindow->wm_desktop == NET_WM_DESKTOP_ALL) { + /* We ignore the hint for an internal workspace because windows in the + * scratchpad also have this value, but upon restarting i3 we don't want + * them to become sticky windows. */ + if (cwindow->wm_desktop == NET_WM_DESKTOP_ALL && !con_is_internal(ws)) { DLOG("This window has _NET_WM_DESKTOP = 0xFFFFFFFF. Will float it and make it sticky.\n"); nc->sticky = true; want_floating = true; diff --git a/testcases/t/529-net-wm-desktop.t b/testcases/t/529-net-wm-desktop.t index f6a3b218..8f2df735 100644 --- a/testcases/t/529-net-wm-desktop.t +++ b/testcases/t/529-net-wm-desktop.t @@ -345,6 +345,26 @@ is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated'); kill_windows; exit_gracefully($pid); +############################################################################### +# _NET_WM_DESKTOP is updated when a window is moved to the scratchpad. +############################################################################### + +$pid = launch_with_config($config); + +cmd 'workspace 0'; +$con = open_window; +cmd 'floating enable'; +is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)'); + +cmd 'move scratchpad'; +is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated'); + +cmd 'scratchpad show'; +is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)'); + +kill_windows; +exit_gracefully($pid); + ############################################################################### done_testing;