]> git.sur5r.net Git - i3/i3/commitdiff
Fix dragging floating containers / click handling
authorMichael Stapelberg <michael@stapelberg.de>
Fri, 31 Dec 2010 00:38:17 +0000 (01:38 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Fri, 31 Dec 2010 00:38:17 +0000 (01:38 +0100)
include/con.h
include/floating.h
src/click.c
src/con.c
src/floating.c

index 820d847d97d12642a31f50c772dc0051e7d3af73..1abc09a01bca0d36d0b7200e930ce70bee77af50 100644 (file)
@@ -54,6 +54,13 @@ Con *con_get_fullscreen_con(Con *con);
  */
 bool con_is_floating(Con *con);
 
+/**
+ * Checks if the given container is either floating or inside some floating
+ * container. It returns the FLOATING_CON container.
+ *
+ */
+Con *con_inside_floating(Con *con);
+
 /**
  * Returns the container with the given client window ID or NULL if no such
  * container exists.
index a312daee37a666ace59cebb4f5d3d7ea4b4e70e2..c3935252dc0d17f4ebe23ccdd21173cb25d5640a 100644 (file)
@@ -53,6 +53,12 @@ void floating_disable(Con *con, bool automatic);
  */
 void toggle_floating_mode(Con *con, bool automatic);
 
+/**
+ * Raises the given container in the list of floating containers
+ *
+ */
+void floating_raise_con(Con *con);
+
 #if 0
 /**
  * Removes the floating client from its workspace and attaches it to the new
index a4d9181aa826ae2b9cb92e2f834996776889421f..243820cb46875f806cdee6d992c716789e785ebd 100644 (file)
@@ -237,26 +237,47 @@ static bool floating_mod_on_tiled_client(xcb_connection_t *conn, Client *client,
 #endif
 
 int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_event_t *event) {
+    /* TODO: dragging floating windows by grabbing their decoration does not
+     * work right now. We need to somehow recognize that special case: either
+     * we check if the con with the clicked decoration is the only con inside
+     * its parent (so that you can only drag single floating windows, not
+     * floating containers with multiple windows) *or* we somehow find out
+     * which decoration(s) are at the top and enable grabbing for them while
+     * resizing for the others. Maybe we could process the resizing parameters
+     * first and check if resizing is possible: if yes, resize, if not, drag.
+     *
+     * Also raise on click on decoration is not working. */
     Con *con;
     DLOG("Button %d pressed on window 0x%08x\n", event->state, event->event);
 
     con = con_by_window_id(event->event);
-    bool border_click = false;
-    if (con == NULL) {
+    bool border_click = (con == NULL);
+    const uint32_t mod = config.floating_modifier;
+    bool mod_pressed = (mod != 0 && (event->state & mod) == mod);
+
+    if (border_click)
         con = con_by_frame_id(event->event);
-        border_click = true;
+
+    DLOG("border_click = %d, mod_pressed = %d\n", border_click, mod_pressed);
+
+    Con *clicked_into = NULL;
+
+    Con *child;
+    TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+        if (!rect_contains(child->deco_rect, event->event_x, event->event_y))
+            continue;
+
+        clicked_into = child;
+        break;
     }
-    DLOG("border_click = %d\n", border_click);
-        //if (con && con->type == CT_FLOATING_CON)
-                //con = TAILQ_FIRST(&(con->nodes_head));
+
+    DLOG("clicked_into = %p\n", clicked_into);
 
     /* See if this was a click with the configured modifier. If so, we need
      * to move around the client if it was floating. if not, we just process
      * as usual. */
     DLOG("state = %d, floating_modifier = %d\n", event->state, config.floating_modifier);
-    if (border_click ||
-        (config.floating_modifier != 0 &&
-         (event->state & config.floating_modifier) == config.floating_modifier)) {
+    if (border_click || mod_pressed) {
         if (con == NULL) {
             LOG("Not handling, floating_modifier was pressed and no client found\n");
             return 1;
@@ -268,11 +289,10 @@ int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_
                 return 1;
         }
 #endif
+        Con *floatingcon = con;
         if ((border_click && con->type == CT_FLOATING_CON) ||
-            (!border_click && con_is_floating(con))) {
-            /* floating operations are always on the container around
-             * the "payload container", so make sure we use the right one */
-            Con *floatingcon = (border_click ? con : con->parent);
+            ((floatingcon = con_inside_floating(con)) != NULL &&
+             clicked_into == NULL)) {
             LOG("button %d pressed\n", event->detail);
             if (event->detail == 1) {
                 LOG("left mouse button, dragging\n");
@@ -287,23 +307,23 @@ int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_
         }
     }
 
-    /* click to focus */
-    con_focus(con);
-
-    Con *clicked_into = NULL;
-
-    Con *child;
-    TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
-        if (!rect_contains(child->deco_rect, event->event_x, event->event_y))
-            continue;
+    /* click to focus, either on the clicked window or its child if thas was a
+     * click into a child decoration */
+    con_focus((clicked_into ? clicked_into : con));
 
-        clicked_into = child;
-        con_focus(child);
-        break;
-    }
+    /* for floating containers, we also want to raise them on click */
+    Con *floatingcon = con_inside_floating(con);
+    if (floatingcon != NULL)
+        floating_raise_con(floatingcon);
 
     tree_render();
 
+    /* if we clicked into a child decoration on a stacked/tabbed container, we
+     * are done and don’t want to resize */
+    if (clicked_into &&
+        (con->layout == L_STACKED || con->layout == L_TABBED))
+        return 1;
+
     /* check if this was a click on the window border (and on which one) */
     Rect bsr = con_border_style_rect(con);
     DLOG("BORDER x = %d, y = %d for con %p, window 0x%08x, border_click = %d, clicked_into = %p\n",
index dc8bc35432942eb4f7142759e3af002ac12ff6a5..0f2374f66975a97b588a83a2c2d87c034958a1d7 100644 (file)
--- a/src/con.c
+++ b/src/con.c
@@ -157,6 +157,7 @@ void con_detach(Con *con) {
  */
 void con_focus(Con *con) {
     assert(con != NULL);
+    DLOG("con_focus = %p\n", con);
 
     /* 1: set focused-pointer to the new con */
     /* 2: exchange the position of the container in focus stack of the parent all the way up */
@@ -170,6 +171,7 @@ void con_focus(Con *con) {
         con->urgent = false;
         workspace_update_urgent_flag(con_get_workspace(con));
     }
+    DLOG("con_focus done = %p\n", con);
 }
 
 /*
@@ -287,6 +289,25 @@ bool con_is_floating(Con *con) {
     return (con->floating >= FLOATING_AUTO_ON);
 }
 
+/*
+ * Checks if the given container is either floating or inside some floating
+ * container. It returns the FLOATING_CON container.
+ *
+ */
+Con *con_inside_floating(Con *con) {
+    assert(con != NULL);
+    if (con->type == CT_FLOATING_CON)
+        return con;
+
+    if (con->floating >= FLOATING_AUTO_ON)
+        return con->parent;
+
+    if (con->type == CT_WORKSPACE)
+        return NULL;
+
+    return con_inside_floating(con->parent);
+}
+
 /*
  * Returns the container with the given client window ID or NULL if no such
  * container exists.
index a88d498aadc90283d914e494b41e894878aaac80..c50cf49444792ad47f78c2e4090b657c907f6255 100644 (file)
@@ -172,6 +172,16 @@ void toggle_floating_mode(Con *con, bool automatic) {
     floating_enable(con, automatic);
 }
 
+/*
+ * Raises the given container in the list of floating containers
+ *
+ */
+void floating_raise_con(Con *con) {
+    DLOG("Raising floating con %p / %s\n", con, con->name);
+    TAILQ_REMOVE(&(con->parent->floating_head), con, floating_windows);
+    TAILQ_INSERT_TAIL(&(con->parent->floating_head), con, floating_windows);
+}
+
 DRAGGING_CB(drag_window_callback) {
     struct xcb_button_press_event_t *event = extra;