- `shift left|right|up|down` — Exchange the current window with the given neighbor.
-- `swap` — Swap the focused window with the last focused window.
+- `swap [biggest|smallest]` — Swap the focused window with the biggest/smallest window or with the last focused window if no arguments are given.
- `push left|right|up|down` — Push the fence located in the given direction.
.BI shift " left|right|up|down"
Exchange the current window with the given neighbor.
.TP
-.BI swap
-Swap the focused window with the last focused window.
+.BI swap " [biggest|smallest]"
+Swap the focused window with the biggest/smallest window or with the last focused window if no arguments are given.
.TP
.BI push " left|right|up|down"
Push the fence located in the given direction.
remove_rule_by_uid(uid);
return;
} else if (strcmp(cmd, "swap") == 0) {
- swap_nodes(mon->desk, mon->desk->focus, mon->desk, mon->desk->last_focus);
+ char *arg;
+ swap_arg_t a;
+ if ((arg = strtok(NULL, TOK_SEP)) != NULL) {
+ if (parse_swap_argument(arg, &a)) {
+ node_t *n = find_by_area(mon->desk, a);
+ swap_nodes(mon->desk, mon->desk->focus, mon->desk, n);
+ }
+ } else {
+ swap_nodes(mon->desk, mon->desk->focus, mon->desk, mon->desk->last_focus);
+ }
} else if (strcmp(cmd, "alternate") == 0) {
focus_node(mon, mon->desk, mon->desk->last_focus, true);
return;
return false;
}
+bool parse_swap_argument(char *s, swap_arg_t *a)
+{
+ if (strcmp(s, "biggest") == 0) {
+ *a = SWAP_BIGGEST;
+ return true;
+ } else if (strcmp(s, "smallest") == 0) {
+ *a = SWAP_SMALLEST;
+ return true;
+ }
+ return false;
+}
+
bool parse_cycle_direction(char *s, cycle_dir_t *d)
{
if (strcmp(s, "prev") == 0) {
bool parse_layout(char *, layout_t *);
bool parse_direction(char *, direction_t *);
bool parse_nearest_argument(char *, nearest_arg_t *);
+bool parse_swap_argument(char *, swap_arg_t *);
bool parse_cycle_direction(char *, cycle_dir_t *);
bool parse_circulate_direction(char *, circulate_dir_t *);
bool parse_list_option(char *, list_option_t *);
return NULL;
}
+int tiled_area(node_t *n)
+{
+ if (n == NULL)
+ return -1;
+ xcb_rectangle_t rect = n->client->tiled_rectangle;
+ return rect.width * rect.height;
+}
+
+node_t *find_by_area(desktop_t *d, swap_arg_t a)
+{
+ if (d == NULL)
+ return NULL;
+
+ node_t *r = NULL;
+ int r_area = tiled_area(r);
+
+ for (node_t *f = first_extrema(d->root); f != NULL; f = next_leaf(f)) {
+ int f_area = tiled_area(f);
+ if (r == NULL) {
+ r = f;
+ r_area = f_area;
+ } else if ((a == SWAP_BIGGEST && f_area > r_area)
+ || (a == SWAP_SMALLEST && f_area < r_area)) {
+ r = f;
+ r_area = f_area;
+ }
+ }
+
+ return r;
+}
+
void move_fence(node_t *n, direction_t dir, fence_move_t mov)
{
node_t *fence = find_fence(n, dir);
node_t *prev_leaf(node_t *);
node_t *find_fence(node_t *, direction_t);
node_t *find_neighbor(node_t *, direction_t);
+int tiled_area(node_t *);
+node_t *find_by_area(desktop_t *, swap_arg_t);
void move_fence(node_t *, direction_t, fence_move_t);
void rotate_tree(node_t *, rotate_t);
void flip_tree(node_t *, flip_t);
NEAREST_NEWER
} nearest_arg_t;
+typedef enum {
+ SWAP_BIGGEST,
+ SWAP_SMALLEST
+} swap_arg_t;
+
typedef enum {
CIRCULATE_FORWARD,
CIRCULATE_BACKWARD