#define tag_foreach_flt(tag, dpy, flt, win) \
for (list_t *dpy = tag ->dpys; dpy; dpy = dpy->next) \
for (list_t *flt = DPY(dpy)->flts; flt; flt = flt->next) \
- for (win_t *win = FLT(flt)->win; win; win = NULL) \
+ for (win_t *win = FLT(flt)->win; win; win = NULL)
/* Window management data
* wm_* macros represent the currently focused item
/* Search for the target window in a given tag
* win may exist in other tags as well */
+static int search(tag_t *tag, win_t *target)
+{
+ tag_foreach_col(tag, dpy, col, row, win)
+ if (target == win)
+ return TILING;
+ tag_foreach_flt(tag, dpy, flt, win)
+ if (target == win)
+ return FLOATING;
+ return -1;
+}
+
static int searchl(tag_t *tag, win_t *target,
list_t **_dpy, list_t **_col, list_t **_row, list_t **_flt)
{
return -1;
}
-static int search(tag_t *tag, win_t *target,
+static int searchw(tag_t *tag, win_t *target,
dpy_t **_dpy, col_t **_col, row_t **_row, flt_t **_flt)
{
list_t *dpy, *col, *row, *flt;
static void set_mode(win_t *win, layout_t layout)
{
col_t *col;
- if (TILING != search(wm_tag, win, NULL, &col, NULL, NULL))
+ if (TILING != searchw(wm_tag, win, NULL, &col, NULL, NULL))
return;
printf("set_mode: %p, %d -> %d\n",
col, col->layout, layout);
}
dpy_t *dpy; col_t *col; row_t *row; flt_t *flt;
- switch (search(wm_tag, win, &dpy, &col, &row, &flt)) {
+ switch (searchw(wm_tag, win, &dpy, &col, &row, &flt)) {
case TILING:
wm_dpy = dpy;
wm_col = col;
/* Search for a tag
* If it does not exist it is based on the
* display geometry in wm->screens */
-static tag_t *tag_find(const char *name)
+static tag_t *tag_find(const char *name, int create)
{
tag_t *tag = NULL;
for (list_t *cur = wm->tags; cur; cur = cur->next)
tag = cur->data;
break;
}
- if (!tag) {
+ if (!tag && create) {
tag = tag_new(wm->screens, name);
wm->tags = list_append(wm->tags, tag);
}
return tag;
}
+/* Compute the number of windows in a tag */
+static int tag_size(tag_t *tag)
+{
+ int count = 0;
+ tag_foreach_col(tag, dpy, col, row, win)
+ count++;
+ tag_foreach_flt(tag, dpy, flt, win)
+ count++;
+ return count;
+}
+
+/* Remove a tag if it contains no windows */
+static void tag_prune(tag_t *tag)
+{
+ if (tag == wm_tag || tag_size(tag) >= 1)
+ return;
+ while (tag->dpys) {
+ dpy_t *dpy = tag->dpys->data;
+ while (dpy->cols)
+ dpy->cols = list_remove(dpy->cols, dpy->cols, 1);
+ tag->dpys = list_remove(tag->dpys, tag->dpys, 1);
+ }
+ list_t *ltag = list_find(wm->tags, tag);
+ wm->tags = list_remove(wm->tags, ltag, 1);
+}
+
/* Move the window from the current tag to the new tag
* Unlike wmii, only remove the current tag, not all tags */
-static void tag_set(win_t *win, const char *name)
+static void tag_set(win_t *win, const char *name, int toggle)
{
- printf("tag_set: %p %s\n", win, name);
- if (!strcmp(wm_tag->name, name))
- return;
- tag_t *tag = tag_find(name);
- layer_t layer = cut_win(win, wm_tag);
- put_win(win, tag, layer);
- set_focus(wm_focus);
+ tag_t *tag = tag_find(name, 1);
+
+ int src_layer = search(wm_tag, win);
+ int dst_layer = search(tag, win);
+
+ int count = 0;
+ if (toggle && dst_layer >= 0)
+ for (list_t *tag = wm->tags; tag; tag = tag->next)
+ if (search(TAG(tag), win) >= 0)
+ count++;
+
+ printf("tag_set: %p %s -- %s layer=%d:%d count=%d\n",
+ win, name, toggle ? "toggle" : "change",
+ src_layer, dst_layer, count);
+
+ if (toggle) {
+ if (dst_layer < 0)
+ put_win(win, tag, src_layer);
+ else if (count >= 2)
+ cut_win(win, tag);
+ if (tag == wm_tag)
+ wm_update();
+ else
+ tag_prune(tag);
+ } else {
+ if (tag != wm_tag)
+ cut_win(win, wm_tag);
+ if (dst_layer < 0)
+ put_win(win, tag, src_layer);
+ if (tag != wm_tag)
+ wm_update();
+ }
}
/* Switch to a different tag */
static void tag_switch(const char *name)
{
printf("tag_switch: %s\n", name);
- tag_t *old = wm_tag;
- if ((wm_col == NULL || wm_row == NULL) && wm_flt == NULL) {
- while (old->dpys) {
- dpy_t *dpy = old->dpys->data;
- while (dpy->cols)
- dpy->cols = list_remove(dpy->cols, dpy->cols, 1);
- old->dpys = list_remove(old->dpys, old->dpys, 1);
- }
- list_t *ltag = list_find(wm->tags, old);
- wm->tags = list_remove(wm->tags, ltag, 1);
- }
- wm_tag = tag_find(name);
+ tag_t *tag = tag_find(name, 1);
+ if (tag == wm_tag)
+ return;
+ tag_prune(wm_tag);
+ wm_tag = tag;
+ wm_update();
}
/* Tile all windows in the given display
for (list_t *tag = wm ->tags; tag; tag = tag->next)
if (tag->data != wm_tag) {
tag_foreach_col(TAG(tag), dpy, col, row, win)
- sys_show(win, ST_HIDE);
+ if (search(wm_tag, win) < 0)
+ sys_show(win, ST_HIDE);
tag_foreach_flt(TAG(tag), dpy, flt, win)
- sys_show(win, ST_HIDE);
+ if (search(wm_tag, win) < 0)
+ sys_show(win, ST_HIDE);
}
/* Set focused window */
/* Tag switching */
if (mod.MODKEY && '0' <= ev && ev <= '9') {
char name[] = {ev, '\0'};
- if (win && mod.shift)
- tag_set(win, name);
- if (!mod.shift)
- tag_switch(name);
- wm_update();
+ if (!mod.shift && !mod.ctrl) tag_switch(name);
+ if ( mod.shift && !mod.ctrl && win) tag_set(win, name, 0);
+ if (!mod.shift && mod.ctrl && win) tag_set(win, name, 1);
}
/* Focus change */
printf("wm_handle_state - %p %x -> %x\n", win, prev, next);
- search(wm_tag, win, NULL, NULL, &row, &flt);
+ searchw(wm_tag, win, NULL, NULL, &row, &flt);
if (!row && !flt && next == ST_SHOW)
return wm_insert(win), 1;
wm->tags = list_insert(NULL, wm->tag);
event_t ev_e[] = {EV_ENTER, EV_FOCUS};
+ event_t ev_c[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
event_t ev_s[] = {'h', 'j', 'k', 'l', 'c', 'q', ' ',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
EV_MOUSE1, EV_MOUSE3};
sys_watch(NULL, ev_e[i], MOD());
for (int i = 0; i < countof(ev_m); i++)
sys_watch(NULL, ev_m[i], MOD(.MODKEY=1));
+ for (int i = 0; i < countof(ev_c); i++)
+ sys_watch(NULL, ev_c[i], MOD(.MODKEY=1,.ctrl=1));
for (int i = 0; i < countof(ev_s); i++)
sys_watch(NULL, ev_s[i], MOD(.MODKEY=1,.shift=1));
}