re-implement assigning windows to workspaces

This commit is contained in:
Michael Stapelberg 2011-05-02 23:29:26 +02:00
parent 7e51f626ef
commit 3d1acd6c2f
9 changed files with 84 additions and 49 deletions

View File

@ -34,6 +34,7 @@
#include "xcb_compat.h"
#endif
#include "data.h"
#include "util.h"
#include "ipc.h"
#include "tree.h"

View 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 {

View 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;

View 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

View 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)

View 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;

View 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);
} 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);
}
}
}

View 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;
}

View 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);