]> git.sur5r.net Git - i3/i3/commitdiff
Implement 'workspace next/prev' (+test)
authorMichael Stapelberg <michael@stapelberg.de>
Fri, 10 Jun 2011 14:03:59 +0000 (16:03 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Fri, 10 Jun 2011 14:03:59 +0000 (16:03 +0200)
docs/userguide
include/workspace.h
src/cmdparse.l
src/cmdparse.y
src/workspace.c
testcases/t/17-workspace.t

index 205b5a99614a6a40120c838b6c4e21de56c751b0..0046028acffb7596ca870757d229b655a4d02e70 100644 (file)
@@ -653,13 +653,10 @@ bindsym Mod1+semicolon move right
 To change to a specific workspace, use the +workspace+ command, followed by the
 number or name of the workspace. To move containers, use +move workspace+.
 
-//////////////////////////////////////////////////////////////////////////////
-TODO: not yet implemented
-
-You can also switch to the next and previous workspace with the commands +nw+
-and +pw+, 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.
-//////////////////////////////////////////////////////////////////////////////
+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.
 
 *Examples*:
 -------------------------
index 367c150e9e33410a9638441dae8de6df06015f13..aebf13656d866e8b15e3de5a03678f3bb9f3baed 100644 (file)
@@ -49,6 +49,18 @@ bool workspace_is_visible(Con *ws);
 /** Switches to the given workspace */
 void workspace_show(const char *num);
 
+/**
+ * Focuses the next workspace.
+ *
+ */
+void workspace_next();
+
+/**
+ * Focuses the previous workspace.
+ *
+ */
+void workspace_prev();
+
 #if 0
 /**
  * Assigns the given workspace to the given screen by correctly updating its
index 641265e60444d78a0e22127e54df257467b8b63d..9a0bc903fcfac2551f3fbf94451899498a951352 100644 (file)
@@ -71,6 +71,11 @@ EOL (\r?\n)
     cmdyycolumn = 1;
 }
 
+    /* the next/prev tokens are here to recognize them *before* handling
+     * strings ('workspace' command) */
+next                            { return TOK_NEXT; }
+prev                            { return TOK_PREV; }
+
 <WANT_STRING>\"[^\"]+\"         {
                                   BEGIN(INITIAL);
                                   /* strip quotes */
@@ -120,7 +125,6 @@ workspace                       { WS_STRING; return TOK_WORKSPACE; }
 focus                           { return TOK_FOCUS; }
 move                            { return TOK_MOVE; }
 open                            { return TOK_OPEN; }
-prev                            { return TOK_PREV; }
 split                           { return TOK_SPLIT; }
 horizontal                      { return TOK_HORIZONTAL; }
 vertical                        { return TOK_VERTICAL; }
index f86bead94c481c373c7c773056cec62f7084d7ef..3268311235a53b522c599dd3c46d99d6e0222d78 100644 (file)
@@ -142,6 +142,7 @@ char *parse_cmd(const char *new) {
 %token              TOK_FOCUS           "focus"
 %token              TOK_MOVE            "move"
 %token              TOK_OPEN            "open"
+%token              TOK_NEXT            "next"
 %token              TOK_PREV            "prev"
 %token              TOK_SPLIT           "split"
 %token              TOK_HORIZONTAL      "horizontal"
@@ -487,7 +488,17 @@ optional_kill_mode:
     ;
 
 workspace:
-    TOK_WORKSPACE STR
+    TOK_WORKSPACE TOK_NEXT
+    {
+        workspace_next();
+        tree_render();
+    }
+    | TOK_WORKSPACE TOK_PREV
+    {
+        workspace_prev();
+        tree_render();
+    }
+    | TOK_WORKSPACE STR
     {
         printf("should switch to workspace %s\n", $2);
         workspace_show($2);
index 3a637b2ff94bd3f7ad3734fabd2402df9e5e040a..ec57df8d43f91b073eec8337fca73b5bc2e46fd8 100644 (file)
@@ -231,6 +231,32 @@ void workspace_show(const char *num) {
     ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"focus\"}");
 }
 
+/*
+ * Focuses the next workspace.
+ *
+ */
+void workspace_next() {
+    Con *ws = con_get_workspace(focused);
+    Con *next = TAILQ_NEXT(ws, nodes);
+    if (!next)
+        next = TAILQ_FIRST(&(ws->parent->nodes_head));
+
+    workspace_show(next->name);
+}
+
+/*
+ * Focuses the previous workspace.
+ *
+ */
+void workspace_prev() {
+    Con *ws = con_get_workspace(focused);
+    Con *prev = TAILQ_PREV(ws, nodes_head, nodes);
+    if (!prev)
+        prev = TAILQ_LAST(&(ws->parent->nodes_head), nodes_head);
+
+    workspace_show(prev->name);
+}
+
 static bool get_urgency_flag(Con *con) {
     Con *child;
     TAILQ_FOREACH(child, &(con->nodes_head), nodes)
index e7892b2b6443765f95663a203f3aa6f023396eb1..32f8296905148b57348f12899f3edc8d9d7d8894 100644 (file)
@@ -4,6 +4,7 @@
 # Tests whether we can switch to a non-existant workspace
 # (necessary for further tests)
 #
+use List::Util qw(first);
 use i3test;
 
 sub workspace_exists {
@@ -32,4 +33,89 @@ cmd "workspace $otmp";
 cmd "workspace $otmp";
 ok(workspace_exists($otmp), 'other workspace still exists');
 
+
+#####################################################################
+# check if the workspace next / prev commands work
+#####################################################################
+
+cmd 'workspace next';
+
+ok(!workspace_exists('next'), 'workspace "next" does not exist');
+
+cmd "workspace $tmp";
+cmd 'open';
+
+ok(workspace_exists($tmp), 'workspace created');
+
+cmd "workspace $otmp";
+cmd 'open';
+
+ok(workspace_exists($tmp), 'workspace tmp still exists');
+ok(workspace_exists($otmp), 'workspace otmp created');
+
+sub focused_ws_con {
+    my $i3 = i3("/tmp/nestedcons");
+    my $tree = $i3->get_tree->recv;
+    my @outputs = @{$tree->{nodes}};
+    my @cons;
+    for my $output (@outputs) {
+        # get the first CT_CON of each output
+        my $content = first { $_->{type} == 2 } @{$output->{nodes}};
+        my @focused = @{$content->{focus}};
+        return first { $_->{id} == $focused[0] } @{$content->{nodes}};
+    }
+}
+
+sub focused_ws {
+    my $con = focused_ws_con;
+    return $con->{name};
+}
+
+is(focused_ws(), $otmp, 'focused workspace is otmp');
+
+cmd 'workspace prev';
+is(focused_ws(), $tmp, 'focused workspace is tmp after workspace prev');
+
+cmd 'workspace next';
+is(focused_ws(), $otmp, 'focused workspace is otmp after workspace next');
+
+
+#####################################################################
+# check that wrapping works
+#####################################################################
+
+cmd 'workspace next';
+is(focused_ws(), '1', 'focused workspace is 1 after workspace next');
+
+cmd 'workspace next';
+is(focused_ws(), $tmp, 'focused workspace is tmp after workspace next');
+
+cmd 'workspace next';
+is(focused_ws(), $otmp, 'focused workspace is otmp after workspace next');
+
+
+cmd 'workspace prev';
+is(focused_ws(), $tmp, 'focused workspace is tmp after workspace prev');
+
+cmd 'workspace prev';
+is(focused_ws(), '1', 'focused workspace is tmp after workspace prev');
+
+cmd 'workspace prev';
+is(focused_ws(), $otmp, 'focused workspace is otmp after workspace prev');
+
+
+#####################################################################
+# check if we can change to "next" / "prev"
+#####################################################################
+
+cmd 'workspace "next"';
+
+ok(workspace_exists('next'), 'workspace "next" exists');
+is(focused_ws(), 'next', 'now on workspace next');
+
+cmd 'workspace "prev"';
+
+ok(workspace_exists('prev'), 'workspace "prev" exists');
+is(focused_ws(), 'prev', 'now on workspace prev');
+
 done_testing;