]> git.sur5r.net Git - i3/i3/commitdiff
re-implement assigning windows to workspaces
authorMichael Stapelberg <michael@stapelberg.de>
Mon, 2 May 2011 21:29:26 +0000 (23:29 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Mon, 2 May 2011 21:29:26 +0000 (23:29 +0200)
include/all.h
include/data.h
include/i3.h
include/match.h
src/cfgparse.l
src/cfgparse.y
src/manage.c
src/match.c
src/render.c

index 9d13bb956e6e8a6997aa0df2644ffdae6cc6a956..f9f12a70afc322d3137039953e37bfe5e89197c2 100644 (file)
@@ -34,6 +34,7 @@
 #include "xcb_compat.h"
 #endif
 
+#include "data.h"
 #include "util.h"
 #include "ipc.h"
 #include "tree.h"
index f20d764eb4db58a246509f70a398187bf3338aa4..d4836dfe62c02817578c66cb10ade09456fa0f86 100644 (file)
@@ -285,20 +285,21 @@ struct Match {
 
     enum { M_USER = 0, M_RESTART } source;
 
+    char *target_ws;
+
     /* Where the window looking for a match should be inserted:
      *
      * M_HERE   = the matched container will be replaced by the window
      *            (layout saving)
-     * M_ACTIVE = the window will be inserted next to the currently focused
-     *            container below the matched container
-     *            (assignments)
+     * M_ASSIGN_WS = the matched container will be inserted in the target_ws.
      * M_BELOW  = the window will be inserted as a child of the matched container
      *            (dockareas)
      *
      */
-    enum { M_HERE = 0, M_ACTIVE, M_BELOW } insert_where;
+    enum { M_HERE = 0, M_ASSIGN_WS, M_BELOW } insert_where;
 
     TAILQ_ENTRY(Match) matches;
+    TAILQ_ENTRY(Match) assignments;
 };
 
 struct Con {
index 060a0cf847838a444d7b78cb4f7e6bc7f4b29db7..2f18ce7062f74a3763fffad52c02f1ab145e7eb2 100644 (file)
@@ -26,7 +26,7 @@ extern Display *xlibdpy, *xkbdpy;
 extern int xkb_current_group;
 extern TAILQ_HEAD(bindings_head, Binding) *bindings;
 extern TAILQ_HEAD(autostarts_head, Autostart) autostarts;
-extern TAILQ_HEAD(assignments_head, Assignment) assignments;
+extern TAILQ_HEAD(assignments_head, Match) assignments;
 extern SLIST_HEAD(stack_wins_head, Stack_Window) stack_wins;
 extern uint8_t root_depth;
 extern bool xcursor_supported, xkb_supported;
index ef0251729a2675d1d4c4ae4e6b247bd95559512a..4f0e9bdc291f3f17df7d9f80dec5dbbf8f355a0f 100644 (file)
@@ -22,4 +22,10 @@ bool match_is_empty(Match *match);
  */
 bool match_matches_window(Match *match, i3Window *window);
 
+/**
+ * Returns the first match in 'assignments' that matches the given window.
+ *
+ */
+Match *match_by_assignment(i3Window *window);
+
 #endif
index c343aad661251b9f909e7fef1cb33f1c0cd0d595..1615288e93f2ec22415369757b8182ee66ec9c72 100644 (file)
@@ -11,7 +11,6 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
-#include "cfgparse.tab.h"
 #include <xcb/xcb.h>
 
 #include "data.h"
@@ -19,6 +18,8 @@
 #include "log.h"
 #include "util.h"
 
+#include "cfgparse.tab.h"
+
 int yycolumn = 1;
 
 #define YY_DECL int yylex (struct context *context)
index e8818b1f72f23b08f3cf3bf54ce6a68d4101dd4b..7ffab78d728a656acdeeff4688f36485d7684593 100644 (file)
@@ -192,7 +192,7 @@ void parse_file(const char *f) {
         char *string;
         uint32_t *single_color;
         struct Colortriple *color;
-        struct Assignment *assignment;
+        Match *match;
         struct Binding *binding;
 }
 
@@ -539,30 +539,40 @@ workspace_name:
 assign:
         TOKASSIGN WHITESPACE window_class WHITESPACE optional_arrow assign_target
         {
-#if 0
                 printf("assignment of %s\n", $<string>3);
 
-                struct Assignment *new = $<assignment>6;
-                printf("  to %d\n", new->workspace);
-                printf("  floating = %d\n", new->floating);
-                new->windowclass_title = $<string>3;
-                TAILQ_INSERT_TAIL(&assignments, new, assignments);
-#endif
+                struct Match *match = $<match>6;
+
+                char *separator = NULL;
+                if ((separator = strchr($<string>3, '/')) != NULL) {
+                        *(separator++) = '\0';
+                        match->title = sstrdup(separator);
+                }
+                if (*$<string>3 != '\0')
+                        match->class = sstrdup($<string>3);
+                free($<string>3);
+
+                printf("  class = %s\n", match->class);
+                printf("  title = %s\n", match->title);
+                if (match->insert_where == M_ASSIGN_WS)
+                        printf("  to ws %s\n", match->target_ws);
+                TAILQ_INSERT_TAIL(&assignments, match, assignments);
         }
         ;
 
 assign_target:
         NUMBER
         {
-#if 0
-                struct Assignment *new = scalloc(sizeof(struct Assignment));
-                new->workspace = $<number>1;
-                new->floating = ASSIGN_FLOATING_NO;
-                $<assignment>$ = new;
-#endif
+                /* TODO: named workspaces */
+                Match *match = smalloc(sizeof(Match));
+                match_init(match);
+                match->insert_where = M_ASSIGN_WS;
+                asprintf(&(match->target_ws), "%d", $<number>1);
+                $<match>$ = match;
         }
         | '~'
         {
+                /* TODO: compatiblity */
 #if 0
                 struct Assignment *new = scalloc(sizeof(struct Assignment));
                 new->floating = ASSIGN_FLOATING_ONLY;
@@ -571,6 +581,7 @@ assign_target:
         }
         | '~' NUMBER
         {
+                /* TODO: compatiblity */
 #if 0
                 struct Assignment *new = scalloc(sizeof(struct Assignment));
                 new->workspace = $<number>2;
index 98a34a154b590cc223c7286aeff7e065a10bc93f..b511189c0a1b36d4207949ef0770d6ac6724e52a 100644 (file)
@@ -203,38 +203,36 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
 
     DLOG("Initial geometry: (%d, %d, %d, %d)\n", geom->x, geom->y, geom->width, geom->height);
 
-    Con *nc;
+    Con *nc = NULL;
     Match *match;
 
-    /* TODO: assignments */
-    /* TODO: two matches for one container */
-
-    /* See if any container swallows this new window */
-    nc = con_for_window(search_at, cwindow, &match);
-    if (nc == NULL) {
-        if (focused->type == CT_CON && con_accepts_window(focused)) {
-            LOG("using current container, focused = %p, focused->name = %s\n",
-                            focused, focused->name);
-            nc = focused;
-        } else nc = tree_open_con(NULL);
+    /* check assignments first */
+    if ((match = match_by_assignment(cwindow))) {
+        DLOG("Assignment matches (%p)\n", match);
+        if (match->insert_where == M_ASSIGN_WS) {
+            nc = con_descend_focused(workspace_get(match->target_ws, NULL));
+            DLOG("focused on ws %s: %p / %s\n", match->target_ws, nc, nc->name);
+            if (nc->type == CT_WORKSPACE)
+                nc = tree_open_con(nc);
+            else nc = tree_open_con(nc->parent);
+        }
     } else {
-        /* M_ACTIVE are assignments */
-        if (match != NULL && match->insert_where == M_ACTIVE) {
-            /* We need to go down the focus stack starting from nc */
-            while (TAILQ_FIRST(&(nc->focus_head)) != TAILQ_END(&(nc->focus_head))) {
-                DLOG("walking down one step...\n");
-                nc = TAILQ_FIRST(&(nc->focus_head));
+        /* TODO: two matches for one container */
+
+        /* See if any container swallows this new window */
+        nc = con_for_window(search_at, cwindow, &match);
+        if (nc == NULL) {
+            if (focused->type == CT_CON && con_accepts_window(focused)) {
+                LOG("using current container, focused = %p, focused->name = %s\n",
+                                focused, focused->name);
+                nc = focused;
+            } else nc = tree_open_con(NULL);
+        } else {
+            /* M_BELOW inserts the new window as a child of the one which was
+             * matched (e.g. dock areas) */
+            if (match != NULL && match->insert_where == M_BELOW) {
+                nc = tree_open_con(nc);
             }
-            /* We need to open a new con */
-            /* TODO: make a difference between match-once containers (directly assign
-             * cwindow) and match-multiple (tree_open_con first) */
-            nc = tree_open_con(nc->parent);
-        }
-
-        /* M_BELOW inserts the new window as a child of the one which was
-         * matched (e.g. dock areas) */
-        else if (match != NULL && match->insert_where == M_BELOW) {
-            nc = tree_open_con(nc);
         }
     }
 
index da58047e0c419d088d7a3a3ecbaa8ee00c790ad3..9ed4d434f14e7c1e86983401531d3f2db8f39068 100644 (file)
@@ -2,7 +2,7 @@
  * 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)
  *
  * A "match" is a data structure which acts like a mask or expression to match
  * certain windows or not. For example, when using commands, you can specify a
@@ -82,3 +82,19 @@ bool match_matches_window(Match *match, i3Window *window) {
     return false;
 }
 
+/*
+ * Returns the first match in 'assignments' that matches the given window.
+ *
+ */
+Match *match_by_assignment(i3Window *window) {
+    Match *match;
+
+    TAILQ_FOREACH(match, &assignments, assignments) {
+        if (!match_matches_window(match, window))
+            continue;
+        DLOG("got a matching assignment (to %s)\n", match->target_ws);
+        return match;
+    }
+
+    return NULL;
+}
index 5bdc2e218519ed364b6295d1899c9b2011aea87d..a59d418b402b8f35e5afee1bc167c35b7c5023e9 100644 (file)
@@ -139,6 +139,7 @@ void render_con(Con *con, bool render_fullscreen) {
         if (!render_fullscreen)
             *inset = rect_add(*inset, con_border_style_rect(con));
 
+        DLOG("Starting with inset = (%d, %d) %d x %d\n", inset->x, inset->y, inset->width, inset->height);
         /* Obey x11 border */
         DLOG("X11 border: %d\n", con->border_width);
         inset->width -= (2 * con->border_width);