]> git.lizzy.rs Git - bspwm.git/commitdiff
Add tiled move/resize pointer actions
authorBastien Dejean <nihilhill@gmail.com>
Mon, 4 Feb 2013 13:22:41 +0000 (14:22 +0100)
committerBastien Dejean <nihilhill@gmail.com>
Mon, 4 Feb 2013 13:22:41 +0000 (14:22 +0100)
New arguments for `grab_pointer`: `{move,resize}_tiled`.
New setting: `fence_grip`.

README.md
bspwm.1
events.c
helpers.h
messages.c
settings.c
settings.h
tree.c
tree.h
types.c
types.h

index a3f41d0a2a6a52872b63f548fe7609a460a47610..92440b3bafcf4f66c43008e85abf784063dbfa17 100644 (file)
--- a/README.md
+++ b/README.md
@@ -115,7 +115,7 @@ The following messages are handled:
 
 - `circulate forward|backward` — Circulate the leaves in the given direction.
 
-- `grab_pointer move|resize|focus` — Begin the specified pointer action.
+- `grab_pointer move|resize|focus|move_tiled|resize_tiled` — Begin the specified pointer action.
 
 - `track_pointer ROOT_X ROOT_Y` — Pass the pointer root coordinates for the current pointer action.
 
@@ -225,6 +225,8 @@ Colors are either [X color names](http://en.wikipedia.org/wiki/X11_color_names)
 
 - `apply_shadow_property` — Enable shadows for floating windows via the `_COMPTON_SHADOW` property.
 
+- `fence_grip` — If the distance to the nearest fence is greater than `fence_grip`, the `resize_tiled` action will not be engaged.
+
 ## Key Features
 
 - Configured and controlled through messages
diff --git a/bspwm.1 b/bspwm.1
index 16c2d82ca465eee3ea99b1ffe5a12137fb1ff95f..c67112ab42a7e4df4ae3207e3cb5b174c21f3346 100644 (file)
--- a/bspwm.1
+++ b/bspwm.1
@@ -159,7 +159,7 @@ Focus the nearest window matching the given constraints.
 .BI circulate " forward|backward"
 Circulate the leaves in the given direction.
 .TP
-.BI grab_pointer " move|resize|focus"
+.BI grab_pointer " move|resize|focus|move_tiled|resize_tiled"
 Begin the specified pointer action.
 .TP
 .BI track_pointer " ROOT_X ROOT_Y"
@@ -346,6 +346,13 @@ Prevent floating windows from being raised when they might cover other floating
 Enable shadows for floating windows via the
 .B _COMPTON_SHADOW
 property.
+.TP
+.I fence_grip
+If the distance to the nearest fence is greater than
+.IR fence_grip ,
+the
+.B resize_tiled
+action will not be engaged.
 .SH AUTHOR
 .EX
 Bastien Dejean <baskerville at lavabit.com>
index 4c1386340bed8a27dd942bd85070ee21882a4336..d9f7290fbb1eed6be8d0a6e57ade515e5ed22c20 100644 (file)
--- a/events.c
+++ b/events.c
@@ -280,28 +280,35 @@ void grab_pointer(pointer_action_t pac)
     }
 
     window_location_t loc;
