Implement 'workspace back_and_forth' (Patch by Michael Walle)

This commit is contained in:
Michael Stapelberg 2011-10-17 23:17:56 +01:00
parent c3a18104cd
commit 178be03fa6
8 changed files with 101 additions and 4 deletions

View File

@ -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
<<back_and_forth>>) 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 dont 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 <yes|no>
--------------------------------------
*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

View File

@ -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;

View File

@ -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

View File

@ -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; }

View File

@ -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
{

View File

@ -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; }
<WANT_STRING>\"[^\"]+\" {
BEGIN(INITIAL);

View File

@ -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);

View File

@ -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)