i3 - improved tiling WM


Make command `move [direction]` work with criteria

Patch status: merged

Patch by Tony Crisci

Long description:

A container selected with criteria should be moved with the `move
[direction]` command, instead of this command always acting on the
focused container.

To apply this patch, use:
curl http://cr.i3wm.org/patch/593/raw.patch | git am

b/include/move.h

20
@@ -10,8 +10,8 @@
21
 #pragma once
22
 
23
 /**
24
- * Moves the current container in the given direction (TOK_LEFT, TOK_RIGHT,
25
+ * Moves the given container in the given direction (TOK_LEFT, TOK_RIGHT,
26
  * TOK_UP, TOK_DOWN from cmdparse.l)
27
  *
28
  */
29
-void tree_move(int direction);
30
+void tree_move(Con *con, int direction);

b/src/commands.c

35
@@ -1552,26 +1552,36 @@ void cmd_move_direction(I3_CMD, char *direction, char *move_px) {
36
     // TODO: We could either handle this in the parser itself as a separate token (and make the stack typed) or we need a better way to convert a string to a number with error checking
37
     int px = atoi(move_px);
38
 
39
-    /* TODO: make 'move' work with criteria. */
40
-    DLOG("moving in direction %s, px %s\n", direction, move_px);
41
-    if (con_is_floating(focused)) {
42
-        DLOG("floating move with %d pixels\n", px);
43
-        Rect newrect = focused->parent->rect;
44
-        if (strcmp(direction, "left") == 0) {
45
-            newrect.x -= px;
46
-        } else if (strcmp(direction, "right") == 0) {
47
-            newrect.x += px;
48
-        } else if (strcmp(direction, "up") == 0) {
49
-            newrect.y -= px;
50
-        } else if (strcmp(direction, "down") == 0) {
51
-            newrect.y += px;
52
+    owindow *current;
53
+    HANDLE_EMPTY_MATCH;
54
+
55
+    Con *initially_focused = focused;
56
+
57
+    TAILQ_FOREACH (current, &owindows, owindows) {
58
+        DLOG("moving in direction %s, px %s\n", direction, move_px);
59
+        if (con_is_floating(current->con)) {
60
+            DLOG("floating move with %d pixels\n", px);
61
+            Rect newrect = current->con->parent->rect;
62
+            if (strcmp(direction, "left") == 0) {
63
+                newrect.x -= px;
64
+            } else if (strcmp(direction, "right") == 0) {
65
+                newrect.x += px;
66
+            } else if (strcmp(direction, "up") == 0) {
67
+                newrect.y -= px;
68
+            } else if (strcmp(direction, "down") == 0) {
69
+                newrect.y += px;
70
+            }
71
+            floating_reposition(current->con->parent, newrect);
72
+        } else {
73
+            tree_move(current->con, (strcmp(direction, "right") == 0 ? D_RIGHT : (strcmp(direction, "left") == 0 ? D_LEFT : (strcmp(direction, "up") == 0 ? D_UP : D_DOWN))));
74
+            cmd_output->needs_tree_render = true;
75
         }
76
-        floating_reposition(focused->parent, newrect);
77
-    } else {
78
-        tree_move((strcmp(direction, "right") == 0 ? D_RIGHT : (strcmp(direction, "left") == 0 ? D_LEFT : (strcmp(direction, "up") == 0 ? D_UP : D_DOWN))));
79
-        cmd_output->needs_tree_render = true;
80
     }
81
 
82
+    /* the move command should not disturb focus */
83
+    if (focused != initially_focused)
84
+        con_focus(initially_focused);
85
+
86
     // XXX: default reply for now, make this a better reply
87
     ysuccess(true);
88
 }

b/src/move.c

93
@@ -132,18 +132,17 @@ static void move_to_output_directed(Con *con, direction_t direction) {
94
 }
95
 
96
 /*
97
- * Moves the current container in the given direction (D_LEFT, D_RIGHT,
98
+ * Moves the given container in the given direction (D_LEFT, D_RIGHT,
99
  * D_UP, D_DOWN).
100
  *
101
  */
102
-void tree_move(int direction) {
103
+void tree_move(Con *con, int direction) {
104
     position_t position;
105
     Con *target;
106
 
107
     DLOG("Moving in direction %d\n", direction);
108
 
109
     /* 1: get the first parent with the same orientation */
110
-    Con *con = focused;
111
 
112
     if (con->type == CT_WORKSPACE) {
113
         DLOG("Not moving workspace\n");

b/testcases/t/232-cmd-move-criteria.t

119
@@ -0,0 +1,37 @@
120
+#!perl
121
+# vim:ts=4:sw=4:expandtab
122
+#
123
+# Please read the following documents before working on tests:
124
+# • http://build.i3wm.org/docs/testsuite.html
125
+#   (or docs/testsuite)
126
+#
127
+# • http://build.i3wm.org/docs/lib-i3test.html
128
+#   (alternatively: perldoc ./testcases/lib/i3test.pm)
129
+#
130
+# • http://build.i3wm.org/docs/ipc.html
131
+#   (or docs/ipc)
132
+#
133
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
134
+#   (unless you are already familiar with Perl)
135
+#
136
+# Test that the `move [direction]` command works with criteria
137
+# Bug still in: 4.8-16-g6888a1f
138
+use i3test;
139
+
140
+my $ws = fresh_workspace;
141
+
142
+my $win1 = open_window;
143
+my $win2 = open_window;
144
+my $win3 = open_window;
145
+
146
+# move win1 from the left to the right
147
+cmd '[id="' . $win1->{id} . '"] move right';
148
+
149
+# now they should be switched, with win2 still being focused
150
+my $ws_con = get_ws($ws);
151
+
152
+# win2 should be on the left
153
+is($ws_con->{nodes}[0]->{window}, $win2->{id}, 'the `move [direction]` command should work with criteria');
154
+is($x->input_focus, $win3->{id}, 'it should not disturb focus');
155
+
156
+done_testing;