]> git.sur5r.net Git - i3/i3/commitdiff
Floating resize uses arbitrary corners
authorAxel Wagner <mail@merovius.de>
Fri, 12 Mar 2010 00:31:48 +0000 (01:31 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Fri, 12 Mar 2010 02:11:20 +0000 (03:11 +0100)
This closes ticket #121

include/floating.h
src/floating.c

index d4942e5681fc116a4089e6140f8a71511ec751b7..d368048bcf6750ff5ce0528cc11e68ec8f34d48a 100644 (file)
@@ -21,7 +21,10 @@ typedef void(*callback_t)(xcb_connection_t*, Client*, Rect*, uint32_t, uint32_t,
                          void *extra)
 
 /** On which border was the dragging initiated? */
-typedef enum { BORDER_LEFT, BORDER_RIGHT, BORDER_TOP, BORDER_BOTTOM} border_t;
+typedef enum { BORDER_LEFT   = (1 << 0),
+               BORDER_RIGHT  = (1 << 1),
+               BORDER_TOP    = (1 << 2),
+               BORDER_BOTTOM = (1 << 3)} border_t;
 
 /**
  * Enters floating mode for the given client.  Correctly takes care of the
index 9a94e409d08e215bd68ca58481702ce062393499..0d97c27a6247384d6d029edbc9022ed1c33eaf68 100644 (file)
@@ -169,13 +169,13 @@ void floating_assign_to_workspace(Client *client, Workspace *new_workspace) {
  * extension and only on Mac OS X systems at the moment).
  *
  */
-struct callback_params {
+struct resize_callback_params {
         border_t border;
         xcb_button_press_event_t *event;
 };
 
 DRAGGING_CB(resize_callback) {
-        struct callback_params *params = extra;
+        struct resize_callback_params *params = extra;
         xcb_button_press_event_t *event = params->event;
         switch (params->border) {
                 case BORDER_RIGHT: {
@@ -251,7 +251,7 @@ int floating_border_click(xcb_connection_t *conn, Client *client, xcb_button_pre
 
         DLOG("border = %d\n", border);
 
-        struct callback_params params = { border, event };
+        struct resize_callback_params params = { border, event };
 
         drag_pointer(conn, client, event, XCB_NONE, border, resize_callback, &params);
 
@@ -282,17 +282,49 @@ void floating_drag_window(xcb_connection_t *conn, Client *client, xcb_button_pre
         drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, drag_window_callback, event);
 }
 
+/*
+ * This is an ugly data structure which we need because there is no standard
+ * way of having nested functions (only available as a gcc extension at the
+ * moment, clang doesn’t support it) or blocks (only available as a clang
+ * extension and only on Mac OS X systems at the moment).
+ *
+ */
+struct resize_window_callback_params {
+        border_t corner;
+        xcb_button_press_event_t *event;
+};
+
 DRAGGING_CB(resize_window_callback) {
-        xcb_button_press_event_t *event = extra;
-        int32_t new_width = old_rect->width + (new_x - event->root_x);
-        int32_t new_height = old_rect->height + (new_y - event->root_y);
+        struct resize_window_callback_params *params = extra;
+        xcb_button_press_event_t *event = params->event;
+        border_t corner = params->corner;
+
+        int32_t dest_x = client->rect.x;
+        int32_t dest_y = client->rect.y;
+        uint32_t dest_width;
+        uint32_t dest_height;
+
+        if (corner & BORDER_LEFT) {
+                dest_x = old_rect->x + (new_x - event->root_x);
+                dest_width = old_rect->width - (new_x - event->root_x);
+        } else dest_width = old_rect->width + (new_x - event->root_x);
+
+        if (corner & BORDER_TOP) {
+                dest_y = old_rect->y + (new_y - event->root_y);
+                dest_height = old_rect->height - (new_y - event->root_y);
+        } else dest_height = old_rect->height + (new_y - event->root_y);
+
 
         /* Obey minimum window size and reposition the client */
-        if (new_width > 0 && new_width >= client_min_width(client))
-                client->rect.width = new_width;
+        if (dest_width > 0 && dest_width >= client_min_width(client)) {
+                client->rect.x = dest_x;
+                client->rect.width = dest_width;
+        }
 
-        if (new_height > 0 && new_height >= client_min_height(client))
-                client->rect.height = new_height;
+        if (dest_height > 0 && dest_height >= client_min_height(client)) {
+                client->rect.y = dest_y;
+                client->rect.height = dest_height;
+        }
 
         /* resize_client flushes */
         resize_client(conn, client);
@@ -307,7 +339,21 @@ DRAGGING_CB(resize_window_callback) {
 void floating_resize_window(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event) {
         DLOG("floating_resize_window\n");
 
-        drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, resize_window_callback, event);
+        /* corner saves the nearest corner to the original click. It contains
+         * a bitmask of the nearest borders (BORDER_LEFT, BORDER_RIGHT, …) */
+        border_t corner = 0;
+
+        if (event->event_x <= (client->rect.width / 2))
+                corner |= BORDER_LEFT;
+        else corner |= BORDER_RIGHT;
+
+        if (event->event_y <= (client->rect.height / 2))
+                corner |= BORDER_TOP;
+        else corner |= BORDER_RIGHT;
+
+        struct resize_window_callback_params params = { corner, event };
+
+        drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, resize_window_callback, &params);
 }