diff --git a/docs/userguide b/docs/userguide index 27e3b9ed..e12d8b6e 100644 --- a/docs/userguide +++ b/docs/userguide @@ -737,6 +737,25 @@ force_xinerama yes Also note that your output names are not descriptive (like +HDMI1+) when using Xinerama, instead they are counted up, starting at 0: +xinerama-0+, +xinerama-1+, … +=== Automatic back-and-forth when switching to the current workspace + +This configuration directive enables automatic +workspace back_and_forth+ (see +<>) when switching to the workspace that is currently focused. + +For instance: Assume you are on workspace "1: www" and switch to "2: IM" using +mod+2 because somebody sent you a message. You don’t need to remember where you +came from now, you can just press mod+2 again to switch back to "1: www". + +*Syntax*: +-------------------------------------- +workspace_auto_back_and_forth +-------------------------------------- + +*Example*: +--------------------------------- +workspace_auto_back_and_forth yes +--------------------------------- + == List of commands Commands are what you bind to specific keypresses. You can also issue commands @@ -892,6 +911,10 @@ workspace 1, 3, 4 and 9 and you want to cycle through them with a single key combination. Similarily, you can use +move workspace next+ and +move workspace prev+ to move a container to the next/previous workspace. +[[back_and_forth]] +To switch back to the previously focused workspace, use +workspace +back_and_forth+. + 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 may also use +left+, +right+, +up+, +down+ instead of the xrandr output name to @@ -906,6 +929,9 @@ bindsym mod+2 workspace 2 bindsym mod+Shift+1 move workspace 1 bindsym mod+Shift+2 move workspace 2 ... + +# switch between the current and the previously focused one +bindsym mod+b workspace back_and_forth ------------------------- ==== Named workspaces diff --git a/include/config.h b/include/config.h index 07391a6a..337db8fb 100644 --- a/include/config.h +++ b/include/config.h @@ -133,6 +133,12 @@ struct Config { * is fetched once and never updated. */ bool force_xinerama; + /** Automatic workspace back and forth switching. If this is set, a + * switch to the currently active workspace will switch to the + * previously focused one instead, making it possible to fast toggle + * between two workspaces. */ + bool workspace_auto_back_and_forth; + /** The default border style for new windows. */ border_style_t default_border; diff --git a/include/workspace.h b/include/workspace.h index 3f0e83c2..1dce680a 100644 --- a/include/workspace.h +++ b/include/workspace.h @@ -70,6 +70,13 @@ Con* workspace_next(); */ Con* workspace_prev(); +/** + * Focuses the previously focused workspace. + * + */ +void workspace_back_and_forth(); + + #if 0 /** * Assigns the given workspace to the given screen by correctly updating its diff --git a/src/cfgparse.l b/src/cfgparse.l index 49714401..622a133b 100644 --- a/src/cfgparse.l +++ b/src/cfgparse.l @@ -127,6 +127,7 @@ none { return TOK_NONE; } focus_follows_mouse { return TOKFOCUSFOLLOWSMOUSE; } force_focus_wrapping { return TOK_FORCE_FOCUS_WRAPPING; } force_xinerama { return TOK_FORCE_XINERAMA; } +workspace_auto_back_and_forth { return TOK_WORKSPACE_AUTO_BAF; } workspace_bar { return TOKWORKSPACEBAR; } popup_during_fullscreen { return TOK_POPUP_DURING_FULLSCREEN; } ignore { return TOK_IGNORE; } diff --git a/src/cfgparse.y b/src/cfgparse.y index 9a417f2a..6869eee7 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -623,6 +623,7 @@ void parse_file(const char *f) { %token TOKFOCUSFOLLOWSMOUSE "focus_follows_mouse" %token TOK_FORCE_FOCUS_WRAPPING "force_focus_wrapping" %token TOK_FORCE_XINERAMA "force_xinerama" +%token TOK_WORKSPACE_AUTO_BAF "workspace_auto_back_and_forth" %token TOKWORKSPACEBAR "workspace_bar" %token TOK_DEFAULT "default" %token TOK_STACKING "stacking" @@ -679,6 +680,7 @@ line: | focus_follows_mouse | force_focus_wrapping | force_xinerama + | workspace_back_and_forth | workspace_bar | workspace | assign @@ -1035,6 +1037,14 @@ force_xinerama: } ; +workspace_back_and_forth: + TOK_WORKSPACE_AUTO_BAF bool + { + DLOG("automatic workspace back-and-forth = %d\n", $2); + config.workspace_auto_back_and_forth = $2; + } + ; + workspace_bar: TOKWORKSPACEBAR bool { diff --git a/src/cmdparse.l b/src/cmdparse.l index f6b132ca..6dda34d0 100644 --- a/src/cmdparse.l +++ b/src/cmdparse.l @@ -72,10 +72,11 @@ EOL (\r?\n) cmdyycolumn = 1; } - /* the next/prev tokens are here to recognize them *before* handling - * strings ('workspace' command) */ + /* the next/prev/back_and_forth tokens are here to recognize them *before* + * handling strings ('workspace' command) */ next { return TOK_NEXT; } prev { return TOK_PREV; } +back_and_forth { return TOK_BACK_AND_FORTH; } \"[^\"]+\" { BEGIN(INITIAL); diff --git a/src/cmdparse.y b/src/cmdparse.y index ecc4bc02..a43d2be0 100644 --- a/src/cmdparse.y +++ b/src/cmdparse.y @@ -174,6 +174,7 @@ bool definitelyGreaterThan(float a, float b, float epsilon) { %token TOK_OR "or" %token TOK_PPT "ppt" %token TOK_NOP "nop" +%token TOK_BACK_AND_FORTH "back_and_forth" %token TOK_CLASS "class" %token TOK_INSTANCE "instance" @@ -587,9 +588,28 @@ workspace: workspace_show(workspace_prev()); tree_render(); } + | TOK_WORKSPACE TOK_BACK_AND_FORTH + { + workspace_back_and_forth(); + tree_render(); + } | TOK_WORKSPACE STR { printf("should switch to workspace %s\n", $2); + + Con *ws = con_get_workspace(focused); + + /* Check if the command wants to switch to the current workspace */ + if (strcmp(ws->name, $2) == 0) { + printf("This workspace is already focused.\n"); + if (config.workspace_auto_back_and_forth) { + workspace_back_and_forth(); + free($2); + tree_render(); + } + break; + } + workspace_show_by_name($2); free($2); diff --git a/src/workspace.c b/src/workspace.c index b4ed5530..e06dbde5 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -2,13 +2,17 @@ * vim:ts=4:sw=4:expandtab * * i3 - an improved dynamic tiling window manager - * © 2009-2010 Michael Stapelberg and contributors (see also: LICENSE) + * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) * * workspace.c: Functions for modifying workspaces * */ #include "all.h" +/* Stores a copy of the name of the last used workspace for the workspace + * back-and-forth switching. */ +static char *previous_workspace_name = NULL; + /* * Returns a pointer to the workspace with the given number (starting at 0), * creating the workspace if necessary (by allocating the necessary amount of @@ -191,11 +195,20 @@ static void _workspace_show(Con *workspace, bool changed_num_workspaces) { /* enable fullscreen for the target workspace. If it happens to be the * same one we are currently on anyways, we can stop here. */ workspace->fullscreen_mode = CF_OUTPUT; - if (workspace == con_get_workspace(focused)) { + current = con_get_workspace(focused); + if (workspace == current) { DLOG("Not switching, already there.\n"); return; } + /* Remember currently focused workspace for switching back to it later with + * the 'workspace back_and_forth' command. + * NOTE: We have to duplicate the name as the original will be freed when + * the corresponding workspace is cleaned up. */ + + FREE(previous_workspace_name); + previous_workspace_name = sstrdup(current->name); + workspace_reassign_sticky(workspace); LOG("switching to %p\n", workspace); @@ -368,6 +381,19 @@ workspace_prev_end: return prev; } +/* + * Focuses the previously focused workspace. + * + */ +void workspace_back_and_forth() { + if (!previous_workspace_name) { + DLOG("No previous workspace name set. Not switching."); + return; + } + + workspace_show_by_name(previous_workspace_name); +} + static bool get_urgency_flag(Con *con) { Con *child; TAILQ_FOREACH(child, &(con->nodes_head), nodes)