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