+/* Raise the window in the floating */
+static void raise_float(win_t *win)
+{
+ printf("raise_float: %p\n", win);
+ list_t *cur;
+ for (cur = wm_dpy->flts; cur; cur = cur->next)
+ if (FLT(cur)->win == win)
+ break;
+ if (cur) {
+ flt_t *flt = cur->data;
+ wm_dpy->flts = list_remove(wm_dpy->flts, cur, 0);
+ wm_dpy->flts = list_append(wm_dpy->flts, flt);
+ sys_raise(win);
+ }
+}
+
+/* Toggle between floating and tiling layers */
+static void switch_layer(void)
+{
+ printf("switch_float: %p %d\n",
+ wm_dpy, wm_dpy->layer);
+ wm_dpy->layer = !wm_dpy->layer;
+ wm_update();
+}
+
+/* Move current window between floating and tiling layers */
+static void set_layer(win_t *win)
+{
+ if (!win) return;
+ printf("set_float: %p %p\n", wm_dpy, win);
+ wm_dpy->layer = !cut_win(win, wm_tag);
+ put_win(win, wm_tag, wm_dpy->layer);
+ wm_update();
+}
+
+/* Allocate a new tag */
+static tag_t *tag_new(list_t *screens, const char *name)
+{
+ tag_t *tag = new0(tag_t);
+ strncpy(tag->name, name, sizeof(tag->name));
+ for (list_t *cur = screens; cur; cur = cur->next) {
+ dpy_t *dpy = new0(dpy_t);
+ dpy->geom = cur->data;
+ tag->dpys = list_append(tag->dpys, dpy);
+ }
+ tag->dpy = tag->dpys->data;
+ for (list_t *dpy = tag->dpys; dpy; dpy = dpy->next)
+ if (DPY(dpy)->geom->z > tag->dpy->geom->z)
+ tag->dpy = dpy->data;
+ return tag;
+}
+
+/* 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, int create)
+{
+ tag_t *tag = NULL;
+ for (list_t *cur = wm->tags; cur; cur = cur->next)
+ if (!strcmp(name, TAG(cur)->name)) {
+ tag = cur->data;
+ break;
+ }
+ 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, int toggle)
+{
+ 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 *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
+ * This performs all the actual window tiling
+ * Currently supports split, stack and maximized modes */
+static void wm_update_cols(dpy_t *dpy)