From 54bbd88e5108cc44822763038bb9bebb4cf4dcbb Mon Sep 17 00:00:00 2001 From: okan Date: Thu, 20 Aug 2015 14:45:15 +0000 Subject: [PATCH 01/21] Alter big move and resize bindings to match what's in cwm(1); functionally the same, but re-binding should be based on default bindings. Matches other similiar bindings. Discovered by a portable user. --- conf.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/conf.c b/conf.c index 38c8c8c..1ba2c54 100644 --- a/conf.c +++ b/conf.c @@ -224,18 +224,18 @@ static const struct { { "M-j", "movedown" }, { "M-k", "moveup" }, { "M-l", "moveright" }, - { "M-H", "bigmoveleft" }, - { "M-J", "bigmovedown" }, - { "M-K", "bigmoveup" }, - { "M-L", "bigmoveright" }, + { "MS-h", "bigmoveleft" }, + { "MS-j", "bigmovedown" }, + { "MS-k", "bigmoveup" }, + { "MS-l", "bigmoveright" }, { "CM-h", "resizeleft" }, { "CM-j", "resizedown" }, { "CM-k", "resizeup" }, { "CM-l", "resizeright" }, - { "CM-H", "bigresizeleft" }, - { "CM-J", "bigresizedown" }, - { "CM-K", "bigresizeup" }, - { "CM-L", "bigresizeright" }, + { "CMS-h", "bigresizeleft" }, + { "CMS-j", "bigresizedown" }, + { "CMS-k", "bigresizeup" }, + { "CMS-l", "bigresizeright" }, { "C-Left", "ptrmoveleft" }, { "C-Down", "ptrmovedown" }, { "C-Up", "ptrmoveup" }, From 871c9f24ba413a7c528ddff2d5c4c8f1601364f3 Mon Sep 17 00:00:00 2001 From: okan Date: Fri, 21 Aug 2015 15:52:49 +0000 Subject: [PATCH 02/21] Bring group and client cycle closer together. --- client.c | 22 +++++++++++----------- group.c | 54 ++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/client.c b/client.c index cbf2cb2..f75a804 100644 --- a/client.c +++ b/client.c @@ -647,7 +647,7 @@ match: void client_cycle(struct screen_ctx *sc, int flags) { - struct client_ctx *oldcc, *newcc; + struct client_ctx *newcc, *oldcc; int again = 1; if (TAILQ_EMPTY(&sc->clientq)) @@ -655,16 +655,16 @@ client_cycle(struct screen_ctx *sc, int flags) oldcc = client_current(); if (oldcc == NULL) - oldcc = ((flags & CWM_RCYCLE) ? + oldcc = (flags & CWM_RCYCLE) ? TAILQ_LAST(&sc->clientq, client_ctx_q) : - TAILQ_FIRST(&sc->clientq)); + TAILQ_FIRST(&sc->clientq); newcc = oldcc; while (again) { again = 0; - newcc = ((flags & CWM_RCYCLE) ? client_prev(newcc) : - client_next(newcc)); + newcc = (flags & CWM_RCYCLE) ? client_prev(newcc) : + client_next(newcc); /* Only cycle visible and non-ignored windows. */ if ((newcc->flags & (CLIENT_HIDDEN|CLIENT_IGNORE)) @@ -705,20 +705,20 @@ static struct client_ctx * client_next(struct client_ctx *cc) { struct screen_ctx *sc = cc->sc; - struct client_ctx *ccc; + struct client_ctx *newcc; - return(((ccc = TAILQ_NEXT(cc, entry)) != NULL) ? - ccc : TAILQ_FIRST(&sc->clientq)); + return(((newcc = TAILQ_NEXT(cc, entry)) != NULL) ? + newcc : TAILQ_FIRST(&sc->clientq)); } static struct client_ctx * client_prev(struct client_ctx *cc) { struct screen_ctx *sc = cc->sc; - struct client_ctx *ccc; + struct client_ctx *newcc; - return(((ccc = TAILQ_PREV(cc, client_ctx_q, entry)) != NULL) ? - ccc : TAILQ_LAST(&sc->clientq, client_ctx_q)); + return(((newcc = TAILQ_PREV(cc, client_ctx_q, entry)) != NULL) ? + newcc : TAILQ_LAST(&sc->clientq, client_ctx_q)); } static void diff --git a/group.c b/group.c index 1bf2fd7..bbcd6cf 100644 --- a/group.c +++ b/group.c @@ -32,6 +32,8 @@ #include "calmwm.h" +static struct group_ctx *group_next(struct group_ctx *); +static struct group_ctx *group_prev(struct group_ctx *); static void group_assign(struct group_ctx *, struct client_ctx *); static void group_restack(struct group_ctx *); static void group_setactive(struct group_ctx *); @@ -255,36 +257,28 @@ group_only(struct screen_ctx *sc, int idx) } } -/* - * Cycle through active groups. If none exist, then just stay put. - */ void group_cycle(struct screen_ctx *sc, int flags) { - struct group_ctx *gc, *showgroup = NULL; + struct group_ctx *newgc, *oldgc, *showgroup = NULL; - if (((gc = sc->group_active)) == NULL) - errx(1, "group_cycle: no active group"); + oldgc = sc->group_active; + newgc = oldgc; for (;;) { - gc = (flags & CWM_RCYCLE) ? TAILQ_PREV(gc, group_ctx_q, - entry) : TAILQ_NEXT(gc, entry); - if (gc == NULL) - gc = (flags & CWM_RCYCLE) ? TAILQ_LAST(&sc->groupq, - group_ctx_q) : TAILQ_FIRST(&sc->groupq); - if (gc == sc->group_active) + newgc = (flags & CWM_RCYCLE) ? group_prev(newgc) : + group_next(newgc); + + if (newgc == oldgc) break; - if (!group_holds_only_sticky(gc) && showgroup == NULL) - showgroup = gc; - else if (!group_holds_only_hidden(gc)) - group_hide(gc); + if (!group_holds_only_sticky(newgc) && showgroup == NULL) + showgroup = newgc; + else if (!group_holds_only_hidden(newgc)) + group_hide(newgc); } - if (showgroup == NULL) - return; - - group_hide(sc->group_active); + group_hide(oldgc); if (group_holds_only_hidden(showgroup)) group_show(showgroup); @@ -292,6 +286,26 @@ group_cycle(struct screen_ctx *sc, int flags) group_setactive(showgroup); } +static struct group_ctx * +group_next(struct group_ctx *gc) +{ + struct screen_ctx *sc = gc->sc; + struct group_ctx *newgc; + + return(((newgc = TAILQ_NEXT(gc, entry)) != NULL) ? + newgc : TAILQ_FIRST(&sc->groupq)); +} + +static struct group_ctx * +group_prev(struct group_ctx *gc) +{ + struct screen_ctx *sc = gc->sc; + struct group_ctx *newgc; + + return(((newgc = TAILQ_PREV(gc, group_ctx_q, entry)) != NULL) ? + newgc : TAILQ_LAST(&sc->groupq, group_ctx_q)); +} + void group_alltoggle(struct screen_ctx *sc) { From a79253abdc9a66fb22e1e88c9514013605610daa Mon Sep 17 00:00:00 2001 From: okan Date: Fri, 21 Aug 2015 15:55:39 +0000 Subject: [PATCH 03/21] Leave command list order from .cwmrc alone; remove sort. --- conf.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/conf.c b/conf.c index 1ba2c54..09f0ddb 100644 --- a/conf.c +++ b/conf.c @@ -40,7 +40,7 @@ static void conf_unbind_mouse(struct conf *, struct binding *); int conf_cmd_add(struct conf *c, const char *name, const char *path) { - struct cmd *cmd, *prev; + struct cmd *cmd; cmd = xmalloc(sizeof(*cmd)); @@ -55,13 +55,6 @@ conf_cmd_add(struct conf *c, const char *name, const char *path) TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry); - /* keep queue sorted by name */ - while ((prev = TAILQ_PREV(cmd, cmd_q, entry)) && - (strcmp(prev->name, cmd->name) > 0)) { - TAILQ_REMOVE(&c->cmdq, cmd, entry); - TAILQ_INSERT_BEFORE(prev, cmd, entry); - } - return(1); } From c96fd247dd951cbbb5ea27a6be3f57f243e2d32a Mon Sep 17 00:00:00 2001 From: okan Date: Fri, 21 Aug 2015 16:05:55 +0000 Subject: [PATCH 04/21] Instead of special casing the 'term' and 'lock' commands, go back to keeping them hidden; showing them has apparently caused confusion/angst. --- kbfunc.c | 8 ++++++-- mousefunc.c | 6 +++++- search.c | 8 +------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/kbfunc.c b/kbfunc.c index ef4c49a..31273e8 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -177,8 +177,12 @@ kbfunc_menu_cmd(struct client_ctx *cc, union arg *arg) struct menu_q menuq; TAILQ_INIT(&menuq); - TAILQ_FOREACH(cmd, &Conf.cmdq, entry) - menuq_add(&menuq, cmd, "%s", cmd->name); + TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { + if ((strcmp(cmd->name, "lock") == 0) || + (strcmp(cmd->name, "term") == 0)) + continue; + menuq_add(&menuq, cmd, NULL); + } if ((mi = menu_filter(sc, &menuq, "application", NULL, 0, search_match_text, search_print_cmd)) != NULL) diff --git a/mousefunc.c b/mousefunc.c index aef5b04..f699243 100644 --- a/mousefunc.c +++ b/mousefunc.c @@ -233,8 +233,12 @@ mousefunc_menu_cmd(struct client_ctx *cc, union arg *arg) struct menu_q menuq; TAILQ_INIT(&menuq); - TAILQ_FOREACH(cmd, &Conf.cmdq, entry) + TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { + if ((strcmp(cmd->name, "lock") == 0) || + (strcmp(cmd->name, "term") == 0)) + continue; menuq_add(&menuq, cmd, NULL); + } if ((mi = menu_filter(sc, &menuq, NULL, NULL, CWM_MENU_LIST, NULL, search_print_cmd)) != NULL) diff --git a/search.c b/search.c index a960076..3192bff 100644 --- a/search.c +++ b/search.c @@ -127,14 +127,8 @@ void search_print_cmd(struct menu *mi, int i) { struct cmd *cmd = (struct cmd *)mi->ctx; - int special = 0; - if ((strcmp(cmd->name, "lock") == 0) || - (strcmp(cmd->name, "term") == 0)) - special = 1; - - (void)snprintf(mi->print, sizeof(mi->print), - (special) ? "[%s]" : "%s", cmd->name); + (void)snprintf(mi->print, sizeof(mi->print), "%s", cmd->name); } void From 05478f061e0b934a0d7d729f0e8ea5755b167487 Mon Sep 17 00:00:00 2001 From: okan Date: Fri, 21 Aug 2015 16:14:39 +0000 Subject: [PATCH 05/21] _NET_WM_STATE_STICKY implies only sticky at the group/desktop level, not position and size; based on discussion with a few. --- client.c | 6 +++--- kbfunc.c | 2 +- mousefunc.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client.c b/client.c index f75a804..e787012 100644 --- a/client.c +++ b/client.c @@ -299,7 +299,7 @@ client_toggle_maximize(struct client_ctx *cc) struct screen_ctx *sc = cc->sc; struct geom area; - if (cc->flags & (CLIENT_FREEZE|CLIENT_STICKY)) + if (cc->flags & CLIENT_FREEZE) return; if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_MAXIMIZED) { @@ -344,7 +344,7 @@ client_toggle_vmaximize(struct client_ctx *cc) struct screen_ctx *sc = cc->sc; struct geom area; - if (cc->flags & (CLIENT_FREEZE|CLIENT_STICKY)) + if (cc->flags & CLIENT_FREEZE) return; if (cc->flags & CLIENT_VMAXIMIZED) { @@ -376,7 +376,7 @@ client_toggle_hmaximize(struct client_ctx *cc) struct screen_ctx *sc = cc->sc; struct geom area; - if (cc->flags & (CLIENT_FREEZE|CLIENT_STICKY)) + if (cc->flags & CLIENT_FREEZE) return; if (cc->flags & CLIENT_HMAXIMIZED) { diff --git a/kbfunc.c b/kbfunc.c index 31273e8..8ff230d 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -61,7 +61,7 @@ kbfunc_client_moveresize(struct client_ctx *cc, union arg *arg) int x, y, flags, amt; unsigned int mx, my; - if (cc->flags & (CLIENT_FREEZE|CLIENT_STICKY)) + if (cc->flags & CLIENT_FREEZE) return; mx = my = 0; diff --git a/mousefunc.c b/mousefunc.c index f699243..ffa0ab0 100644 --- a/mousefunc.c +++ b/mousefunc.c @@ -72,7 +72,7 @@ mousefunc_client_resize(struct client_ctx *cc, union arg *arg) struct screen_ctx *sc = cc->sc; int x = cc->geom.x, y = cc->geom.y; - if (cc->flags & (CLIENT_FREEZE|CLIENT_STICKY)) + if (cc->flags & CLIENT_FREEZE) return; client_raise(cc); @@ -128,7 +128,7 @@ mousefunc_client_move(struct client_ctx *cc, union arg *arg) client_raise(cc); - if (cc->flags & (CLIENT_FREEZE|CLIENT_STICKY)) + if (cc->flags & CLIENT_FREEZE) return; if (xu_ptr_grab(cc->win, MOUSEMASK, Conf.cursor[CF_MOVE]) < 0) From 1d31f9000cabc965f478991c4ad11c43f163c30f Mon Sep 17 00:00:00 2001 From: okan Date: Fri, 21 Aug 2015 16:30:02 +0000 Subject: [PATCH 06/21] Add client freeze extension to _NET_WM_STATE Atom, allowing flag to persist. As usual with new Atoms, requires X restart. --- calmwm.h | 3 ++- client.c | 2 ++ conf.c | 1 + xutil.c | 10 +++++++++- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/calmwm.h b/calmwm.h index 19c0a96..79ac615 100644 --- a/calmwm.h +++ b/calmwm.h @@ -364,7 +364,8 @@ enum { _NET_WM_DESKTOP, _NET_CLOSE_WINDOW, _NET_WM_STATE, -#define _NET_WM_STATES_NITEMS 6 +#define _NET_WM_STATES_NITEMS 7 + _CWM_WM_STATE_FREEZE, _NET_WM_STATE_STICKY, _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ, diff --git a/client.c b/client.c index e787012..5eb814e 100644 --- a/client.c +++ b/client.c @@ -237,6 +237,8 @@ client_toggle_freeze(struct client_ctx *cc) cc->flags &= ~CLIENT_FREEZE; else cc->flags |= CLIENT_FREEZE; + + xu_ewmh_set_net_wm_state(cc); } void diff --git a/conf.c b/conf.c index 09f0ddb..c8af9f6 100644 --- a/conf.c +++ b/conf.c @@ -680,6 +680,7 @@ static char *ewmhints[] = { "_NET_WM_DESKTOP", "_NET_CLOSE_WINDOW", "_NET_WM_STATE", + "_CWM_WM_STATE_FREEZE", "_NET_WM_STATE_STICKY", "_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ", diff --git a/xutil.c b/xutil.c index c6248c4..51e3fec 100644 --- a/xutil.c +++ b/xutil.c @@ -374,6 +374,9 @@ xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action, int property; void (*toggle)(struct client_ctx *); } handlers[] = { + { _CWM_WM_STATE_FREEZE, + CLIENT_FREEZE, + client_toggle_freeze }, { _NET_WM_STATE_STICKY, CLIENT_STICKY, client_toggle_sticky }, @@ -421,6 +424,8 @@ xu_ewmh_restore_net_wm_state(struct client_ctx *cc) atoms = xu_ewmh_get_net_wm_state(cc, &n); for (i = 0; i < n; i++) { + if (atoms[i] == ewmh[_CWM_WM_STATE_FREEZE]) + client_toggle_freeze(cc); if (atoms[i] == ewmh[_NET_WM_STATE_STICKY]) client_toggle_sticky(cc); if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_HORZ]) @@ -446,7 +451,8 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc) oatoms = xu_ewmh_get_net_wm_state(cc, &n); atoms = xreallocarray(NULL, (n + _NET_WM_STATES_NITEMS), sizeof(Atom)); for (i = j = 0; i < n; i++) { - if (oatoms[i] != ewmh[_NET_WM_STATE_STICKY] && + if (oatoms[i] != ewmh[_CWM_WM_STATE_FREEZE] && + oatoms[i] != ewmh[_NET_WM_STATE_STICKY] && oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_HORZ] && oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_VERT] && oatoms[i] != ewmh[_NET_WM_STATE_HIDDEN] && @@ -455,6 +461,8 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc) atoms[j++] = oatoms[i]; } free(oatoms); + if (cc->flags & CLIENT_FREEZE) + atoms[j++] = ewmh[_CWM_WM_STATE_FREEZE]; if (cc->flags & CLIENT_STICKY) atoms[j++] = ewmh[_NET_WM_STATE_STICKY]; if (cc->flags & CLIENT_HIDDEN) From cd3bbb1c9c2d789977ec761aeddedc26d282de89 Mon Sep 17 00:00:00 2001 From: okan Date: Fri, 21 Aug 2015 16:52:37 +0000 Subject: [PATCH 07/21] Fix whitespace. --- calmwm.h | 12 ++++++------ client.c | 4 ++-- conf.c | 52 ++++++++++++++++++++++++++-------------------------- cwm.1 | 4 ++-- screen.c | 8 ++++---- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/calmwm.h b/calmwm.h index 79ac615..ebb2a47 100644 --- a/calmwm.h +++ b/calmwm.h @@ -43,12 +43,12 @@ #define CONFFILE ".cwmrc" #define WMNAME "CWM" -#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -#define MOUSEMASK (BUTTONMASK|PointerMotionMask) -#define MENUMASK (MOUSEMASK|ButtonMotionMask|ExposureMask) -#define MENUGRABMASK (MOUSEMASK|ButtonMotionMask|StructureNotifyMask) -#define KEYMASK (KeyPressMask|ExposureMask) -#define IGNOREMODMASK (LockMask|Mod2Mask) +#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask) +#define MOUSEMASK (BUTTONMASK | PointerMotionMask) +#define MENUMASK (MOUSEMASK | ButtonMotionMask | ExposureMask) +#define MENUGRABMASK (MOUSEMASK | ButtonMotionMask | StructureNotifyMask) +#define KEYMASK (KeyPressMask | ExposureMask) +#define IGNOREMODMASK (LockMask | Mod2Mask) /* kb movement */ #define CWM_MOVE 0x0001 diff --git a/client.c b/client.c index 5eb814e..7faf0ef 100644 --- a/client.c +++ b/client.c @@ -669,7 +669,7 @@ client_cycle(struct screen_ctx *sc, int flags) client_next(newcc); /* Only cycle visible and non-ignored windows. */ - if ((newcc->flags & (CLIENT_HIDDEN|CLIENT_IGNORE)) + if ((newcc->flags & (CLIENT_HIDDEN | CLIENT_IGNORE)) || ((flags & CWM_INGROUP) && (newcc->group != oldcc->group))) again = 1; @@ -729,7 +729,7 @@ client_placecalc(struct client_ctx *cc) struct screen_ctx *sc = cc->sc; int xslack, yslack; - if (cc->hint.flags & (USPosition|PPosition)) { + if (cc->hint.flags & (USPosition | PPosition)) { /* * Ignore XINERAMA screens, just make sure it's somewhere * in the virtual desktop. else it stops people putting xterms diff --git a/conf.c b/conf.c index c8af9f6..9769863 100644 --- a/conf.c +++ b/conf.c @@ -390,9 +390,9 @@ static const struct { { "cyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_CYCLE} }, { "rcyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_RCYCLE} }, { "cycleingroup", kbfunc_client_cycle, CWM_WIN, - {.i = CWM_CYCLE|CWM_INGROUP} }, + {.i = (CWM_CYCLE | CWM_INGROUP)} }, { "rcycleingroup", kbfunc_client_cycle, CWM_WIN, - {.i = CWM_RCYCLE|CWM_INGROUP} }, + {.i = (CWM_RCYCLE | CWM_INGROUP)} }, { "grouptoggle", kbfunc_client_grouptoggle, CWM_WIN, {.i = 0}}, { "sticky", kbfunc_client_toggle_sticky, CWM_WIN, {0} }, { "fullscreen", kbfunc_client_toggle_fullscreen, CWM_WIN, {0} }, @@ -408,53 +408,53 @@ static const struct { { "terminal", kbfunc_term, 0, {0} }, { "lock", kbfunc_lock, 0, {0} }, { "moveup", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_UP|CWM_MOVE)} }, + {.i = (CWM_UP | CWM_MOVE)} }, { "movedown", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_DOWN|CWM_MOVE)} }, + {.i = (CWM_DOWN | CWM_MOVE)} }, { "moveright", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_RIGHT|CWM_MOVE)} }, + {.i = (CWM_RIGHT | CWM_MOVE)} }, { "moveleft", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_LEFT|CWM_MOVE)} }, + {.i = (CWM_LEFT | CWM_MOVE)} }, { "bigmoveup", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_UP|CWM_MOVE|CWM_BIGMOVE)} }, + {.i = (CWM_UP | CWM_MOVE | CWM_BIGMOVE)} }, { "bigmovedown", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_DOWN|CWM_MOVE|CWM_BIGMOVE)} }, + {.i = (CWM_DOWN | CWM_MOVE | CWM_BIGMOVE)} }, { "bigmoveright", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_RIGHT|CWM_MOVE|CWM_BIGMOVE)} }, + {.i = (CWM_RIGHT | CWM_MOVE | CWM_BIGMOVE)} }, { "bigmoveleft", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_LEFT|CWM_MOVE|CWM_BIGMOVE)} }, + {.i = (CWM_LEFT | CWM_MOVE | CWM_BIGMOVE)} }, { "resizeup", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_UP|CWM_RESIZE)} }, + {.i = (CWM_UP | CWM_RESIZE)} }, { "resizedown", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_DOWN|CWM_RESIZE)} }, + {.i = (CWM_DOWN | CWM_RESIZE)} }, { "resizeright", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_RIGHT|CWM_RESIZE)} }, + {.i = (CWM_RIGHT | CWM_RESIZE)} }, { "resizeleft", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_LEFT|CWM_RESIZE)} }, + {.i = (CWM_LEFT | CWM_RESIZE)} }, { "bigresizeup", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_UP|CWM_RESIZE|CWM_BIGMOVE)} }, + {.i = (CWM_UP | CWM_RESIZE | CWM_BIGMOVE)} }, { "bigresizedown", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_DOWN|CWM_RESIZE|CWM_BIGMOVE)} }, + {.i = (CWM_DOWN | CWM_RESIZE | CWM_BIGMOVE)} }, { "bigresizeright", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_RIGHT|CWM_RESIZE|CWM_BIGMOVE)} }, + {.i = (CWM_RIGHT | CWM_RESIZE | CWM_BIGMOVE)} }, { "bigresizeleft", kbfunc_client_moveresize, CWM_WIN, - {.i = (CWM_LEFT|CWM_RESIZE|CWM_BIGMOVE)} }, + {.i = (CWM_LEFT | CWM_RESIZE | CWM_BIGMOVE)} }, { "ptrmoveup", kbfunc_client_moveresize, 0, - {.i = (CWM_UP|CWM_PTRMOVE)} }, + {.i = (CWM_UP | CWM_PTRMOVE)} }, { "ptrmovedown", kbfunc_client_moveresize, 0, - {.i = (CWM_DOWN|CWM_PTRMOVE)} }, + {.i = (CWM_DOWN | CWM_PTRMOVE)} }, { "ptrmoveleft", kbfunc_client_moveresize, 0, - {.i = (CWM_LEFT|CWM_PTRMOVE)} }, + {.i = (CWM_LEFT | CWM_PTRMOVE)} }, { "ptrmoveright", kbfunc_client_moveresize, 0, - {.i = (CWM_RIGHT|CWM_PTRMOVE)} }, + {.i = (CWM_RIGHT | CWM_PTRMOVE)} }, { "bigptrmoveup", kbfunc_client_moveresize, 0, - {.i = (CWM_UP|CWM_PTRMOVE|CWM_BIGMOVE)} }, + {.i = (CWM_UP | CWM_PTRMOVE | CWM_BIGMOVE)} }, { "bigptrmovedown", kbfunc_client_moveresize, 0, - {.i = (CWM_DOWN|CWM_PTRMOVE|CWM_BIGMOVE)} }, + {.i = (CWM_DOWN | CWM_PTRMOVE | CWM_BIGMOVE)} }, { "bigptrmoveleft", kbfunc_client_moveresize, 0, - {.i = (CWM_LEFT|CWM_PTRMOVE|CWM_BIGMOVE)} }, + {.i = (CWM_LEFT | CWM_PTRMOVE | CWM_BIGMOVE)} }, { "bigptrmoveright", kbfunc_client_moveresize, 0, - {.i = (CWM_RIGHT|CWM_PTRMOVE|CWM_BIGMOVE)} }, + {.i = (CWM_RIGHT | CWM_PTRMOVE | CWM_BIGMOVE)} }, { "htile", kbfunc_tile, CWM_WIN, {.i = CWM_TILE_HORIZ} }, { "vtile", kbfunc_tile, CWM_WIN, {.i = CWM_TILE_VERT} }, { "window_lower", kbfunc_client_lower, CWM_WIN, {0} }, diff --git a/cwm.1 b/cwm.1 index e4776ca..447b646 100644 --- a/cwm.1 +++ b/cwm.1 @@ -117,9 +117,9 @@ Toggle maximization of current window. Toggle vertical maximization of current window. .It Ic CMS-= Toggle horizontal maximization of current window. -.It Ic C-[Up|Down|Left|Right] +.It Ic C-[Up | Down | Left | Right] Move pointer by a small amount. -.It Ic CS-[Up|Down|Left|Right] +.It Ic CS-[Up | Down | Left | Right] Move pointer by a large amount; see .Xr cwmrc 5 . .It Ic M-[hjkl] diff --git a/screen.c b/screen.c index 7ba8a31..aad2159 100644 --- a/screen.c +++ b/screen.c @@ -67,12 +67,12 @@ screen_init(int which) xu_ewmh_net_virtual_roots(sc); rootattr.cursor = Conf.cursor[CF_NORMAL]; - rootattr.event_mask = SubstructureRedirectMask|SubstructureNotifyMask| - PropertyChangeMask|EnterWindowMask|LeaveWindowMask| - ColormapChangeMask|BUTTONMASK; + rootattr.event_mask = SubstructureRedirectMask | + SubstructureNotifyMask | PropertyChangeMask | EnterWindowMask | + LeaveWindowMask | ColormapChangeMask | BUTTONMASK; XChangeWindowAttributes(X_Dpy, sc->rootwin, - CWEventMask|CWCursor, &rootattr); + (CWEventMask | CWCursor), &rootattr); /* Deal with existing clients. */ if (XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins)) { From ae9306748b36c5264ac95a9b50ffbbde94911b48 Mon Sep 17 00:00:00 2001 From: okan Date: Fri, 21 Aug 2015 16:53:48 +0000 Subject: [PATCH 08/21] Add Xkb modifier to ignore mask; from Alexander Polakov. --- calmwm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calmwm.h b/calmwm.h index ebb2a47..858441e 100644 --- a/calmwm.h +++ b/calmwm.h @@ -48,7 +48,7 @@ #define MENUMASK (MOUSEMASK | ButtonMotionMask | ExposureMask) #define MENUGRABMASK (MOUSEMASK | ButtonMotionMask | StructureNotifyMask) #define KEYMASK (KeyPressMask | ExposureMask) -#define IGNOREMODMASK (LockMask | Mod2Mask) +#define IGNOREMODMASK (LockMask | Mod2Mask | 0x2000) /* kb movement */ #define CWM_MOVE 0x0001 From b224945446083ec061cea8ae41ee98190f7a4185 Mon Sep 17 00:00:00 2001 From: okan Date: Sun, 23 Aug 2015 17:31:20 +0000 Subject: [PATCH 09/21] Move CLIENT_STICKY logic from client hide/unhide to group hide/unhide; rationale being that clients should be able to hide/unhide independently of group switching. --- client.c | 6 ------ group.c | 12 ++++++++---- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/client.c b/client.c index 7faf0ef..6b3ab11 100644 --- a/client.c +++ b/client.c @@ -493,9 +493,6 @@ client_ptrsave(struct client_ctx *cc) void client_hide(struct client_ctx *cc) { - if (cc->flags & CLIENT_STICKY) - return; - XUnmapWindow(X_Dpy, cc->win); cc->flags &= ~CLIENT_ACTIVE; @@ -509,9 +506,6 @@ client_hide(struct client_ctx *cc) void client_unhide(struct client_ctx *cc) { - if (cc->flags & CLIENT_STICKY) - return; - XMapRaised(X_Dpy, cc->win); cc->flags &= ~CLIENT_HIDDEN; diff --git a/group.c b/group.c index bbcd6cf..c2d4b36 100644 --- a/group.c +++ b/group.c @@ -64,8 +64,10 @@ group_hide(struct group_ctx *gc) screen_updatestackingorder(gc->sc); - TAILQ_FOREACH(cc, &gc->clientq, group_entry) - client_hide(cc); + TAILQ_FOREACH(cc, &gc->clientq, group_entry) { + if (!(cc->flags & CLIENT_STICKY)) + client_hide(cc); + } } void @@ -73,8 +75,10 @@ group_show(struct group_ctx *gc) { struct client_ctx *cc; - TAILQ_FOREACH(cc, &gc->clientq, group_entry) - client_unhide(cc); + TAILQ_FOREACH(cc, &gc->clientq, group_entry) { + if (!(cc->flags & CLIENT_STICKY)) + client_unhide(cc); + } group_restack(gc); group_setactive(gc); From 4269ea046355991779eaf397fb9d99685532af69 Mon Sep 17 00:00:00 2001 From: okan Date: Mon, 24 Aug 2015 14:56:10 +0000 Subject: [PATCH 10/21] Sort _NET_WM_STATE Atoms like the spec. --- calmwm.h | 2 +- conf.c | 2 +- xutil.c | 30 +++++++++++++++--------------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/calmwm.h b/calmwm.h index 858441e..16cccba 100644 --- a/calmwm.h +++ b/calmwm.h @@ -365,13 +365,13 @@ enum { _NET_CLOSE_WINDOW, _NET_WM_STATE, #define _NET_WM_STATES_NITEMS 7 - _CWM_WM_STATE_FREEZE, _NET_WM_STATE_STICKY, _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_HIDDEN, _NET_WM_STATE_FULLSCREEN, _NET_WM_STATE_DEMANDS_ATTENTION, + _CWM_WM_STATE_FREEZE, EWMH_NITEMS }; enum { diff --git a/conf.c b/conf.c index 9769863..4bcfbb8 100644 --- a/conf.c +++ b/conf.c @@ -680,13 +680,13 @@ static char *ewmhints[] = { "_NET_WM_DESKTOP", "_NET_CLOSE_WINDOW", "_NET_WM_STATE", - "_CWM_WM_STATE_FREEZE", "_NET_WM_STATE_STICKY", "_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ", "_NET_WM_STATE_HIDDEN", "_NET_WM_STATE_FULLSCREEN", "_NET_WM_STATE_DEMANDS_ATTENTION", + "_CWM_WM_STATE_FREEZE", }; void diff --git a/xutil.c b/xutil.c index 51e3fec..56e180c 100644 --- a/xutil.c +++ b/xutil.c @@ -374,9 +374,6 @@ xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action, int property; void (*toggle)(struct client_ctx *); } handlers[] = { - { _CWM_WM_STATE_FREEZE, - CLIENT_FREEZE, - client_toggle_freeze }, { _NET_WM_STATE_STICKY, CLIENT_STICKY, client_toggle_sticky }, @@ -395,6 +392,9 @@ xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action, { _NET_WM_STATE_DEMANDS_ATTENTION, CLIENT_URGENCY, client_urgency }, + { _CWM_WM_STATE_FREEZE, + CLIENT_FREEZE, + client_toggle_freeze }, }; for (i = 0; i < nitems(handlers); i++) { @@ -424,20 +424,20 @@ xu_ewmh_restore_net_wm_state(struct client_ctx *cc) atoms = xu_ewmh_get_net_wm_state(cc, &n); for (i = 0; i < n; i++) { - if (atoms[i] == ewmh[_CWM_WM_STATE_FREEZE]) - client_toggle_freeze(cc); if (atoms[i] == ewmh[_NET_WM_STATE_STICKY]) client_toggle_sticky(cc); - if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_HORZ]) - client_toggle_hmaximize(cc); if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_VERT]) client_toggle_vmaximize(cc); + if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_HORZ]) + client_toggle_hmaximize(cc); if (atoms[i] == ewmh[_NET_WM_STATE_HIDDEN]) client_toggle_hidden(cc); if (atoms[i] == ewmh[_NET_WM_STATE_FULLSCREEN]) client_toggle_fullscreen(cc); if (atoms[i] == ewmh[_NET_WM_STATE_DEMANDS_ATTENTION]) client_urgency(cc); + if (atoms[i] == ewmh[_CWM_WM_STATE_FREEZE]) + client_toggle_freeze(cc); } free(atoms); } @@ -451,18 +451,16 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc) oatoms = xu_ewmh_get_net_wm_state(cc, &n); atoms = xreallocarray(NULL, (n + _NET_WM_STATES_NITEMS), sizeof(Atom)); for (i = j = 0; i < n; i++) { - if (oatoms[i] != ewmh[_CWM_WM_STATE_FREEZE] && - oatoms[i] != ewmh[_NET_WM_STATE_STICKY] && - oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_HORZ] && + if (oatoms[i] != ewmh[_NET_WM_STATE_STICKY] && oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_VERT] && + oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_HORZ] && oatoms[i] != ewmh[_NET_WM_STATE_HIDDEN] && oatoms[i] != ewmh[_NET_WM_STATE_FULLSCREEN] && - oatoms[i] != ewmh[_NET_WM_STATE_DEMANDS_ATTENTION]) + oatoms[i] != ewmh[_NET_WM_STATE_DEMANDS_ATTENTION] && + oatoms[i] != ewmh[_CWM_WM_STATE_FREEZE]) atoms[j++] = oatoms[i]; } free(oatoms); - if (cc->flags & CLIENT_FREEZE) - atoms[j++] = ewmh[_CWM_WM_STATE_FREEZE]; if (cc->flags & CLIENT_STICKY) atoms[j++] = ewmh[_NET_WM_STATE_STICKY]; if (cc->flags & CLIENT_HIDDEN) @@ -470,13 +468,15 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc) if (cc->flags & CLIENT_FULLSCREEN) atoms[j++] = ewmh[_NET_WM_STATE_FULLSCREEN]; else { - if (cc->flags & CLIENT_HMAXIMIZED) - atoms[j++] = ewmh[_NET_WM_STATE_MAXIMIZED_HORZ]; if (cc->flags & CLIENT_VMAXIMIZED) atoms[j++] = ewmh[_NET_WM_STATE_MAXIMIZED_VERT]; + if (cc->flags & CLIENT_HMAXIMIZED) + atoms[j++] = ewmh[_NET_WM_STATE_MAXIMIZED_HORZ]; } if (cc->flags & CLIENT_URGENCY) atoms[j++] = ewmh[_NET_WM_STATE_DEMANDS_ATTENTION]; + if (cc->flags & CLIENT_FREEZE) + atoms[j++] = ewmh[_CWM_WM_STATE_FREEZE]; if (j > 0) XChangeProperty(X_Dpy, cc->win, ewmh[_NET_WM_STATE], XA_ATOM, 32, PropModeReplace, (unsigned char *)atoms, j); From 97db17d0568c8dcb41173104af16b000879a36e4 Mon Sep 17 00:00:00 2001 From: okan Date: Mon, 24 Aug 2015 14:57:19 +0000 Subject: [PATCH 11/21] Don't allow freeze operations on fullscreen (consistent with what fullscreen does). --- client.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client.c b/client.c index 6b3ab11..3298bf7 100644 --- a/client.c +++ b/client.c @@ -233,6 +233,9 @@ client_current(void) void client_toggle_freeze(struct client_ctx *cc) { + if (cc->flags & CLIENT_FULLSCREEN) + return; + if (cc->flags & CLIENT_FREEZE) cc->flags &= ~CLIENT_FREEZE; else From dcfbc9e809623eee64e9df28fd8cfc754d1f6a6a Mon Sep 17 00:00:00 2001 From: okan Date: Mon, 24 Aug 2015 15:42:57 +0000 Subject: [PATCH 12/21] Implement _NET_CLIENT_LIST_STACKING (from Thomas Admin), but bottom-to-top order, as per spec (notified Thomas as well). --- calmwm.h | 2 ++ client.c | 2 ++ conf.c | 1 + xutil.c | 21 +++++++++++++++++++++ 4 files changed, 26 insertions(+) diff --git a/calmwm.h b/calmwm.h index 16cccba..f1b110b 100644 --- a/calmwm.h +++ b/calmwm.h @@ -352,6 +352,7 @@ enum { _NET_SUPPORTING_WM_CHECK, _NET_ACTIVE_WINDOW, _NET_CLIENT_LIST, + _NET_CLIENT_LIST_STACKING, _NET_NUMBER_OF_DESKTOPS, _NET_CURRENT_DESKTOP, _NET_DESKTOP_VIEWPORT, @@ -562,6 +563,7 @@ void xu_ewmh_net_supported_wm_check(struct screen_ctx *); void xu_ewmh_net_desktop_geometry(struct screen_ctx *); void xu_ewmh_net_workarea(struct screen_ctx *); void xu_ewmh_net_client_list(struct screen_ctx *); +void xu_ewmh_net_client_list_stacking(struct screen_ctx *); void xu_ewmh_net_active_window(struct screen_ctx *, Window); void xu_ewmh_net_wm_desktop_viewport(struct screen_ctx *); void xu_ewmh_net_wm_number_of_desktops(struct screen_ctx *); diff --git a/client.c b/client.c index 3298bf7..3a3e66e 100644 --- a/client.c +++ b/client.c @@ -112,6 +112,7 @@ client_init(Window win, struct screen_ctx *sc) TAILQ_INSERT_TAIL(&sc->clientq, cc, entry); xu_ewmh_net_client_list(sc); + xu_ewmh_net_client_list_stacking(sc); xu_ewmh_restore_net_wm_state(cc); if (client_get_wm_state(cc) == IconicState) @@ -152,6 +153,7 @@ client_delete(struct client_ctx *cc) TAILQ_REMOVE(&sc->clientq, cc, entry); xu_ewmh_net_client_list(sc); + xu_ewmh_net_client_list_stacking(sc); if (cc->group != NULL) TAILQ_REMOVE(&cc->group->clientq, cc, group_entry); diff --git a/conf.c b/conf.c index 4bcfbb8..608acf0 100644 --- a/conf.c +++ b/conf.c @@ -668,6 +668,7 @@ static char *ewmhints[] = { "_NET_SUPPORTING_WM_CHECK", "_NET_ACTIVE_WINDOW", "_NET_CLIENT_LIST", + "_NET_CLIENT_LIST_STACKING", "_NET_NUMBER_OF_DESKTOPS", "_NET_CURRENT_DESKTOP", "_NET_DESKTOP_VIEWPORT", diff --git a/xutil.c b/xutil.c index 56e180c..f61aeef 100644 --- a/xutil.c +++ b/xutil.c @@ -228,6 +228,27 @@ xu_ewmh_net_client_list(struct screen_ctx *sc) free(winlist); } +void +xu_ewmh_net_client_list_stacking(struct screen_ctx *sc) +{ + struct client_ctx *cc; + Window *winlist; + int i = 0, j; + + TAILQ_FOREACH(cc, &sc->clientq, entry) + i++; + if (i == 0) + return; + + j = i; + winlist = xreallocarray(NULL, i, sizeof(*winlist)); + TAILQ_FOREACH(cc, &sc->clientq, entry) + winlist[--j] = cc->win; + XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_CLIENT_LIST_STACKING], + XA_WINDOW, 32, PropModeReplace, (unsigned char *)winlist, i); + free(winlist); +} + void xu_ewmh_net_active_window(struct screen_ctx *sc, Window w) { From 96262a6b0cc6dbf5d82fcac45b81cbc376c2a0ef Mon Sep 17 00:00:00 2001 From: okan Date: Tue, 25 Aug 2015 18:29:10 +0000 Subject: [PATCH 13/21] Split out sticky mode checks and the restoring of a client's group and _NET_WM_DESKTOP from the config-based auto-grouping; no (intentional) behavior changes. Needed for further work in cleaning up this area. --- calmwm.h | 4 ++- client.c | 14 ++++++++--- group.c | 75 +++++++++++++++++++++++++++++++++----------------------- 3 files changed, 58 insertions(+), 35 deletions(-) diff --git a/calmwm.h b/calmwm.h index f1b110b..08631ad 100644 --- a/calmwm.h +++ b/calmwm.h @@ -426,7 +426,8 @@ void client_warp(struct client_ctx *); void client_wm_hints(struct client_ctx *); void group_alltoggle(struct screen_ctx *); -void group_autogroup(struct client_ctx *); +void group_assign(struct group_ctx *, struct client_ctx *); +int group_autogroup(struct client_ctx *); void group_cycle(struct screen_ctx *, int); void group_hide(struct group_ctx *); void group_hidetoggle(struct screen_ctx *, int); @@ -435,6 +436,7 @@ int group_holds_only_sticky(struct group_ctx *); void group_init(struct screen_ctx *, int); void group_movetogroup(struct client_ctx *, int); void group_only(struct screen_ctx *, int); +int group_restore(struct client_ctx *); void group_show(struct group_ctx *); void group_toggle_membership_enter(struct client_ctx *); void group_toggle_membership_leave(struct client_ctx *); diff --git a/client.c b/client.c index 3a3e66e..ff492de 100644 --- a/client.c +++ b/client.c @@ -120,9 +120,17 @@ client_init(Window win, struct screen_ctx *sc) else client_unhide(cc); - if (mapped) - group_autogroup(cc); - + if (mapped) { + if (group_restore(cc)) + goto out; + if (group_autogroup(cc)) + goto out; + if (Conf.flags & CONF_STICKY_GROUPS) + group_assign(sc->group_active, cc); + else + group_assign(NULL, cc); + } +out: XSync(X_Dpy, False); XUngrabServer(X_Dpy); diff --git a/group.c b/group.c index c2d4b36..fa7d8c9 100644 --- a/group.c +++ b/group.c @@ -34,7 +34,6 @@ static struct group_ctx *group_next(struct group_ctx *); static struct group_ctx *group_prev(struct group_ctx *); -static void group_assign(struct group_ctx *, struct client_ctx *); static void group_restack(struct group_ctx *); static void group_setactive(struct group_ctx *); @@ -43,7 +42,7 @@ const char *num_to_name[] = { "seven", "eight", "nine" }; -static void +void group_assign(struct group_ctx *gc, struct client_ctx *cc) { if (cc->group != NULL) @@ -324,51 +323,65 @@ group_alltoggle(struct screen_ctx *sc) sc->hideall = !sc->hideall; } -void +int +group_restore(struct client_ctx *cc) +{ + struct screen_ctx *sc = cc->sc; + struct group_ctx *gc; + int num = -1; + long *grpnum; + + if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP], XA_CARDINAL, 1L, + (unsigned char **)&grpnum) <= 0) + return(0); + + num = MIN(*grpnum, (CALMWM_NGROUPS - 1)); + XFree(grpnum); + + if ((num == -1) || (num == 0)) { + group_assign(NULL, cc); + return(1); + } + TAILQ_FOREACH(gc, &sc->groupq, entry) { + if (gc->num == num) { + group_assign(gc, cc); + return(1); + } + } + return(0); +} + +int group_autogroup(struct client_ctx *cc) { struct screen_ctx *sc = cc->sc; struct autogroupwin *aw; struct group_ctx *gc; - int num = -2, both_match = 0; - long *grpnum; + int num = -1, both_match = 0; if (cc->ch.res_class == NULL || cc->ch.res_name == NULL) - return; + return(0); - if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP], - XA_CARDINAL, 1, (unsigned char **)&grpnum) > 0) { - num = *grpnum; - if (num > CALMWM_NGROUPS || num < -1) - num = CALMWM_NGROUPS - 1; - XFree(grpnum); - } else { - TAILQ_FOREACH(aw, &Conf.autogroupq, entry) { - if (strcmp(aw->class, cc->ch.res_class) == 0) { - if ((aw->name != NULL) && - (strcmp(aw->name, cc->ch.res_name) == 0)) { - num = aw->num; - both_match = 1; - } else if (aw->name == NULL && !both_match) - num = aw->num; - } + TAILQ_FOREACH(aw, &Conf.autogroupq, entry) { + if (strcmp(aw->class, cc->ch.res_class) == 0) { + if ((aw->name != NULL) && + (strcmp(aw->name, cc->ch.res_name) == 0)) { + num = aw->num; + both_match = 1; + } else if (aw->name == NULL && !both_match) + num = aw->num; } } - if ((num == -1) || (num == 0)) { + if (num == 0) { group_assign(NULL, cc); - return; + return(1); } - TAILQ_FOREACH(gc, &sc->groupq, entry) { if (gc->num == num) { group_assign(gc, cc); - return; + return(1); } } - - if (Conf.flags & CONF_STICKY_GROUPS) - group_assign(sc->group_active, cc); - else - group_assign(NULL, cc); + return(0); } From cb60a4b917a4e72cd579f1f7bc8d863be00498bb Mon Sep 17 00:00:00 2001 From: okan Date: Tue, 25 Aug 2015 19:49:19 +0000 Subject: [PATCH 14/21] Allowing sending a valid 'nogroup' (0) group_ctx to group_assign() (since we init all groups), though assigning the client's group to NULL for 'sticky'; use this simplification in a few places (others to follow). --- group.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/group.c b/group.c index fa7d8c9..30a6f53 100644 --- a/group.c +++ b/group.c @@ -48,6 +48,9 @@ group_assign(struct group_ctx *gc, struct client_ctx *cc) if (cc->group != NULL) TAILQ_REMOVE(&cc->group->clientq, cc, group_entry); + if ((gc != NULL) && (gc->num == 0)) + gc = NULL; + cc->group = gc; if (cc->group != NULL) @@ -129,6 +132,8 @@ group_init(struct screen_ctx *sc, int num) gc->num = num; TAILQ_INIT(&gc->clientq); + fprintf(stderr, "%d: %s\n", gc->num, gc->name); + TAILQ_INSERT_TAIL(&sc->groupq, gc, entry); if (num == 1) @@ -338,7 +343,7 @@ group_restore(struct client_ctx *cc) num = MIN(*grpnum, (CALMWM_NGROUPS - 1)); XFree(grpnum); - if ((num == -1) || (num == 0)) { + if (num == -1) { group_assign(NULL, cc); return(1); } @@ -373,10 +378,6 @@ group_autogroup(struct client_ctx *cc) } } - if (num == 0) { - group_assign(NULL, cc); - return(1); - } TAILQ_FOREACH(gc, &sc->groupq, entry) { if (gc->num == num) { group_assign(gc, cc); From 871ed39ccf6b6ab7385c87f849a7c9bcff130792 Mon Sep 17 00:00:00 2001 From: okan Date: Tue, 25 Aug 2015 19:52:02 +0000 Subject: [PATCH 15/21] oops; remove left over debug print --- group.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/group.c b/group.c index 30a6f53..0857437 100644 --- a/group.c +++ b/group.c @@ -132,8 +132,6 @@ group_init(struct screen_ctx *sc, int num) gc->num = num; TAILQ_INIT(&gc->clientq); - fprintf(stderr, "%d: %s\n", gc->num, gc->name); - TAILQ_INSERT_TAIL(&sc->groupq, gc, entry); if (num == 1) From 6d53091429e074e0d5bd504a9001016106d2d1ac Mon Sep 17 00:00:00 2001 From: okan Date: Tue, 25 Aug 2015 20:35:49 +0000 Subject: [PATCH 16/21] Further simplify _NET_WM_DESKTOP handling using new group_assign(). --- group.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/group.c b/group.c index 0857437..5482d70 100644 --- a/group.c +++ b/group.c @@ -331,20 +331,17 @@ group_restore(struct client_ctx *cc) { struct screen_ctx *sc = cc->sc; struct group_ctx *gc; - int num = -1; + int num; long *grpnum; if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP], XA_CARDINAL, 1L, (unsigned char **)&grpnum) <= 0) return(0); - num = MIN(*grpnum, (CALMWM_NGROUPS - 1)); + num = (*grpnum == -1) ? 0 : *grpnum; + num = MIN(num, (CALMWM_NGROUPS - 1)); XFree(grpnum); - if (num == -1) { - group_assign(NULL, cc); - return(1); - } TAILQ_FOREACH(gc, &sc->groupq, entry) { if (gc->num == num) { group_assign(gc, cc); From 5391659629a7fa75b7447e824e56e179c10ca642 Mon Sep 17 00:00:00 2001 From: okan Date: Thu, 27 Aug 2015 17:43:44 +0000 Subject: [PATCH 17/21] Re-add lost chunk in group_cycle from r1.113. --- group.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/group.c b/group.c index 5482d70..3cb5e79 100644 --- a/group.c +++ b/group.c @@ -284,6 +284,9 @@ group_cycle(struct screen_ctx *sc, int flags) group_hide(newgc); } + if (showgroup == NULL) + return; + group_hide(oldgc); if (group_holds_only_hidden(showgroup)) From 19826222f6dc85116145acaf8210c83c2c91dab6 Mon Sep 17 00:00:00 2001 From: okan Date: Thu, 27 Aug 2015 18:40:09 +0000 Subject: [PATCH 18/21] Move client cycle grab/ungrab into a more relevant place; while here, update comments about why we need to grab/ungrab the keyboard. --- client.c | 4 ++++ kbfunc.c | 10 ++-------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/client.c b/client.c index ff492de..f30910a 100644 --- a/client.c +++ b/client.c @@ -659,6 +659,10 @@ client_cycle(struct screen_ctx *sc, int flags) struct client_ctx *newcc, *oldcc; int again = 1; + /* For X apps that ignore events. */ + XGrabKeyboard(X_Dpy, sc->rootwin, True, + GrabModeAsync, GrabModeAsync, CurrentTime); + if (TAILQ_EMPTY(&sc->clientq)) return; diff --git a/kbfunc.c b/kbfunc.c index 8ff230d..8d220a6 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -219,13 +219,7 @@ kbfunc_menu_group(struct client_ctx *cc, union arg *arg) void kbfunc_client_cycle(struct client_ctx *cc, union arg *arg) { - struct screen_ctx *sc = cc->sc; - - /* XXX for X apps that ignore events */ - XGrabKeyboard(X_Dpy, sc->rootwin, True, - GrabModeAsync, GrabModeAsync, CurrentTime); - - client_cycle(sc, arg->i); + client_cycle(cc->sc, arg->i); } void @@ -464,7 +458,7 @@ void kbfunc_client_grouptoggle(struct client_ctx *cc, union arg *arg) { if (arg->i == 0) { - /* XXX for stupid X apps like xpdf and gvim */ + /* For X apps that steal events. */ XGrabKeyboard(X_Dpy, cc->win, True, GrabModeAsync, GrabModeAsync, CurrentTime); } From f467838e7b1045c43f2b2ad9622736a614c8c58f Mon Sep 17 00:00:00 2001 From: okan Date: Thu, 27 Aug 2015 18:42:56 +0000 Subject: [PATCH 19/21] Add consistent checks against NULL. --- client.c | 9 +++++---- xevents.c | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/client.c b/client.c index f30910a..396ba70 100644 --- a/client.c +++ b/client.c @@ -204,7 +204,7 @@ client_setactive(struct client_ctx *cc) if (cc->flags & CLIENT_WM_TAKE_FOCUS) client_msg(cc, cwmh[WM_TAKE_FOCUS], Last_Event_Time); - if ((oldcc = client_current())) { + if ((oldcc = client_current()) != NULL) { oldcc->flags &= ~CLIENT_ACTIVE; client_draw_border(oldcc); } @@ -707,9 +707,10 @@ client_cycle_leave(struct screen_ctx *sc) sc->cycling = 0; - if ((cc = client_current())) { + if ((cc = client_current()) != NULL) { client_mtf(cc); - group_toggle_membership_leave(cc); + cc->flags &= ~CLIENT_HIGHLIGHT; + client_draw_border(cc); XUngrabKeyboard(X_Dpy, CurrentTime); } } @@ -914,7 +915,7 @@ client_transient(struct client_ctx *cc) Window trans; if (XGetTransientForHint(X_Dpy, cc->win, &trans)) { - if ((tc = client_find(trans)) && tc->group) { + if ((tc = client_find(trans)) != NULL && tc->group) { group_movetogroup(cc, tc->group->num); if (tc->flags & CLIENT_IGNORE) cc->flags |= CLIENT_IGNORE; diff --git a/xevents.c b/xevents.c index f75f8b5..33b6ea0 100644 --- a/xevents.c +++ b/xevents.c @@ -77,7 +77,7 @@ xev_handle_maprequest(XEvent *ee) XMapRequestEvent *e = &ee->xmaprequest; struct client_ctx *cc = NULL, *old_cc; - if ((old_cc = client_current())) + if ((old_cc = client_current()) != NULL) client_ptrsave(old_cc); if ((cc = client_find(e->window)) == NULL) @@ -252,7 +252,7 @@ xev_handle_buttonrelease(XEvent *ee) { struct client_ctx *cc; - if ((cc = client_current())) + if ((cc = client_current()) != NULL) group_toggle_membership_leave(cc); } @@ -339,7 +339,7 @@ xev_handle_clientmessage(XEvent *ee) } } else if (e->message_type == ewmh[_NET_ACTIVE_WINDOW]) { if ((cc = client_find(e->window)) != NULL) { - if ((old_cc = client_current())) + if ((old_cc = client_current()) != NULL) client_ptrsave(old_cc); client_ptrwarp(cc); } From 28d4001ecaf57a722ec418f8b8b955242402e5a2 Mon Sep 17 00:00:00 2001 From: okan Date: Thu, 27 Aug 2015 18:53:14 +0000 Subject: [PATCH 20/21] Mechanical change: group->gc --- calmwm.h | 2 +- client.c | 14 +++++++------- group.c | 12 ++++++------ search.c | 2 +- xutil.c | 4 ++-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/calmwm.h b/calmwm.h index 08631ad..039dc36 100644 --- a/calmwm.h +++ b/calmwm.h @@ -147,6 +147,7 @@ struct client_ctx { TAILQ_ENTRY(client_ctx) entry; TAILQ_ENTRY(client_ctx) group_entry; struct screen_ctx *sc; + struct group_ctx *gc; Window win; Colormap colormap; unsigned int bwidth; /* border width */ @@ -198,7 +199,6 @@ struct client_ctx { char *name; char *label; char *matchname; - struct group_ctx *group; XClassHint ch; XWMHints *wmh; }; diff --git a/client.c b/client.c index 396ba70..54eced1 100644 --- a/client.c +++ b/client.c @@ -163,8 +163,8 @@ client_delete(struct client_ctx *cc) xu_ewmh_net_client_list(sc); xu_ewmh_net_client_list_stacking(sc); - if (cc->group != NULL) - TAILQ_REMOVE(&cc->group->clientq, cc, group_entry); + if (cc->gc != NULL) + TAILQ_REMOVE(&cc->gc->clientq, cc, group_entry); if (cc == client_current()) client_none(sc); @@ -682,7 +682,7 @@ client_cycle(struct screen_ctx *sc, int flags) /* Only cycle visible and non-ignored windows. */ if ((newcc->flags & (CLIENT_HIDDEN | CLIENT_IGNORE)) || ((flags & CWM_INGROUP) && - (newcc->group != oldcc->group))) + (newcc->gc != oldcc->gc))) again = 1; /* Is oldcc the only non-hidden window? */ @@ -915,8 +915,8 @@ client_transient(struct client_ctx *cc) Window trans; if (XGetTransientForHint(X_Dpy, cc->win, &trans)) { - if ((tc = client_find(trans)) != NULL && tc->group) { - group_movetogroup(cc, tc->group->num); + if ((tc = client_find(trans)) != NULL && tc->gc) { + group_movetogroup(cc, tc->gc->num); if (tc->flags & CLIENT_IGNORE) cc->flags |= CLIENT_IGNORE; } @@ -961,7 +961,7 @@ void client_htile(struct client_ctx *cc) { struct client_ctx *ci; - struct group_ctx *gc = cc->group; + struct group_ctx *gc = cc->gc; struct screen_ctx *sc = cc->sc; struct geom area; int i, n, mh, x, h, w; @@ -1020,7 +1020,7 @@ void client_vtile(struct client_ctx *cc) { struct client_ctx *ci; - struct group_ctx *gc = cc->group; + struct group_ctx *gc = cc->gc; struct screen_ctx *sc = cc->sc; struct geom area; int i, n, mw, y, h, w; diff --git a/group.c b/group.c index 3cb5e79..c455bcd 100644 --- a/group.c +++ b/group.c @@ -45,15 +45,15 @@ const char *num_to_name[] = { void group_assign(struct group_ctx *gc, struct client_ctx *cc) { - if (cc->group != NULL) - TAILQ_REMOVE(&cc->group->clientq, cc, group_entry); + if (cc->gc != NULL) + TAILQ_REMOVE(&cc->gc->clientq, cc, group_entry); if ((gc != NULL) && (gc->num == 0)) gc = NULL; - cc->group = gc; + cc->gc = gc; - if (cc->group != NULL) + if (cc->gc != NULL) TAILQ_INSERT_TAIL(&gc->clientq, cc, group_entry); xu_ewmh_net_wm_desktop(cc); @@ -162,7 +162,7 @@ group_movetogroup(struct client_ctx *cc, int idx) break; } - if (cc->group == gc) + if (cc->gc == gc) return; if (group_holds_only_hidden(gc)) client_hide(cc); @@ -175,7 +175,7 @@ group_toggle_membership_enter(struct client_ctx *cc) struct screen_ctx *sc = cc->sc; struct group_ctx *gc = sc->group_active; - if (gc == cc->group) { + if (gc == cc->gc) { group_assign(NULL, cc); cc->flags |= CLIENT_UNGROUP; } else { diff --git a/search.c b/search.c index 3192bff..aa409e0 100644 --- a/search.c +++ b/search.c @@ -156,7 +156,7 @@ search_print_client(struct menu *mi, int list) cc->matchname = cc->name; (void)snprintf(mi->print, sizeof(mi->print), "(%d) %c[%s] %s", - (cc->group) ? cc->group->num : 0, flag, + (cc->gc) ? cc->gc->num : 0, flag, (cc->label) ? cc->label : "", cc->matchname); } diff --git a/xutil.c b/xutil.c index f61aeef..a831794 100644 --- a/xutil.c +++ b/xutil.c @@ -362,8 +362,8 @@ xu_ewmh_net_wm_desktop(struct client_ctx *cc) { long num = 0xffffffff; - if (cc->group) - num = cc->group->num; + if (cc->gc) + num = cc->gc->num; XChangeProperty(X_Dpy, cc->win, ewmh[_NET_WM_DESKTOP], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&num, 1); From 47a10cc05549b0a94e3606ca7be9fe626754d12d Mon Sep 17 00:00:00 2001 From: okan Date: Fri, 28 Aug 2015 12:07:28 +0000 Subject: [PATCH 21/21] Lost fix from r1.112; add comment. Reported (again!) by Peter Kane. --- kbfunc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kbfunc.c b/kbfunc.c index 8d220a6..c23e8f8 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -181,7 +181,8 @@ kbfunc_menu_cmd(struct client_ctx *cc, union arg *arg) if ((strcmp(cmd->name, "lock") == 0) || (strcmp(cmd->name, "term") == 0)) continue; - menuq_add(&menuq, cmd, NULL); + /* search_match_text() needs mi->text */ + menuq_add(&menuq, cmd, "%s", cmd->name); } if ((mi = menu_filter(sc, &menuq, "application", NULL, 0,