diff --git a/include/all.h b/include/all.h index 9d13bb95..f9f12a70 100644 --- a/include/all.h +++ b/include/all.h @@ -34,6 +34,7 @@ #include "xcb_compat.h" #endif +#include "data.h" #include "util.h" #include "ipc.h" #include "tree.h" diff --git a/include/data.h b/include/data.h index f20d764e..d4836dfe 100644 --- a/include/data.h +++ b/include/data.h @@ -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 { diff --git a/include/i3.h b/include/i3.h index 060a0cf8..2f18ce70 100644 --- a/include/i3.h +++ b/include/i3.h @@ -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; diff --git a/include/match.h b/include/match.h index ef025172..4f0e9bdc 100644 --- a/include/match.h +++ b/include/match.h @@ -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 diff --git a/src/cfgparse.l b/src/cfgparse.l index c343aad6..1615288e 100644 --- a/src/cfgparse.l +++ b/src/cfgparse.l @@ -11,7 +11,6 @@ #include #include #include -#include "cfgparse.tab.h" #include #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) diff --git a/src/cfgparse.y b/src/cfgparse.y index e8818b1f..7ffab78d 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -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", $3); - struct Assignment *new = $6; - printf(" to %d\n", new->workspace); - printf(" floating = %d\n", new->floating); - new->windowclass_title = $3; - TAILQ_INSERT_TAIL(&assignments, new, assignments); -#endif + struct Match *match = $6; + + char *separator = NULL; + if ((separator = strchr($3, '/')) != NULL) { + *(separator++) = '\0'; + match->title = sstrdup(separator); + } + if (*$3 != '\0') + match->class = sstrdup($3); + free($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 = $1; - new->floating = ASSIGN_FLOATING_NO; - $$ = new; -#endif + /* TODO: named workspaces */ + Match *match = smalloc(sizeof(Match)); + match_init(match); + match->insert_where = M_ASSIGN_WS; + asprintf(&(match->target_ws), "%d", $1); + $$ = 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 = $2; diff --git a/src/manage.c b/src/manage.c index 98a34a15..b511189c 100644 --- a/src/manage.c +++ b/src/manage.c @@ -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); - } 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)); - } - /* 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); + /* 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 { + /* TODO: two matches for one container */ - /* 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); + /* 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); + } } } diff --git a/src/match.c b/src/match.c index da58047e..9ed4d434 100644 --- a/src/match.c +++ b/src/match.c @@ -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; +} diff --git a/src/render.c b/src/render.c index 5bdc2e21..a59d418b 100644 --- a/src/render.c +++ b/src/render.c @@ -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);