From 9866b0080226504b23eace04947cc44e13ca6697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 22 Aug 2015 23:37:41 +0200 Subject: [PATCH] Implement new 'sticky' command to manually set, remove or toggle the sticky state on a window. --- docs/userguide | 21 +++++++++++++++++++++ include/commands.h | 6 ++++++ include/ewmh.h | 6 ++++++ parser-specs/commands.spec | 6 ++++++ src/commands.c | 31 +++++++++++++++++++++++++++++++ src/ewmh.c | 14 ++++++++++++++ testcases/t/187-commands-parser.t | 2 +- 7 files changed, 85 insertions(+), 1 deletion(-) diff --git a/docs/userguide b/docs/userguide index 5e148ff5..d1660c49 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1834,6 +1834,27 @@ bindsym $mod+c move absolute position center bindsym $mod+m move position mouse ------------------------------------------------------- +=== Sticky floating windows + +If you want a window to stick to the glass, i.e., have it stay on screen even +if you switch to another workspace, you can use the +sticky+ command. For +example, this can be useful for notepads, a media player or a video chat +window. + +Note that while any window can be made sticky through this command, it will +only take effect if the window is floating. + +*Syntax*: +---------------------------- +sticky enable|disable|toggle +---------------------------- + +*Examples*: +------------------------------------------------------ +# make a terminal sticky that was started as a notepad +for_window [instance=notepad] sticky enable +------------------------------------------------------ + === Changing (named) workspaces/moving to workspaces To change to a specific workspace, use the +workspace+ command, followed by the diff --git a/include/commands.h b/include/commands.h index b243b9e0..80b0efb0 100644 --- a/include/commands.h +++ b/include/commands.h @@ -204,6 +204,12 @@ void cmd_focus(I3_CMD); */ void cmd_fullscreen(I3_CMD, char *action, char *fullscreen_mode); +/** + * Implementation of 'sticky enable|disable|toggle'. + * + */ +void cmd_sticky(I3_CMD, char *action); + /** * Implementation of 'move [ [px]]'. * diff --git a/include/ewmh.h b/include/ewmh.h index d94b7f3a..7ed9b544 100644 --- a/include/ewmh.h +++ b/include/ewmh.h @@ -68,6 +68,12 @@ void ewmh_update_client_list(xcb_window_t *list, int num_windows); */ void ewmh_update_client_list_stacking(xcb_window_t *stack, int num_windows); +/** + * Set or remove _NET_WM_STATE_STICKY on the window. + * + */ +void ewmh_update_sticky(xcb_window_t window, bool sticky); + /** * Set up the EWMH hints on the root window. * diff --git a/parser-specs/commands.spec b/parser-specs/commands.spec index f5fb9884..5e2bfd8f 100644 --- a/parser-specs/commands.spec +++ b/parser-specs/commands.spec @@ -29,6 +29,7 @@ state INITIAL: 'kill' -> KILL 'open' -> call cmd_open() 'fullscreen' -> FULLSCREEN + 'sticky' -> STICKY 'split' -> SPLIT 'floating' -> FLOATING 'mark' -> MARK @@ -183,6 +184,11 @@ state FULLSCREEN_COMPAT: end -> call cmd_fullscreen("toggle", "output") +# sticky enable|disable|toggle +state STICKY: + action = 'enable', 'disable', 'toggle' + -> call cmd_sticky($action) + # split v|h|vertical|horizontal state SPLIT: direction = 'horizontal', 'vertical', 'v', 'h' diff --git a/src/commands.c b/src/commands.c index 443edf4a..c8164da6 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1569,6 +1569,37 @@ void cmd_fullscreen(I3_CMD, char *action, char *fullscreen_mode) { ysuccess(true); } +/* + * Implementation of 'sticky enable|disable|toggle'. + * + */ +void cmd_sticky(I3_CMD, char *action) { + DLOG("%s sticky on window\n", action); + HANDLE_EMPTY_MATCH; + + owindow *current; + TAILQ_FOREACH(current, &owindows, owindows) { + if (current->con->window == NULL) { + ELOG("only containers holding a window can be made sticky, skipping con = %p\n", current->con); + continue; + } + DLOG("setting sticky for container = %p / %s\n", current->con, current->con->name); + + bool sticky = false; + if (strcmp(action, "enable") == 0) + sticky = true; + else if (strcmp(action, "disable") == 0) + sticky = false; + else if (strcmp(action, "toggle") == 0) + sticky = !current->con->sticky; + + current->con->sticky = sticky; + ewmh_update_sticky(current->con->window->id, sticky); + } + + ysuccess(true); +} + /* * Implementation of 'move [ [px]]'. * diff --git a/src/ewmh.c b/src/ewmh.c index 36c6a160..eb6a6ea6 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -213,6 +213,20 @@ void ewmh_update_client_list_stacking(xcb_window_t *stack, int num_windows) { stack); } +/* + * Set or remove _NET_WM_STATE_STICKY on the window. + * + */ +void ewmh_update_sticky(xcb_window_t window, bool sticky) { + uint32_t values[1]; + unsigned int num = 0; + + if (sticky) + values[num++] = A__NET_WM_STATE_STICKY; + + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, window, A__NET_WM_STATE, XCB_ATOM_ATOM, 32, num, values); +} + /* * Set up the EWMH hints on the root window. * diff --git a/testcases/t/187-commands-parser.t b/testcases/t/187-commands-parser.t index fc7fa882..8aff1f6d 100644 --- a/testcases/t/187-commands-parser.t +++ b/testcases/t/187-commands-parser.t @@ -144,7 +144,7 @@ is(parser_calls("\nworkspace test"), ################################################################################ is(parser_calls('unknown_literal'), - "ERROR: Expected one of these tokens: , '[', 'move', 'exec', 'exit', 'restart', 'reload', 'shmlog', 'debuglog', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'split', 'floating', 'mark', 'unmark', 'resize', 'rename', 'nop', 'scratchpad', 'title_format', 'mode', 'bar'\n" . + "ERROR: Expected one of these tokens: , '[', 'move', 'exec', 'exit', 'restart', 'reload', 'shmlog', 'debuglog', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'sticky', 'split', 'floating', 'mark', 'unmark', 'resize', 'rename', 'nop', 'scratchpad', 'title_format', 'mode', 'bar'\n" . "ERROR: Your command: unknown_literal\n" . "ERROR: ^^^^^^^^^^^^^^^", 'error for unknown literal ok');