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