]> git.sur5r.net Git - i3/i3/blobdiff - src/con.c
Merge branch 'master' into next
[i3/i3] / src / con.c
index d5346c41ba40467060302384b93d043afcd0865b..7b5cc499468e5594f463a726b3a4864ee832e281 100644 (file)
--- a/src/con.c
+++ b/src/con.c
@@ -2,11 +2,11 @@
  * vim:ts=4:sw=4:expandtab
  *
  * i3 - an improved dynamic tiling window manager
- * © 2009-2010 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
  *
- * con.c contains all functions which deal with containers directly (creating
- * containers, searching containers, getting specific properties from
- * containers, …).
+ * con.c: Functions which deal with containers directly (creating containers,
+ *        searching containers, getting specific properties from containers,
+ *        …).
  *
  */
 #include "all.h"
@@ -129,7 +129,9 @@ void con_attach(Con *con, Con *parent, bool ignore_focus) {
          * workspace or a new split container with the configured
          * workspace_layout).
          */
-        if (con->window != NULL && parent->type == CT_WORKSPACE) {
+        if (con->window != NULL &&
+            parent->type == CT_WORKSPACE &&
+            config.default_layout != L_DEFAULT) {
             DLOG("Parent is a workspace. Applying default layout...\n");
             Con *target = workspace_attach_to(parent);
 
@@ -193,7 +195,6 @@ void con_focus(Con *con) {
         con->urgent = false;
         workspace_update_urgent_flag(con_get_workspace(con));
     }
-    DLOG("con_focus done = %p\n", con);
 }
 
 /*
@@ -404,8 +405,8 @@ Con *con_by_frame_id(xcb_window_t frame) {
 Con *con_for_window(Con *con, i3Window *window, Match **store_match) {
     Con *child;
     Match *match;
-    DLOG("searching con for window %p starting at con %p\n", window, con);
-    DLOG("class == %s\n", window->class_class);
+    //DLOG("searching con for window %p starting at con %p\n", window, con);
+    //DLOG("class == %s\n", window->class_class);
 
     TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
         TAILQ_FOREACH(match, &(child->swallow_head), matches) {
@@ -613,17 +614,26 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool
          * to the coordinate space of the correct output */
         if (fix_coordinates && con->type == CT_FLOATING_CON) {
             DLOG("Floating window, fixing coordinates\n");
+            /* First we get the x/y coordinates relative to the x/y coordinates
+             * of the output on which the window is on */
             uint32_t rel_x = (con->rect.x - source_output->rect.x);
             uint32_t rel_y = (con->rect.y - source_output->rect.y);
-            con->rect.x = dest_output->rect.x + rel_x;
-            con->rect.y = dest_output->rect.y + rel_y;
+            /* Then we calculate a fraction, for example 0.63 for a window
+             * which is at y = 1212 of a 1920 px high output */
+            double fraction_x = ((double)rel_x / source_output->rect.width);
+            double fraction_y = ((double)rel_y / source_output->rect.height);
+            DLOG("rel_x = %d, rel_y = %d, fraction_x = %f, fraction_y = %f, output->w = %d, output->h = %d\n",
+                 rel_x, rel_y, fraction_x, fraction_y, source_output->rect.width, source_output->rect.height);
+            con->rect.x = dest_output->rect.x + (fraction_x * dest_output->rect.width);
+            con->rect.y = dest_output->rect.y + (fraction_y * dest_output->rect.height);
+            DLOG("Resulting coordinates: x = %d, y = %d\n", con->rect.x, con->rect.y);
         } else DLOG("Not fixing coordinates, fix_coordinates flag = %d\n", fix_coordinates);
 
         /* If moving to a visible workspace, call show so it can be considered
          * focused. Must do before attaching because workspace_show checks to see
          * if focused container is in its area. */
         if (workspace_is_visible(workspace)) {
-            workspace_show(workspace->name);
+            workspace_show(workspace);
 
             /* Don’t warp if told so (when dragging floating windows with the
              * mouse for example) */
@@ -659,7 +669,7 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool
         /* Descend focus stack in case focus_next is a workspace which can
          * occur if we move to the same workspace.  Also show current workspace
          * to ensure it is focused. */
-        workspace_show(con_get_workspace(focus_next)->name);
+        workspace_show(con_get_workspace(focus_next));
         con_focus(con_descend_focused(focus_next));
     }
 
@@ -835,15 +845,16 @@ Con *con_descend_tiling_focused(Con *con) {
  */
 Con *con_descend_direction(Con *con, direction_t direction) {
     Con *most = NULL;
-    DLOG("con_descend_direction(%p, %d)\n", con, direction);
+    int orientation = con_orientation(con);
+    DLOG("con_descend_direction(%p, orientation %d, direction %d)\n", con, orientation, direction);
     if (direction == D_LEFT || direction == D_RIGHT) {
-        if (con->orientation == HORIZ) {
+        if (orientation == HORIZ) {
             /* If the direction is horizontal, we can use either the first
              * (D_RIGHT) or the last con (D_LEFT) */
             if (direction == D_RIGHT)
                 most = TAILQ_FIRST(&(con->nodes_head));
             else most = TAILQ_LAST(&(con->nodes_head), nodes_head);
-        } else if (con->orientation == VERT) {
+        } else if (orientation == VERT) {
             /* Wrong orientation. We use the last focused con. Within that con,
              * we recurse to chose the left/right con or at least the last
              * focused one. */
@@ -856,13 +867,13 @@ Con *con_descend_direction(Con *con, direction_t direction) {
     }
 
     if (direction == D_UP || direction == D_DOWN) {
-        if (con->orientation == VERT) {
+        if (orientation == VERT) {
             /* If the direction is vertical, we can use either the first
              * (D_DOWN) or the last con (D_UP) */
             if (direction == D_UP)
                 most = TAILQ_LAST(&(con->nodes_head), nodes_head);
             else most = TAILQ_FIRST(&(con->nodes_head));
-        } else if (con->orientation == HORIZ) {
+        } else if (orientation == HORIZ) {
             /* Wrong orientation. We use the last focused con. Within that con,
              * we recurse to chose the top/bottom con or at least the last
              * focused one. */
@@ -930,6 +941,49 @@ int con_border_style(Con *con) {
     return con->border_style;
 }
 
+/*
+ * Sets the given border style on con, correctly keeping the position/size of a
+ * floating window.
+ *
+ */
+void con_set_border_style(Con *con, int border_style) {
+    /* Handle the simple case: non-floating containerns */
+    if (!con_is_floating(con)) {
+        con->border_style = border_style;
+        return;
+    }
+
+    /* For floating containers, we want to keep the position/size of the
+     * *window* itself. We first add the border pixels to con->rect to make
+     * con->rect represent the absolute position of the window. Then, we change
+     * the border and subtract the new border pixels. Afterwards, we update
+     * parent->rect to contain con. */
+    DLOG("This is a floating container\n");
+
+    Rect bsr = con_border_style_rect(con);
+    con->rect.x += bsr.x;
+    con->rect.y += bsr.y;
+    con->rect.width += bsr.width;
+    con->rect.height += bsr.height;
+
+    /* Change the border style, get new border/decoration values. */
+    con->border_style = border_style;
+    bsr = con_border_style_rect(con);
+    int deco_height =
+        (con->border_style == BS_NORMAL ? config.font.height + 5 : 0);
+
+    con->rect.x -= bsr.x;
+    con->rect.y -= bsr.y;
+    con->rect.width -= bsr.width;
+    con->rect.height -= bsr.height;
+
+    Con *parent = con->parent;
+    parent->rect.x = con->rect.x;
+    parent->rect.y = con->rect.y - deco_height;
+    parent->rect.width = con->rect.width;
+    parent->rect.height = con->rect.height + deco_height;
+}
+
 /*
  * This function changes the layout of a given container. Use it to handle
  * special cases like changing a whole workspace to stacked/tabbed (creates a
@@ -998,20 +1052,29 @@ static void con_on_remove_child(Con *con) {
 
     /* Every container 'above' (in the hierarchy) the workspace content should
      * not be closed when the last child was removed */
-    if (con->type == CT_WORKSPACE ||
-        con->type == CT_OUTPUT ||
+    if (con->type == CT_OUTPUT ||
         con->type == CT_ROOT ||
         con->type == CT_DOCKAREA) {
         DLOG("not handling, type = %d\n", con->type);
         return;
     }
 
+    /* For workspaces, close them only if they're not visible anymore */
+    if (con->type == CT_WORKSPACE) {
+        if (TAILQ_EMPTY(&(con->focus_head)) && !workspace_is_visible(con)) {
+            LOG("Closing old workspace (%p / %s), it is empty\n", con, con->name);
+            tree_close(con, DONT_KILL_WINDOW, false, false);
+            ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"empty\"}");
+        }
+        return;
+    }
+
     /* TODO: check if this container would swallow any other client and
      * don’t close it automatically. */
     int children = con_num_children(con);
     if (children == 0) {
         DLOG("Container empty, closing\n");
-        tree_close(con, DONT_KILL_WINDOW, false);
+        tree_close(con, DONT_KILL_WINDOW, false, false);
         return;
     }
 }