]> git.sur5r.net Git - i3/i3/blobdiff - src/floating.c
s/DLOG/LOG (Thanks ccount)
[i3/i3] / src / floating.c
index 70112b57051e48fd56495b2f863fa7a6e0f5f7c1..dd6c86e760f367b32cb04e002b26d374ab1ac448 100644 (file)
@@ -26,6 +26,7 @@
 #include "layout.h"
 #include "client.h"
 #include "floating.h"
+#include "workspace.h"
 
 /*
  * Toggles floating mode for the given client.
@@ -40,20 +41,26 @@ void toggle_floating_mode(xcb_connection_t *conn, Client *client, bool automatic
         Container *con = client->container;
         i3Font *font = load_font(conn, config.font);
 
+        if (client->dock) {
+                LOG("Not putting dock client into floating mode\n");
+                return;
+        }
+
         if (con == NULL) {
                 LOG("This client is already in floating (container == NULL), re-inserting\n");
                 Client *next_tiling;
-                SLIST_FOREACH(next_tiling, &(client->workspace->focus_stack), focus_clients)
+                Workspace *ws = client->workspace;
+                SLIST_FOREACH(next_tiling, &(ws->focus_stack), focus_clients)
                         if (!client_is_floating(next_tiling))
                                 break;
                 /* If there are no tiling clients on this workspace, there can only be one
                  * container: the first one */
-                if (next_tiling == TAILQ_END(&(client->workspace->focus_stack)))
-                        con = client->workspace->table[0][0];
+                if (next_tiling == TAILQ_END(&(ws->focus_stack)))
+                        con = ws->table[0][0];
                 else con = next_tiling->container;
 
                 /* Remove the client from the list of floating clients */
-                TAILQ_REMOVE(&(client->workspace->floating_clients), client, floating_clients);
+                TAILQ_REMOVE(&(ws->floating_clients), client, floating_clients);
 
                 LOG("destination container = %p\n", con);
                 Client *old_focused = con->currently_focused;
@@ -152,7 +159,6 @@ void floating_assign_to_workspace(Client *client, Workspace *new_workspace) {
         TAILQ_INSERT_TAIL(&(client->workspace->floating_clients), client, floating_clients);
         if (client->fullscreen)
                 client->workspace->fullscreen_client = client;
-
 }
 
 /*
@@ -255,10 +261,37 @@ void floating_drag_window(xcb_connection_t *conn, Client *client, xcb_button_pre
                 /* fake_absolute_configure_notify flushes */
         }
 
-
         drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, drag_window_callback);
 }
 
+/*
+ * Called when the user right-clicked on the titlebar of a floating window to
+ * resize it.
+ * Calls the drag_pointer function with the resize_window callback
+ *
+ */
+void floating_resize_window(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event) {
+        LOG("floating_resize_window\n");
+
+        void resize_window_callback(Rect *old_rect, uint32_t new_x, uint32_t new_y) {
+                int32_t new_width = old_rect->width + (new_x - event->root_x);
+                int32_t new_height = old_rect->height + (new_y - event->root_y);
+
+                /* Obey minimum window size and reposition the client */
+                if (new_width >= 50)
+                        client->rect.width = new_width;
+
+                if (new_height >= 20)
+                        client->rect.height = new_height;
+
+                /* resize_client flushes */
+                resize_client(conn, client);
+        }
+
+        drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, resize_window_callback);
+}
+
+
 /*
  * This function grabs your pointer and lets you drag stuff around (borders).
  * Every time you move your mouse, an XCB_MOTION_NOTIFY event will be received
@@ -315,8 +348,13 @@ void drag_pointer(xcb_connection_t *conn, Client *client, xcb_button_press_event
                                         /* motion_notify events are saved for later */
                                         FREE(last_motion_notify);
                                         last_motion_notify = inside_event;
-
                                         break;
+
+                                case XCB_UNMAP_NOTIFY:
+                                        LOG("Unmap-notify, aborting\n");
+                                        xcb_event_handle(&evenths, inside_event);
+                                        goto done;
+
                                 default:
                                         LOG("Passing to original handler\n");
                                         /* Use original handler */
@@ -373,28 +411,37 @@ void floating_focus_direction(xcb_connection_t *conn, Client *currently_focused,
 void floating_move(xcb_connection_t *conn, Client *currently_focused, direction_t direction) {
         LOG("floating move\n");
 
+        Rect destination = currently_focused->rect;
+        Rect *screen = &(currently_focused->workspace->screen->rect);
+
         switch (direction) {
                 case D_LEFT:
-                        if (currently_focused->rect.x < 10)
-                                return;
-                        currently_focused->rect.x -= 10;
+                        destination.x -= 10;
                         break;
                 case D_RIGHT:
-                        currently_focused->rect.x += 10;
+                        destination.x += 10;
                         break;
                 case D_UP:
-                        if (currently_focused->rect.y < 10)
-                                return;
-                        currently_focused->rect.y -= 10;
+                        destination.y -= 10;
                         break;
                 case D_DOWN:
-                        currently_focused->rect.y += 10;
+                        destination.y += 10;
                         break;
                 /* to make static analyzers happy */
                 default:
                         break;
         }
 
+        /* Prevent windows from vanishing completely */
+        if ((int32_t)(destination.x + destination.width - 5) <= (int32_t)screen->x ||
+            (int32_t)(destination.x + 5) >= (int32_t)(screen->x + screen->width) ||
+            (int32_t)(destination.y + destination.height - 5) <= (int32_t)screen->y ||
+            (int32_t)(destination.y + 5) >= (int32_t)(screen->y + screen->height)) {
+                LOG("boundary check failed, not moving\n");
+                return;
+        }
+
+        currently_focused->rect = destination;
         reposition_client(conn, currently_focused);
 
         /* Because reposition_client does not send a faked configure event (only resize does),
@@ -415,8 +462,8 @@ void floating_toggle_hide(xcb_connection_t *conn, Workspace *workspace) {
         LOG("floating_hidden is now: %d\n", workspace->floating_hidden);
         TAILQ_FOREACH(client, &(workspace->floating_clients), floating_clients) {
                 if (workspace->floating_hidden)
-                        xcb_unmap_window(conn, client->frame);
-                else xcb_map_window(conn, client->frame);
+                        client_unmap(conn, client);
+                else client_map(conn, client);
         }
 
         /* If we just unmapped all floating windows we should ensure that the focus