-    if (locate_window(win, &loc)) {
-        client_t *c = loc.node->client;
+    bool found_win = locate_window(win, &loc);
+    if (found_win || pac == ACTION_RESIZE_TILED) {
+        fence_distance_t fd;
+        client_t *c = NULL;
+        frozen_pointer->position = pos;
+        frozen_pointer->action = pac;
+        if (found_win) {
+            c = loc.node->client;
+            frozen_pointer->monitor = loc.monitor;
+            frozen_pointer->desktop = loc.desktop;
+            frozen_pointer->node = loc.node;
+            frozen_pointer->client = c;
+            frozen_pointer->window = c->window;
+        }
         switch (pac)  {
             case ACTION_FOCUS:
                 focus_node(loc.monitor, loc.desktop, loc.node, true);
                 break;
             case ACTION_MOVE:
             case ACTION_RESIZE:
-                if (is_tiled(loc.node->client)) {
-                    loc.node->client->floating_rectangle = loc.node->client->tiled_rectangle;
+                if (is_tiled(c)) {
+                    loc.node->client->floating_rectangle = c->tiled_rectangle;
                     toggle_floating(loc.node);
                     arrange(loc.monitor, loc.desktop);
-                } else if (loc.node->client->fullscreen) {
+                } else if (c->fullscreen) {
                     frozen_pointer->action = ACTION_NONE;
                     return;
                 }
-                frozen_pointer->monitor = loc.monitor;
-                frozen_pointer->desktop = loc.desktop;
-                frozen_pointer->node = loc.node;
                 frozen_pointer->rectangle = c->floating_rectangle;
-                frozen_pointer->position = pos;
-                frozen_pointer->action = pac;
                 if (pac == ACTION_RESIZE) {
                     int16_t mid_x, mid_y;
                     mid_x = c->floating_rectangle.x + (c->floating_rectangle.width / 2);
@@ -319,6 +326,20 @@ void grab_pointer(pointer_action_t pac)
                     }
                 }
                 break;
+            case ACTION_RESIZE_TILED:
+                fd = nearest_fence(pos, mon->desk->root);
+                if (fd.fence != NULL && fd.distance < fence_grip) {
+                    frozen_pointer->node = fd.fence;
+                    frozen_pointer->action = pac;
+                    frozen_pointer->rectangle = fd.fence->rectangle;
+                } else {
+                    frozen_pointer->action = ACTION_NONE;
+                }
+                break;
+            case ACTION_MOVE_TILED:
+                if (!is_tiled(c))
+                    frozen_pointer->action = ACTION_NONE;
+                break;
             case ACTION_NONE:
                 break;
         }
@@ -338,15 +359,19 @@ void track_pointer(int root_x, int root_y)
     monitor_t *m = frozen_pointer->monitor;
     desktop_t *d = frozen_pointer->desktop;
     node_t *n = frozen_pointer->node;
-    client_t *c = n->client;
+    client_t *c = frozen_pointer->client;
+    xcb_window_t win = frozen_pointer->window;
     xcb_rectangle_t rect = frozen_pointer->rectangle;
-    xcb_window_t win = c->window;
 
     x = y = 0;
     w = h = 1;
 
     delta_x = root_x - frozen_pointer->position.x;
     delta_y = root_y - frozen_pointer->position.y;
+    double sr;
+    xcb_query_pointer_reply_t *qpr;
+    xcb_window_t pwin;
+    window_location_t loc;
 
     switch (frozen_pointer->action) {
         case ACTION_MOVE:
@@ -387,6 +412,27 @@ void track_pointer(int root_x, int root_y)
             c->floating_rectangle = (xcb_rectangle_t) {x, y, width, height};
             window_draw_border(n, d->focus == n, mon == m);
             break;
+        case ACTION_RESIZE_TILED:
+            if (n->split_type == TYPE_VERTICAL)
+                sr = (double) (root_x - rect.x + window_gap / 2) / rect.width;
+            else
+                sr = (double) (root_y - rect.y + window_gap / 2) / rect.height;
+            sr = MAX(0, sr);
+            sr = MIN(1, sr);
+            n->split_ratio = sr;
+            arrange(mon, mon->desk);
+            break;
+        case ACTION_MOVE_TILED:
+            qpr = xcb_query_pointer_reply(dpy, xcb_query_pointer(dpy, root), NULL);
+            if (qpr != NULL) {
+                pwin = qpr->child;
+                free(qpr);
+                if (locate_window(pwin, &loc) && loc.monitor == m && loc.desktop == d && is_tiled(loc.node->client)) {
+                    swap_nodes(n, loc.node);
+                    arrange(m, d);
+                }
+            }
+            break;
         case ACTION_FOCUS:
         case ACTION_NONE:
             break;
@@ -400,8 +446,9 @@ void ungrab_pointer(void)
     if (frozen_pointer->action == ACTION_NONE)
         return;
 
-    update_floating_rectangle(frozen_pointer->node->client);
-    monitor_t *m = underlying_monitor(frozen_pointer->node->client);
+    if (is_floating(frozen_pointer->client))
+        update_floating_rectangle(frozen_pointer->client);
+    monitor_t *m = underlying_monitor(frozen_pointer->client);
     if (m != NULL && m != frozen_pointer->monitor) {
         transfer_node(frozen_pointer->monitor, frozen_pointer->desktop, m, m->desk, frozen_pointer->node);
         select_monitor(m);
index d9fe1daf07f1fe34b27b254b69219443d8df3cfe..cc5a3d363041748a59d3276ce4ae8352a1b4d31e 100644 (file)
--- a/helpers.h
+++ b/helpers.h
@@ -9,6 +9,7 @@
 #define LENGTH(x)         (sizeof(x) / sizeof(*x))
 #define MAX(A, B)         ((A) > (B) ? (A) : (B))
 #define MIN(A, B)         ((A) < (B) ? (A) : (B))
+#define ABS(A)            ((A) < 0 ? -(A) : (A))
 #define BOOLSTR(A)        ((A) ? "true" : "false")
 
 #define XCB_CONFIG_WINDOW_X_Y_WIDTH_HEIGHT XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT
index fab5fc9140238453d40d966a6631a5ad18e5203f..84c0f669048a3405fa1ae3d834f34d8849f8b6d1 100644 (file)
@@ -446,6 +446,8 @@ void set_setting(char *name, char *value, char *rsp)
     } else if (strcmp(name, "outer_border_width") == 0) {
         sscanf(value, "%u", &outer_border_width);
         border_width = inner_border_width + main_border_width + outer_border_width;
+    } else if (strcmp(name, "fence_grip") == 0) {
+        sscanf(value, "%u", &fence_grip);
     } else if (strcmp(name, "window_gap") == 0) {
         sscanf(value, "%i", &window_gap);
     } else if (strcmp(name, "left_padding") == 0) {
@@ -540,6 +542,8 @@ void get_setting(char *name, char* rsp)
         snprintf(rsp, BUFSIZ, "%u", outer_border_width);
     else if (strcmp(name, "border_width") == 0)
         snprintf(rsp, BUFSIZ, "%u", border_width);
+    else if (strcmp(name, "fence_grip") == 0)
+        snprintf(rsp, BUFSIZ, "%u", fence_grip);
     else if (strcmp(name, "window_gap") == 0)
         snprintf(rsp, BUFSIZ, "%i", window_gap);
     else if (strcmp(name, "left_padding") == 0)
@@ -756,11 +760,17 @@ bool parse_pointer_action(char *s, pointer_action_t *a)
     if (strcmp(s, "move") == 0) {
         *a = ACTION_MOVE;
         return true;
+    } else if (strcmp(s, "resize") == 0) {
+        *a = ACTION_RESIZE;
+        return true;
     } else if (strcmp(s, "focus") == 0) {
         *a = ACTION_FOCUS;
         return true;
-    } else if (strcmp(s, "resize") == 0) {
-        *a = ACTION_RESIZE;
+    } else if (strcmp(s, "move_tiled") == 0) {
+        *a = ACTION_MOVE_TILED;
+        return true;
+    } else if (strcmp(s, "resize_tiled") == 0) {
+        *a = ACTION_RESIZE_TILED;
         return true;
     }
     return false;
index 1f5c3adef24b5034d93cff76241f6f5e8eb2a658..658167605df47c896b9edb4f04a0dcca08bb1139 100644 (file)
@@ -62,6 +62,7 @@ void load_settings(void)
 
     border_width = inner_border_width + main_border_width + outer_border_width;
     window_gap = WINDOW_GAP;
+    fence_grip = FENCE_GRIP;
 
     borderless_monocle = BORDERLESS_MONOCLE;
     gapless_monocle = GAPLESS_MONOCLE;
index a2cddf9d4f1548ad6e7a4c040c6dc64d933bfed9..2b9f409baa121046a6171d38e16ffb3d826e8f82 100644 (file)
@@ -23,6 +23,7 @@
 
 #define WINDOW_GAP          6
 #define SPLIT_RATIO         0.5
+#define FENCE_GRIP          20
 
 #define BORDERLESS_MONOCLE     false
 #define GAPLESS_MONOCLE        false
@@ -58,6 +59,7 @@ unsigned int outer_border_width;
 unsigned int border_width;
 
 int window_gap;
+unsigned int fence_grip;
 
 bool borderless_monocle;
 bool gapless_monocle;
diff --git a/tree.c b/tree.c
index 09957231c5cb830dc36a225b211c918aeef6c488..6df52c832e068a2799b62b61a535b48cd09885bb 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -140,6 +140,40 @@ void move_fence(node_t *n, direction_t dir, fence_move_t mov)
         change_split_ratio(fence, CHANGE_DECREASE);
 }
 
+unsigned int distance_to_fence(xcb_point_t pt, node_t *fence)
+{
+    xcb_rectangle_t rect = fence->rectangle;
+    if (fence->split_type == TYPE_VERTICAL) {
+        int fx = rect.x + fence->split_ratio * rect.width - window_gap / 2;
+        return ABS(pt.x - fx);
+    } else {
+        int fy = rect.y + fence->split_ratio * rect.height - window_gap / 2;
+        return ABS(pt.y - fy);
+    }
+}
+
+fence_distance_t nearest_fence(xcb_point_t pt, node_t *tree)
+{
+    fence_distance_t fd;
+    if (tree == NULL || is_leaf(tree)) {
+        fd.fence = NULL;
+    } else {
+        fd.fence = tree;
+        fd.distance = distance_to_fence(pt, tree);
+        fence_distance_t first_fd = nearest_fence(pt, tree->first_child);
+        fence_distance_t second_fd = nearest_fence(pt, tree->second_child);
+        if (first_fd.fence != NULL && fd.distance > first_fd.distance) {
+            fd.fence = first_fd.fence;
+            fd.distance = first_fd.distance;
+        }
+        if (second_fd.fence != NULL && fd.distance > second_fd.distance) {
+            fd.fence = second_fd.fence;
+            fd.distance = second_fd.distance;
+        }
+    }
+    return fd;
+}
+
 void rotate_tree(node_t *n, rotate_t rot)
 {
     if (n == NULL || is_leaf(n))
diff --git a/tree.h b/tree.h
index ad076e6ad472bfa8a763ee231faeb8bc7175ac89..00486e6aa6572d21a5ebb010fab46b7516666da4 100644 (file)
--- a/tree.h
+++ b/tree.h
@@ -17,6 +17,8 @@ node_t *prev_leaf(node_t *);
 node_t *find_fence(node_t *, direction_t);
 node_t *find_neighbor(node_t *, direction_t);
 void move_fence(node_t *, direction_t, fence_move_t);
+unsigned int distance_to_fence(xcb_point_t, node_t *);
+fence_distance_t nearest_fence(xcb_point_t, node_t *);
 void rotate_tree(node_t *, rotate_t);
 void arrange(monitor_t *, desktop_t *);
 void apply_layout(monitor_t *, desktop_t *, node_t *, xcb_rectangle_t, xcb_rectangle_t);
diff --git a/types.c b/types.c
index c690842df23fcaea0442005cd5fb036174d7609b..20f43a1f0812109b6564fed5b8ebe07e3ea96e17 100644 (file)
--- a/types.c
+++ b/types.c
@@ -154,5 +154,10 @@ rule_t *make_rule(void)
 pointer_state_t *make_pointer_state(void)
 {
     pointer_state_t *p = malloc(sizeof(pointer_state_t));
+    p->monitor = NULL;
+    p->desktop = NULL;
+    p->node = NULL;
+    p->client = NULL;
+    p->window = XCB_NONE;
     return p;
 }
diff --git a/types.h b/types.h
index 199ef727267fca90b135e67330a03072c99db887..efc36a12a0790043442b22250bd198e01723bfc8 100644 (file)
--- a/types.h
+++ b/types.h
@@ -96,10 +96,12 @@ typedef enum {
 } corner_t;
 
 typedef enum {
+    ACTION_NONE,
     ACTION_MOVE,
     ACTION_RESIZE,
     ACTION_FOCUS,
-    ACTION_NONE
+    ACTION_MOVE_TILED,
+    ACTION_RESIZE_TILED
 } pointer_action_t;
 
 typedef struct {
@@ -193,9 +195,16 @@ typedef struct {
     monitor_t *monitor;
     desktop_t *desktop;
     node_t *node;
+    client_t *client;
+    xcb_window_t window;
     corner_t corner;
 } pointer_state_t;
 
+typedef struct {
+    node_t *fence;
+    unsigned int distance;
+} fence_distance_t;
+
 node_t *make_node(void);
 monitor_t *make_monitor(xcb_rectangle_t *);
 monitor_t *find_monitor(char *);