diff --git a/docs/userguide b/docs/userguide index 8b3a6859..27e3b9ed 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1,7 +1,7 @@ i3 User’s Guide =============== Michael Stapelberg -September 2011 +October 2011 This document contains all the information you need to configure and use the i3 window manager. If it does not, please contact us on IRC (preferred) or post your @@ -889,7 +889,8 @@ number or name of the workspace. To move containers to specific workspaces, use You can also switch to the next and previous workspace with the commands +workspace next+ and +workspace prev+, which is handy, for example, if you have workspace 1, 3, 4 and 9 and you want to cycle through them with a single key -combination. +combination. Similarily, you can use +move workspace next+ and +move workspace +prev+ to move a container to the next/previous workspace. To move a container to another xrandr output such as +LVDS1+ or +VGA1+, you can use the +move output+ command followed by the name of the target output. You diff --git a/include/workspace.h b/include/workspace.h index aebf1365..3f0e83c2 100644 --- a/include/workspace.h +++ b/include/workspace.h @@ -46,20 +46,29 @@ void workspace_set_name(Workspace *ws, const char *name); */ bool workspace_is_visible(Con *ws); -/** Switches to the given workspace */ -void workspace_show(const char *num); - /** - * Focuses the next workspace. + * Switches to the given workspace * */ -void workspace_next(); +void workspace_show(Con *ws); /** - * Focuses the previous workspace. + * Looks up the workspace by name and switches to it. * */ -void workspace_prev(); +void workspace_show_by_name(const char *num); + +/** + * Returns the next workspace. + * + */ +Con* workspace_next(); + +/** + * Returns the previous workspace. + * + */ +Con* workspace_prev(); #if 0 /** diff --git a/src/cmdparse.y b/src/cmdparse.y index 04e8b3ca..da962cf4 100644 --- a/src/cmdparse.y +++ b/src/cmdparse.y @@ -440,7 +440,7 @@ focus: int count = 0; TAILQ_FOREACH(current, &owindows, owindows) { Con *ws = con_get_workspace(current->con); - workspace_show(ws->name); + workspace_show(ws); LOG("focusing %p / %s\n", current->con, current->con->name); con_focus(current->con); count++; @@ -561,18 +561,18 @@ optional_kill_mode: workspace: TOK_WORKSPACE TOK_NEXT { - workspace_next(); + workspace_show(workspace_next()); tree_render(); } | TOK_WORKSPACE TOK_PREV { - workspace_prev(); + workspace_show(workspace_prev()); tree_render(); } | TOK_WORKSPACE STR { printf("should switch to workspace %s\n", $2); - workspace_show($2); + workspace_show_by_name($2); free($2); tree_render(); @@ -715,6 +715,38 @@ move: tree_render(); } + | TOK_MOVE TOK_WORKSPACE TOK_NEXT + { + owindow *current; + + /* get the workspace */ + Con *ws = workspace_next(); + + HANDLE_EMPTY_MATCH; + + TAILQ_FOREACH(current, &owindows, owindows) { + printf("matching: %p / %s\n", current->con, current->con->name); + con_move_to_workspace(current->con, ws, true, false); + } + + tree_render(); + } + | TOK_MOVE TOK_WORKSPACE TOK_PREV + { + owindow *current; + + /* get the workspace */ + Con *ws = workspace_prev(); + + HANDLE_EMPTY_MATCH; + + TAILQ_FOREACH(current, &owindows, owindows) { + printf("matching: %p / %s\n", current->con, current->con->name); + con_move_to_workspace(current->con, ws, true, false); + } + + tree_render(); + } | TOK_MOVE TOK_OUTPUT STR { owindow *current; diff --git a/src/con.c b/src/con.c index 8fbedd3d..805d33b8 100644 --- a/src/con.c +++ b/src/con.c @@ -632,7 +632,7 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool * focused. Must do before attaching because workspace_show checks to see * if focused container is in its area. */ if (workspace_is_visible(workspace)) { - workspace_show(workspace->name); + workspace_show(workspace); /* Don’t warp if told so (when dragging floating windows with the * mouse for example) */ @@ -668,7 +668,7 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool /* Descend focus stack in case focus_next is a workspace which can * occur if we move to the same workspace. Also show current workspace * to ensure it is focused. */ - workspace_show(con_get_workspace(focus_next)->name); + workspace_show(con_get_workspace(focus_next)); con_focus(con_descend_focused(focus_next)); } diff --git a/src/randr.c b/src/randr.c index 2b8757e5..f5f5d198 100644 --- a/src/randr.c +++ b/src/randr.c @@ -363,7 +363,7 @@ void init_ws_for_output(Output *output, Con *content) { if (visible && (previous = TAILQ_NEXT(workspace, focused))) { LOG("Switching to previously used workspace \"%s\" on output \"%s\"\n", previous->name, workspace_out->name); - workspace_show(previous->name); + workspace_show(previous); } con_detach(workspace); @@ -390,7 +390,7 @@ void init_ws_for_output(Output *output, Con *content) { if (!visible) { visible = TAILQ_FIRST(&(content->nodes_head)); focused = content; - workspace_show(visible->name); + workspace_show(visible); } return; } @@ -403,7 +403,7 @@ void init_ws_for_output(Output *output, Con *content) { LOG("Initializing first assigned workspace \"%s\" for output \"%s\"\n", assignment->name, assignment->output); focused = content; - workspace_show(assignment->name); + workspace_show_by_name(assignment->name); return; } diff --git a/src/tree.c b/src/tree.c index 4baba58e..8c73b6ab 100644 --- a/src/tree.c +++ b/src/tree.c @@ -420,7 +420,7 @@ static bool _tree_next(Con *con, char way, orientation_t orientation, bool wrap) if (!workspace) return false; - workspace_show(workspace->name); + workspace_show(workspace); Con *focus = con_descend_direction(workspace, direction); if (focus) { con_focus(focus); diff --git a/src/workspace.c b/src/workspace.c index 32564459..b4ed5530 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -176,15 +176,9 @@ static void workspace_reassign_sticky(Con *con) { workspace_reassign_sticky(current); } -/* - * Switches to the given workspace - * - */ -void workspace_show(const char *num) { - Con *workspace, *current, *old = NULL; - bool changed_num_workspaces; - workspace = workspace_get(num, &changed_num_workspaces); +static void _workspace_show(Con *workspace, bool changed_num_workspaces) { + Con *current, *old = NULL; /* disable fullscreen for the other workspaces and get the workspace we are * currently on. */ @@ -238,11 +232,30 @@ void workspace_show(const char *num) { ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"focus\"}"); } +/* + * Switches to the given workspace + * + */ +void workspace_show(Con *workspace) { + _workspace_show(workspace, false); +} + +/* + * Looks up the workspace by name and switches to it. + * + */ +void workspace_show_by_name(const char *num) { + Con *workspace; + bool changed_num_workspaces; + workspace = workspace_get(num, &changed_num_workspaces); + _workspace_show(workspace, changed_num_workspaces); +} + /* * Focuses the next workspace. * */ -void workspace_next() { +Con* workspace_next() { Con *current = con_get_workspace(focused); Con *next = NULL; Con *output; @@ -277,7 +290,7 @@ void workspace_next() { found_current = 1; } else if (child->num == -1 && (current->num != -1 || found_current)) { next = child; - goto workspace_next_show; + goto workspace_next_end; } } } @@ -292,16 +305,15 @@ void workspace_next() { next = child; } } - -workspace_next_show: - workspace_show(next->name); +workspace_next_end: + return next; } /* * Focuses the previous workspace. * */ -void workspace_prev() { +Con* workspace_prev() { Con *current = con_get_workspace(focused); Con *prev = NULL; Con *output; @@ -336,7 +348,7 @@ void workspace_prev() { found_current = 1; } else if (child->num == -1 && (current->num != -1 || found_current)) { prev = child; - goto workspace_prev_show; + goto workspace_prev_end; } } } @@ -352,8 +364,8 @@ void workspace_prev() { } } -workspace_prev_show: - workspace_show(prev->name); +workspace_prev_end: + return prev; } static bool get_urgency_flag(Con *con) { diff --git a/testcases/t/32-move-workspace.t b/testcases/t/32-move-workspace.t index 3b50e39b..82e59dd1 100644 --- a/testcases/t/32-move-workspace.t +++ b/testcases/t/32-move-workspace.t @@ -37,6 +37,39 @@ is($focus->[0], $second, 'same container on different ws'); ($nodes, $focus) = get_ws_content($tmp); ok($nodes->[0]->{focused}, 'first container focused on first ws'); +################################################################### +# check if 'move workspace next' and 'move workspace prev' work +################################################################### + +# Open two containers on the first workspace, one container on the second +# workspace. Because the workspaces are named, they will be sorted by order of +# creation. +$tmp = get_unused_workspace(); +$tmp2 = get_unused_workspace(); +cmd "workspace $tmp"; +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); +$first = open_empty_con($i3); +$second = open_empty_con($i3); +ok(@{get_ws_content($tmp)} == 2, 'two containers on first ws'); + +cmd "workspace $tmp2"; +ok(@{get_ws_content($tmp2)} == 0, 'no containers yet'); +my $third = open_empty_con($i3); +ok(@{get_ws_content($tmp2)} == 1, 'one container on second ws'); + +# go back to the first workspace, move one of the containers to the next one +cmd "workspace $tmp"; +cmd 'move workspace next'; +ok(@{get_ws_content($tmp)} == 1, 'one container on first ws'); +ok(@{get_ws_content($tmp2)} == 2, 'two containers on second ws'); + +# go to the second workspace and move two containers to the first one +cmd "workspace $tmp2"; +cmd 'move workspace prev'; +cmd 'move workspace prev'; +ok(@{get_ws_content($tmp)} == 3, 'three containers on first ws'); +ok(@{get_ws_content($tmp2)} == 0, 'no containers on second ws'); + ################################################################### # check if floating cons are moved to new workspaces properly # (that is, if they are floating on the target ws, too)