}
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) {
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
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);
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;
+ }
}
}
}
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;
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;