diff options
author | Christian Neukirchen <chneukirchen@gmail.com> | 2014-09-07 15:47:44 +0000 |
---|---|---|
committer | Christian Neukirchen <chneukirchen@gmail.com> | 2014-09-07 15:47:44 +0000 |
commit | 9e560bd745c4ba9cb47bd242bc93a09b296cb779 (patch) | |
tree | faf0c6a5fe0935f5947c46d4ddc33f2a3cc38eb3 | |
parent | 870418ff684caae3b1dac508e6ab0103c8039a5b (diff) | |
parent | f7af0ebd7267cdfd4e7b9c12bb910992f1a094e5 (diff) | |
download | cwm-9e560bd745c4ba9cb47bd242bc93a09b296cb779.tar.gz cwm-9e560bd745c4ba9cb47bd242bc93a09b296cb779.tar.xz cwm-9e560bd745c4ba9cb47bd242bc93a09b296cb779.zip |
cvsimport
-rw-r--r-- | calmwm.c | 23 | ||||
-rw-r--r-- | calmwm.h | 24 | ||||
-rw-r--r-- | client.c | 19 | ||||
-rw-r--r-- | conf.c | 89 | ||||
-rw-r--r-- | cwm.1 | 4 | ||||
-rw-r--r-- | cwmrc.5 | 4 | ||||
-rw-r--r-- | group.c | 241 | ||||
-rw-r--r-- | kbfunc.c | 37 | ||||
-rw-r--r-- | menu.c | 4 | ||||
-rw-r--r-- | mousefunc.c | 34 | ||||
-rw-r--r-- | screen.c | 9 | ||||
-rw-r--r-- | search.c | 2 | ||||
-rw-r--r-- | xevents.c | 2 | ||||
-rw-r--r-- | xutil.c | 63 |
14 files changed, 271 insertions, 284 deletions
diff --git a/calmwm.c b/calmwm.c index e78b912..3c76bb4 100644 --- a/calmwm.c +++ b/calmwm.c @@ -48,7 +48,7 @@ struct conf Conf; const char *homedir; volatile sig_atomic_t cwm_status; -static void sigchld_cb(int); +static void sighdlr(int); static int x_errorhandler(Display *, XErrorEvent *); static void x_init(const char *); static void x_restart(char **); @@ -84,7 +84,7 @@ main(int argc, char **argv) argc -= optind; argv += optind; - if (signal(SIGCHLD, sigchld_cb) == SIG_ERR) + if (signal(SIGCHLD, sighdlr) == SIG_ERR) err(1, "signal"); if ((homedir = getenv("HOME")) == NULL || *homedir == '\0') { @@ -205,16 +205,19 @@ x_errorhandler(Display *dpy, XErrorEvent *e) } static void -sigchld_cb(int which) +sighdlr(int sig) { pid_t pid; - int save_errno = errno; - int status; - - /* Collect dead children. */ - while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || - (pid < 0 && errno == EINTR)) - ; + int save_errno = errno, status; + + switch (sig) { + case SIGCHLD: + /* Collect dead children. */ + while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0 || + (pid < 0 && errno == EINTR)) + ; + break; + } errno = save_errno; } diff --git a/calmwm.h b/calmwm.h index e5fa2c8..02f31d1 100644 --- a/calmwm.h +++ b/calmwm.h @@ -199,6 +199,7 @@ struct client_ctx { #define CLIENT_WM_TAKE_FOCUS 0x0200 #define CLIENT_URGENCY 0x0400 #define CLIENT_FULLSCREEN 0x0800 +#define CLIENT_STICKY 0x1000 #define CLIENT_HIGHLIGHT (CLIENT_GROUP | CLIENT_UNGROUP) #define CLIENT_MAXFLAGS (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED) @@ -222,10 +223,8 @@ TAILQ_HEAD(cycle_entry_q, client_ctx); struct group_ctx { TAILQ_ENTRY(group_ctx) entry; struct client_ctx_q clients; - int shortcut; - int hidden; - int nhidden; - int highstack; + char *name; + int num; }; TAILQ_HEAD(group_ctx_q, group_ctx); @@ -263,9 +262,7 @@ struct screen_ctx { struct group_ctx groups[CALMWM_NGROUPS]; struct group_ctx_q groupq; int group_hideall; - int group_nonames; struct group_ctx *group_active; - char **group_names; }; TAILQ_HEAD(screen_ctx_q, screen_ctx); @@ -316,8 +313,6 @@ struct conf { int snapdist; struct gap gap; char *color[CWM_COLOR_NITEMS]; - char termpath[MAXPATHLEN]; - char lockpath[MAXPATHLEN]; char known_hosts[MAXPATHLEN]; #define CONF_FONT "sans-serif:pixelsize=14:bold" char *font; @@ -371,7 +366,8 @@ enum { _NET_WM_DESKTOP, _NET_CLOSE_WINDOW, _NET_WM_STATE, -#define _NET_WM_STATES_NITEMS 4 +#define _NET_WM_STATES_NITEMS 5 + _NET_WM_STATE_STICKY, _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_FULLSCREEN, @@ -418,6 +414,7 @@ void client_set_wm_state(struct client_ctx *, long); void client_setactive(struct client_ctx *); void client_setname(struct client_ctx *); int client_snapcalc(int, int, int, int, int); +void client_sticky(struct client_ctx *); void client_transient(struct client_ctx *); void client_unhide(struct client_ctx *); void client_urgency(struct client_ctx *); @@ -429,12 +426,13 @@ void client_wm_hints(struct client_ctx *); void group_alltoggle(struct screen_ctx *); void group_autogroup(struct client_ctx *); void group_cycle(struct screen_ctx *, int); +int group_hidden_state(struct group_ctx *); +void group_hide(struct screen_ctx *, struct group_ctx *); void group_hidetoggle(struct screen_ctx *, int); void group_init(struct screen_ctx *); -void group_menu(struct screen_ctx *); void group_movetogroup(struct client_ctx *, int); void group_only(struct screen_ctx *, int); -void group_set_state(struct screen_ctx *); +void group_show(struct screen_ctx *, struct group_ctx *); void group_sticky(struct client_ctx *); void group_sticky_toggle_enter(struct client_ctx *); void group_sticky_toggle_exit(struct client_ctx *); @@ -487,6 +485,7 @@ void kbfunc_client_nogroup(struct client_ctx *, void kbfunc_client_raise(struct client_ctx *, union arg *); void kbfunc_client_rcycle(struct client_ctx *, union arg *); void kbfunc_client_search(struct client_ctx *, union arg *); +void kbfunc_client_sticky(struct client_ctx *, union arg *); void kbfunc_client_vmaximize(struct client_ctx *, union arg *); void kbfunc_cmdexec(struct client_ctx *, union arg *); @@ -564,8 +563,7 @@ void xu_ewmh_net_wm_number_of_desktops(struct screen_ctx *); void xu_ewmh_net_showing_desktop(struct screen_ctx *); void xu_ewmh_net_virtual_roots(struct screen_ctx *); void xu_ewmh_net_current_desktop(struct screen_ctx *, long); -void xu_ewmh_net_desktop_names(struct screen_ctx *, char *, - int); +void xu_ewmh_net_desktop_names(struct screen_ctx *); void xu_ewmh_net_wm_desktop(struct client_ctx *); Atom *xu_ewmh_get_net_wm_state(struct client_ctx *, int *); diff --git a/client.c b/client.c index adc2f9c..6e5781c 100644 --- a/client.c +++ b/client.c @@ -239,6 +239,17 @@ client_freeze(struct client_ctx *cc) } void +client_sticky(struct client_ctx *cc) +{ + if (cc->flags & CLIENT_STICKY) + cc->flags &= ~CLIENT_STICKY; + else + cc->flags |= CLIENT_STICKY; + + xu_ewmh_set_net_wm_state(cc); +} + +void client_fullscreen(struct client_ctx *cc) { struct screen_ctx *sc = cc->sc; @@ -468,6 +479,9 @@ 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->active = 0; @@ -481,6 +495,9 @@ 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; @@ -869,7 +886,7 @@ client_transient(struct client_ctx *cc) if (XGetTransientForHint(X_Dpy, cc->win, &trans)) { if ((tc = client_find(trans)) && tc->group) { - group_movetogroup(cc, tc->group->shortcut); + group_movetogroup(cc, tc->group->num); if (tc->flags & CLIENT_IGNORE) cc->flags |= CLIENT_IGNORE; } diff --git a/conf.c b/conf.c index 8b3c5da..390368c 100644 --- a/conf.c +++ b/conf.c @@ -41,27 +41,19 @@ conf_cmd_add(struct conf *c, const char *name, const char *path) { struct cmd *cmd; - /* "term" and "lock" have special meanings. */ - if (strcmp(name, "term") == 0) { - if (strlcpy(c->termpath, path, sizeof(c->termpath)) >= - sizeof(c->termpath)) - return (0); - } else if (strcmp(name, "lock") == 0) { - if (strlcpy(c->lockpath, path, sizeof(c->lockpath)) >= - sizeof(c->lockpath)) - return (0); - } else { - conf_cmd_remove(c, name); - - cmd = xmalloc(sizeof(*cmd)); + cmd = xmalloc(sizeof(*cmd)); - cmd->name = xstrdup(name); - if (strlcpy(cmd->path, path, sizeof(cmd->path)) >= - sizeof(cmd->path)) - return (0); - TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry); + cmd->name = xstrdup(name); + if (strlcpy(cmd->path, path, sizeof(cmd->path)) >= sizeof(cmd->path)) { + free(cmd->name); + free(cmd); + return(0); } - return (1); + + conf_cmd_remove(c, name); + + TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry); + return(1); } static void @@ -78,7 +70,7 @@ conf_cmd_remove(struct conf *c, const char *name) } } void -conf_autogroup(struct conf *c, int no, const char *val) +conf_autogroup(struct conf *c, int num, const char *val) { struct autogroupwin *aw; char *p; @@ -93,7 +85,7 @@ conf_autogroup(struct conf *c, int no, const char *val) aw->name = xstrdup(val); aw->class = xstrdup(p); } - aw->num = no; + aw->num = num; TAILQ_INSERT_TAIL(&c->autogroupq, aw, entry); } @@ -204,6 +196,7 @@ static const struct { { "CM-g", "grouptoggle" }, { "CM-f", "fullscreen" }, { "CM-m", "maximize" }, + { "CM-s", "sticky" }, { "CM-equal", "vmaximize" }, { "CMS-equal", "hmaximize" }, { "CMS-f", "freeze" }, @@ -250,8 +243,6 @@ conf_init(struct conf *c) { unsigned int i; - (void)memset(c, 0, sizeof(*c)); - c->bwidth = CONF_BWIDTH; c->mamount = CONF_MAMOUNT; c->snapdist = CONF_SNAPDIST; @@ -346,7 +337,7 @@ static const struct { void (*handler)(struct client_ctx *, union arg *); int flags; union arg argument; -} name_to_kbfunc[] = { +} name_to_func[] = { { "lower", kbfunc_client_lower, CWM_WIN, {0} }, { "raise", kbfunc_client_raise, CWM_WIN, {0} }, { "search", kbfunc_client_search, 0, {0} }, @@ -391,6 +382,7 @@ static const struct { { "rcycleingroup", kbfunc_client_cycle, CWM_WIN, {.i = CWM_RCYCLE|CWM_INGROUP} }, { "grouptoggle", kbfunc_client_grouptoggle, CWM_WIN, {0}}, + { "sticky", kbfunc_client_sticky, CWM_WIN, {0} }, { "fullscreen", kbfunc_client_fullscreen, CWM_WIN, {0} }, { "maximize", kbfunc_client_maximize, CWM_WIN, {0} }, { "vmaximize", kbfunc_client_vmaximize, CWM_WIN, {0} }, @@ -453,6 +445,15 @@ static const struct { {.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} }, + { "window_raise", kbfunc_client_raise, CWM_WIN, {0} }, + { "window_hide", kbfunc_client_hide, CWM_WIN, {0} }, + { "window_move", mousefunc_client_move, CWM_WIN, {0} }, + { "window_resize", mousefunc_client_resize, CWM_WIN, {0} }, + { "window_grouptoggle", mousefunc_client_grouptoggle, CWM_WIN, {0} }, + { "menu_group", mousefunc_menu_group, 0, {0} }, + { "menu_unhide", mousefunc_menu_unhide, 0, {0} }, + { "menu_cmd", mousefunc_menu_cmd, 0, {0} }, }; static const struct { @@ -510,13 +511,13 @@ conf_bind_kbd(struct conf *c, const char *bind, const char *cmd) return (1); } - for (i = 0; i < nitems(name_to_kbfunc); i++) { - if (strcmp(name_to_kbfunc[i].tag, cmd) != 0) + for (i = 0; i < nitems(name_to_func); i++) { + if (strcmp(name_to_func[i].tag, cmd) != 0) continue; - kb->callback = name_to_kbfunc[i].handler; - kb->flags = name_to_kbfunc[i].flags; - kb->argument = name_to_kbfunc[i].argument; + kb->callback = name_to_func[i].handler; + kb->flags = name_to_func[i].flags; + kb->argument = name_to_func[i].argument; kb->argtype |= ARG_INT; TAILQ_INSERT_TAIL(&c->keybindingq, kb, entry); return (1); @@ -548,25 +549,6 @@ conf_unbind_kbd(struct conf *c, struct binding *unbind) } } -static const struct { - const char *tag; - void (*handler)(struct client_ctx *, union arg *); - int flags; - union arg argument; -} name_to_mousefunc[] = { - { "window_lower", kbfunc_client_lower, CWM_WIN, {0} }, - { "window_raise", kbfunc_client_raise, CWM_WIN, {0} }, - { "window_hide", kbfunc_client_hide, CWM_WIN, {0} }, - { "cyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_CYCLE} }, - { "rcyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_RCYCLE} }, - { "window_move", mousefunc_client_move, CWM_WIN, {0} }, - { "window_resize", mousefunc_client_resize, CWM_WIN, {0} }, - { "window_grouptoggle", mousefunc_client_grouptoggle, CWM_WIN, {0} }, - { "menu_group", mousefunc_menu_group, 0, {0} }, - { "menu_unhide", mousefunc_menu_unhide, 0, {0} }, - { "menu_cmd", mousefunc_menu_cmd, 0, {0} }, -}; - int conf_bind_mouse(struct conf *c, const char *bind, const char *cmd) { @@ -593,13 +575,13 @@ conf_bind_mouse(struct conf *c, const char *bind, const char *cmd) return (1); } - for (i = 0; i < nitems(name_to_mousefunc); i++) { - if (strcmp(name_to_mousefunc[i].tag, cmd) != 0) + for (i = 0; i < nitems(name_to_func); i++) { + if (strcmp(name_to_func[i].tag, cmd) != 0) continue; - mb->callback = name_to_mousefunc[i].handler; - mb->flags = name_to_mousefunc[i].flags; - mb->argument = name_to_mousefunc[i].argument; + mb->callback = name_to_func[i].handler; + mb->flags = name_to_func[i].flags; + mb->argument = name_to_func[i].argument; TAILQ_INSERT_TAIL(&c->mousebindingq, mb, entry); return (1); } @@ -690,6 +672,7 @@ static char *ewmhints[] = { "_NET_WM_DESKTOP", "_NET_CLOSE_WINDOW", "_NET_WM_STATE", + "_NET_WM_STATE_STICKY", "_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ", "_NET_WM_STATE_FULLSCREEN", diff --git a/cwm.1 b/cwm.1 index b3a5c3d..eb6c9e7 100644 --- a/cwm.1 +++ b/cwm.1 @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: December 16 2013 $ +.Dd $Mdocdate$ .Dt CWM 1 .Os .Sh NAME @@ -90,6 +90,8 @@ Cycle through active groups. Reverse cycle through active groups. .It Ic CMS-f Toggle freezing geometry of current window. +.It Ic CM-s +Toggle stickiness of current window. .It Ic CM-f Toggle full-screen mode of current window. .It Ic CM-m diff --git a/cwmrc.5 b/cwmrc.5 index bc6e9c2..a0b39d3 100644 --- a/cwmrc.5 +++ b/cwmrc.5 @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: December 16 2013 $ +.Dd $Mdocdate$ .Dt CWMRC 5 .Os .Sh NAME @@ -341,6 +341,8 @@ Raise current window. Label current window. .It freeze Freeze current window geometry. +.It sticky +Stick current window to all groups (same as assigning to nogroup). .It fullscreen Full-screen current window (gap + border removed). .It maximize diff --git a/group.c b/group.c index 8ad372e..cdc5912 100644 --- a/group.c +++ b/group.c @@ -33,13 +33,10 @@ #include "calmwm.h" static void group_assign(struct group_ctx *, struct client_ctx *); -static void group_hide(struct screen_ctx *, struct group_ctx *); -static void group_show(struct screen_ctx *, struct group_ctx *); -static void group_fix_hidden_state(struct group_ctx *); +static void group_restack(struct screen_ctx *, struct group_ctx *); static void group_setactive(struct screen_ctx *, long); -static void group_set_names(struct screen_ctx *); -const char *shortcut_to_name[] = { +const char *num_to_name[] = { "nogroup", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; @@ -47,63 +44,62 @@ const char *shortcut_to_name[] = { static void group_assign(struct group_ctx *gc, struct client_ctx *cc) { - if (gc == NULL) - gc = TAILQ_FIRST(&cc->sc->groupq); - if (cc->group == gc) - return; - if (cc->group != NULL) TAILQ_REMOVE(&cc->group->clients, cc, group_entry); - TAILQ_INSERT_TAIL(&gc->clients, cc, group_entry); cc->group = gc; + if (cc->group != NULL) + TAILQ_INSERT_TAIL(&gc->clients, cc, group_entry); + xu_ewmh_net_wm_desktop(cc); } -static void +void group_hide(struct screen_ctx *sc, struct group_ctx *gc) { struct client_ctx *cc; screen_updatestackingorder(sc); - gc->nhidden = 0; - gc->highstack = 0; - TAILQ_FOREACH(cc, &gc->clients, group_entry) { + TAILQ_FOREACH(cc, &gc->clients, group_entry) client_hide(cc); - gc->nhidden++; - if (cc->stackingorder > gc->highstack) - gc->highstack = cc->stackingorder; - } - gc->hidden = 1; /* XXX: equivalent to gc->nhidden > 0 */ } -static void +void group_show(struct screen_ctx *sc, struct group_ctx *gc) { struct client_ctx *cc; + + TAILQ_FOREACH(cc, &gc->clients, group_entry) + client_unhide(cc); + + group_restack(sc, gc); + group_setactive(sc, gc->num); +} + +static void +group_restack(struct screen_ctx *sc, struct group_ctx *gc) +{ + struct client_ctx *cc; Window *winlist; int i, lastempty = -1; + int nwins = 0, highstack = 0; - gc->highstack = 0; TAILQ_FOREACH(cc, &gc->clients, group_entry) { - if (cc->stackingorder > gc->highstack) - gc->highstack = cc->stackingorder; + if (cc->stackingorder > highstack) + highstack = cc->stackingorder; } - winlist = xcalloc((gc->highstack + 1), sizeof(*winlist)); + winlist = xcalloc((highstack + 1), sizeof(*winlist)); - /* - * Invert the stacking order as XRestackWindows() expects them - * top-to-bottom. - */ + /* Invert the stacking order for XRestackWindows(). */ TAILQ_FOREACH(cc, &gc->clients, group_entry) { - winlist[gc->highstack - cc->stackingorder] = cc->win; - client_unhide(cc); + winlist[highstack - cc->stackingorder] = cc->win; + nwins++; } /* Un-sparseify */ - for (i = 0; i <= gc->highstack; i++) { + for (i = 0; i <= highstack; i++) { if (!winlist[i] && lastempty == -1) lastempty = i; else if (winlist[i] && lastempty != -1) { @@ -113,11 +109,8 @@ group_show(struct screen_ctx *sc, struct group_ctx *gc) } } - XRestackWindows(X_Dpy, winlist, gc->nhidden); + XRestackWindows(X_Dpy, winlist, nwins); free(winlist); - - gc->hidden = 0; - group_setactive(sc, gc->shortcut); } void @@ -127,19 +120,15 @@ group_init(struct screen_ctx *sc) TAILQ_INIT(&sc->groupq); sc->group_hideall = 0; - /* - * See if any group names have already been set and update the - * property with ours if they'll have changed. - */ - group_update_names(sc); for (i = 0; i < CALMWM_NGROUPS; i++) { TAILQ_INIT(&sc->groups[i].clients); - sc->groups[i].hidden = 0; - sc->groups[i].shortcut = i; + sc->groups[i].name = xstrdup(num_to_name[i]); + sc->groups[i].num = i; TAILQ_INSERT_TAIL(&sc->groupq, &sc->groups[i], entry); } + xu_ewmh_net_desktop_names(sc); xu_ewmh_net_wm_desktop_viewport(sc); xu_ewmh_net_wm_number_of_desktops(sc); xu_ewmh_net_showing_desktop(sc); @@ -148,15 +137,6 @@ group_init(struct screen_ctx *sc) group_setactive(sc, 1); } -void -group_set_state(struct screen_ctx *sc) -{ - struct group_ctx *gc; - - TAILQ_FOREACH(gc, &sc->groupq, entry) - group_fix_hidden_state(gc); -} - static void group_setactive(struct screen_ctx *sc, long idx) { @@ -175,12 +155,11 @@ group_movetogroup(struct client_ctx *cc, int idx) errx(1, "group_movetogroup: index out of range (%d)", idx); gc = &sc->groups[idx]; + if (cc->group == gc) return; - if (gc->hidden) { + if (group_hidden_state(gc)) client_hide(cc); - gc->nhidden++; - } group_assign(gc, cc); } @@ -212,21 +191,25 @@ group_sticky_toggle_exit(struct client_ctx *cc) } /* - * if group_hidetoggle would produce no effect, toggle the group's hidden state + * If all clients in a group are hidden, then the group state is hidden. */ -static void -group_fix_hidden_state(struct group_ctx *gc) +int +group_hidden_state(struct group_ctx *gc) { struct client_ctx *cc; - int same = 0; + int hidden = 0, same = 0; TAILQ_FOREACH(cc, &gc->clients, group_entry) { - if (gc->hidden == ((cc->flags & CLIENT_HIDDEN) ? 1 : 0)) + if (cc->flags & CLIENT_STICKY) + continue; + if (hidden == ((cc->flags & CLIENT_HIDDEN) ? 1 : 0)) same++; } if (same == 0) - gc->hidden = !gc->hidden; + hidden = !hidden; + + return(hidden); } void @@ -238,9 +221,8 @@ group_hidetoggle(struct screen_ctx *sc, int idx) errx(1, "group_hidetoggle: index out of range (%d)", idx); gc = &sc->groups[idx]; - group_fix_hidden_state(gc); - if (gc->hidden) + if (group_hidden_state(gc)) group_show(sc, gc); else { group_hide(sc, gc); @@ -259,7 +241,7 @@ group_only(struct screen_ctx *sc, int idx) errx(1, "group_only: index out of range (%d)", idx); TAILQ_FOREACH(gc, &sc->groupq, entry) { - if (gc->shortcut == idx) + if (gc->num == idx) group_show(sc, gc); else group_hide(sc, gc); @@ -288,7 +270,7 @@ group_cycle(struct screen_ctx *sc, int flags) if (!TAILQ_EMPTY(&gc->clients) && showgroup == NULL) showgroup = gc; - else if (!gc->hidden) + else if (!group_hidden_state(gc)) group_hide(sc, gc); } @@ -297,39 +279,10 @@ group_cycle(struct screen_ctx *sc, int flags) group_hide(sc, sc->group_active); - if (showgroup->hidden) + if (group_hidden_state(showgroup)) group_show(sc, showgroup); else - group_setactive(sc, showgroup->shortcut); -} - -void -group_menu(struct screen_ctx *sc) -{ - struct group_ctx *gc; - struct menu *mi; - struct menu_q menuq; - - TAILQ_INIT(&menuq); - - TAILQ_FOREACH(gc, &sc->groupq, entry) { - if (TAILQ_EMPTY(&gc->clients)) - continue; - - menuq_add(&menuq, gc, gc->hidden ? "%d: [%s]" : "%d: %s", - gc->shortcut, sc->group_names[gc->shortcut]); - } - - if (TAILQ_EMPTY(&menuq)) - return; - - mi = menu_filter(sc, &menuq, NULL, NULL, 0, NULL, NULL); - if (mi != NULL && mi->ctx != NULL) { - gc = (struct group_ctx *)mi->ctx; - (gc->hidden) ? group_show(sc, gc) : group_hide(sc, gc); - } - - menuq_clear(&menuq); + group_setactive(sc, showgroup->num); } void @@ -352,36 +305,38 @@ group_autogroup(struct client_ctx *cc) struct screen_ctx *sc = cc->sc; struct autogroupwin *aw; struct group_ctx *gc; - int no = -1, both_match = 0; - long *grpno; + int num = -2, both_match = 0; + long *grpnum; if (cc->ch.res_class == NULL || cc->ch.res_name == NULL) return; if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP], - XA_CARDINAL, 1, (unsigned char **)&grpno) > 0) { - if (*grpno == -1) - no = 0; - else if (*grpno > CALMWM_NGROUPS || *grpno < 0) - no = CALMWM_NGROUPS - 1; - else - no = *grpno; - XFree(grpno); + 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)) { - no = aw->num; + num = aw->num; both_match = 1; } else if (aw->name == NULL && !both_match) - no = aw->num; + num = aw->num; } } } + if ((num == -1) || (num == 0)) { + group_assign(NULL, cc); + return; + } + TAILQ_FOREACH(gc, &sc->groupq, entry) { - if (gc->shortcut == no) { + if (gc->num == num) { group_assign(gc, cc); return; } @@ -392,71 +347,3 @@ group_autogroup(struct client_ctx *cc) else group_assign(NULL, cc); } - -void -group_update_names(struct screen_ctx *sc) -{ - char **strings, *p; - unsigned char *prop_ret; - int i = 0, j = 0, nstrings = 0, n = 0, setnames = 0; - - if ((j = xu_getprop(sc->rootwin, ewmh[_NET_DESKTOP_NAMES], - cwmh[UTF8_STRING], 0xffffff, (unsigned char **)&prop_ret)) > 0) { - prop_ret[j - 1] = '\0'; /* paranoia */ - while (i < j) { - if (prop_ret[i++] == '\0') - nstrings++; - } - } - - strings = xcalloc((nstrings < CALMWM_NGROUPS ? CALMWM_NGROUPS : - nstrings), sizeof(*strings)); - - p = (char *)prop_ret; - while (n < nstrings) { - strings[n++] = xstrdup(p); - p += strlen(p) + 1; - } - /* - * make sure we always set our defaults if nothing is there to - * replace them. - */ - if (n < CALMWM_NGROUPS) { - setnames = 1; - i = 0; - while (n < CALMWM_NGROUPS) - strings[n++] = xstrdup(shortcut_to_name[i++]); - } - - if (prop_ret != NULL) - XFree(prop_ret); - if (sc->group_nonames != 0) - free(sc->group_names); - - sc->group_names = strings; - sc->group_nonames = n; - if (setnames) - group_set_names(sc); -} - -static void -group_set_names(struct screen_ctx *sc) -{ - char *p, *q; - size_t len = 0, tlen, slen; - int i; - - for (i = 0; i < sc->group_nonames; i++) - len += strlen(sc->group_names[i]) + 1; - q = p = xcalloc(len, sizeof(*p)); - - tlen = len; - for (i = 0; i < sc->group_nonames; i++) { - slen = strlen(sc->group_names[i]) + 1; - (void)strlcpy(q, sc->group_names[i], tlen); - tlen -= slen; - q += slen; - } - - xu_ewmh_net_desktop_names(sc, p, len); -} diff --git a/kbfunc.c b/kbfunc.c index 513c81c..78cb9fd 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -159,7 +159,6 @@ kbfunc_client_search(struct client_ctx *cc, union arg *arg) cc = (struct client_ctx *)mi->ctx; if (cc->flags & CLIENT_HIDDEN) client_unhide(cc); - if (old_cc) client_ptrsave(old_cc); client_ptrwarp(cc); @@ -214,13 +213,23 @@ kbfunc_cmdexec(struct client_ctx *cc, union arg *arg) void kbfunc_term(struct client_ctx *cc, union arg *arg) { - u_spawn(Conf.termpath); + struct cmd *cmd; + + TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { + if (strcmp(cmd->name, "term") == 0) + u_spawn(cmd->path); + } } void kbfunc_lock(struct client_ctx *cc, union arg *arg) { - u_spawn(Conf.lockpath); + struct cmd *cmd; + + TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { + if (strcmp(cmd->name, "lock") == 0) + u_spawn(cmd->path); + } } void @@ -310,12 +319,13 @@ void kbfunc_ssh(struct client_ctx *cc, union arg *arg) { struct screen_ctx *sc = cc->sc; + struct cmd *cmd; struct menu *mi; struct menu_q menuq; FILE *fp; char *buf, *lbuf, *p; char hostbuf[MAXHOSTNAMELEN]; - char cmd[256]; + char path[MAXPATHLEN]; int l; size_t len; @@ -324,6 +334,11 @@ kbfunc_ssh(struct client_ctx *cc, union arg *arg) return; } + TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { + if (strcmp(cmd->name, "term") == 0) + break; + } + TAILQ_INIT(&menuq); lbuf = NULL; @@ -356,10 +371,10 @@ kbfunc_ssh(struct client_ctx *cc, union arg *arg) search_match_exec, NULL)) != NULL) { if (mi->text[0] == '\0') goto out; - l = snprintf(cmd, sizeof(cmd), "%s -T '[ssh] %s' -e ssh %s", - Conf.termpath, mi->text, mi->text); - if (l != -1 && l < sizeof(cmd)) - u_spawn(cmd); + l = snprintf(path, sizeof(path), "%s -T '[ssh] %s' -e ssh %s", + cmd->path, mi->text, mi->text); + if (l != -1 && l < sizeof(path)) + u_spawn(path); } out: if (mi != NULL && mi->dummy) @@ -433,6 +448,12 @@ kbfunc_client_movetogroup(struct client_ctx *cc, union arg *arg) } void +kbfunc_client_sticky(struct client_ctx *cc, union arg *arg) +{ + client_sticky(cc); +} + +void kbfunc_client_fullscreen(struct client_ctx *cc, union arg *arg) { client_fullscreen(cc); diff --git a/menu.c b/menu.c index ebf1cbd..efbf756 100644 --- a/menu.c +++ b/menu.c @@ -260,7 +260,7 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq, * even if dummy is zero, we need to return something. */ if ((mi = TAILQ_FIRST(resultq)) == NULL) { - mi = xmalloc(sizeof *mi); + mi = xmalloc(sizeof(*mi)); (void)strlcpy(mi->text, mc->searchstr, sizeof(mi->text)); mi->dummy = 1; @@ -302,7 +302,7 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq, mc->list = !mc->list; break; case CTL_ABORT: - mi = xmalloc(sizeof *mi); + mi = xmalloc(sizeof(*mi)); mi->text[0] = '\0'; mi->dummy = 1; mi->abort = 1; diff --git a/mousefunc.c b/mousefunc.c index 9db0aa6..3442f67 100644 --- a/mousefunc.c +++ b/mousefunc.c @@ -181,7 +181,30 @@ mousefunc_client_grouptoggle(struct client_ctx *cc, union arg *arg) void mousefunc_menu_group(struct client_ctx *cc, union arg *arg) { - group_menu(cc->sc); + struct screen_ctx *sc = cc->sc; + struct group_ctx *gc; + struct menu *mi; + struct menu_q menuq; + + TAILQ_INIT(&menuq); + TAILQ_FOREACH(gc, &sc->groupq, entry) { + if (TAILQ_EMPTY(&gc->clients)) + continue; + menuq_add(&menuq, gc, + group_hidden_state(gc) ? "%d: [%s]" : "%d: %s", + gc->num, gc->name); + } + if (TAILQ_EMPTY(&menuq)) + return; + + if ((mi = menu_filter(sc, &menuq, NULL, NULL, 0, + NULL, NULL)) != NULL) { + gc = (struct group_ctx *)mi->ctx; + (group_hidden_state(gc)) ? + group_show(sc, gc) : group_hide(sc, gc); + } + + menuq_clear(&menuq); } void @@ -196,16 +219,15 @@ mousefunc_menu_unhide(struct client_ctx *cc, union arg *arg) old_cc = client_current(); TAILQ_INIT(&menuq); - TAILQ_FOREACH(cc, &Clientq, entry) + TAILQ_FOREACH(cc, &Clientq, entry) { if (cc->flags & CLIENT_HIDDEN) { wname = (cc->label) ? cc->label : cc->name; if (wname == NULL) continue; - menuq_add(&menuq, cc, "(%d) %s", - cc->group->shortcut, wname); + cc->group ? cc->group->num : 0, wname); } - + } if (TAILQ_EMPTY(&menuq)) return; @@ -213,7 +235,6 @@ mousefunc_menu_unhide(struct client_ctx *cc, union arg *arg) NULL, NULL)) != NULL) { cc = (struct client_ctx *)mi->ctx; client_unhide(cc); - if (old_cc != NULL) client_ptrsave(old_cc); client_ptrwarp(cc); @@ -233,7 +254,6 @@ mousefunc_menu_cmd(struct client_ctx *cc, union arg *arg) TAILQ_INIT(&menuq); TAILQ_FOREACH(cmd, &Conf.cmdq, entry) menuq_add(&menuq, cmd, "%s", cmd->name); - if (TAILQ_EMPTY(&menuq)) return; diff --git a/screen.c b/screen.c index 59fa992..02aefcc 100644 --- a/screen.c +++ b/screen.c @@ -69,7 +69,6 @@ screen_init(int which) XFree(wins); } screen_updatestackingorder(sc); - group_set_state(sc); if (HasRandr) XRRSelectInput(X_Dpy, sc->rootwin, RRScreenChangeNotifyMask); @@ -105,7 +104,7 @@ screen_updatestackingorder(struct screen_ctx *sc) if ((cc = client_find(wins[i])) == NULL || cc->flags & CLIENT_HIDDEN) continue; - + cc->stackingorder = s++; } XFree(wins); @@ -142,7 +141,7 @@ screen_update_geometry(struct screen_ctx *sc) { XineramaScreenInfo *info = NULL; struct region_ctx *region; - int info_no = 0, i; + int info_num = 0, i; sc->view.x = 0; sc->view.y = 0; @@ -156,13 +155,13 @@ screen_update_geometry(struct screen_ctx *sc) /* RandR event may have a CTRC added or removed. */ if (XineramaIsActive(X_Dpy)) - info = XineramaQueryScreens(X_Dpy, &info_no); + info = XineramaQueryScreens(X_Dpy, &info_num); while ((region = TAILQ_FIRST(&sc->regionq)) != NULL) { TAILQ_REMOVE(&sc->regionq, region, entry); free(region); } - for (i = 0; i < info_no; i++) { + for (i = 0; i < info_num; i++) { region = xmalloc(sizeof(*region)); region->num = i; region->area.x = info[i].x_org; diff --git a/search.c b/search.c index 980cb54..4012400 100644 --- a/search.c +++ b/search.c @@ -143,7 +143,7 @@ search_print_client(struct menu *mi, int list) cc->matchname = cc->name; (void)snprintf(mi->print, sizeof(mi->print), "(%d) %c%s", - cc->group->shortcut, flag, cc->matchname); + cc->group ? cc->group->num : 0, flag, cc->matchname); if (!list && cc->matchname != cc->name && strlen(mi->print) < sizeof(mi->print) - 1) { diff --git a/xevents.c b/xevents.c index 027f52a..c72bd0c 100644 --- a/xevents.c +++ b/xevents.c @@ -196,7 +196,7 @@ xev_handle_propertynotify(XEvent *ee) TAILQ_FOREACH(sc, &Screenq, entry) { if (sc->rootwin == e->window) { if (e->atom == ewmh[_NET_DESKTOP_NAMES]) - group_update_names(sc); + xu_ewmh_net_desktop_names(sc); } } } diff --git a/xutil.c b/xutil.c index 7d39ee4..dd5bbc1 100644 --- a/xutil.c +++ b/xutil.c @@ -281,20 +281,67 @@ xu_ewmh_net_current_desktop(struct screen_ctx *sc, long idx) } void -xu_ewmh_net_desktop_names(struct screen_ctx *sc, char *data, int n) +xu_ewmh_net_desktop_names(struct screen_ctx *sc) { + struct group_ctx *gc; + char *p, *q; + unsigned char *prop_ret; + int i = 0, j = 0, nstrings = 0, n = 0; + size_t len = 0, tlen, slen; + + /* Let group names be overwritten if _NET_DESKTOP_NAMES is set. */ + + if ((j = xu_getprop(sc->rootwin, ewmh[_NET_DESKTOP_NAMES], + cwmh[UTF8_STRING], 0xffffff, (unsigned char **)&prop_ret)) > 0) { + prop_ret[j - 1] = '\0'; /* paranoia */ + while (i < j) { + if (prop_ret[i++] == '\0') + nstrings++; + } + } + + p = (char *)prop_ret; + while (n < nstrings) { + TAILQ_FOREACH(gc, &sc->groupq, entry) { + if (gc->num == n) { + free(gc->name); + gc->name = xstrdup(p); + p += strlen(p) + 1; + break; + } + } + n++; + } + if (prop_ret != NULL) + XFree(prop_ret); + + TAILQ_FOREACH(gc, &sc->groupq, entry) + len += strlen(gc->name) + 1; + q = p = xcalloc(len, sizeof(*p)); + + tlen = len; + TAILQ_FOREACH(gc, &sc->groupq, entry) { + slen = strlen(gc->name) + 1; + (void)strlcpy(q, gc->name, tlen); + tlen -= slen; + q += slen; + } + XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_DESKTOP_NAMES], - cwmh[UTF8_STRING], 8, PropModeReplace, (unsigned char *)data, n); + cwmh[UTF8_STRING], 8, PropModeReplace, (unsigned char *)p, len); } /* Application Window Properties */ void xu_ewmh_net_wm_desktop(struct client_ctx *cc) { - long no = cc->group->shortcut; + long num = 0xffffffff; + + if (cc->group) + num = cc->group->num; XChangeProperty(X_Dpy, cc->win, ewmh[_NET_WM_DESKTOP], - XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&no, 1); + XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&num, 1); } Atom * @@ -323,6 +370,9 @@ xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action, int property; void (*toggle)(struct client_ctx *); } handlers[] = { + { _NET_WM_STATE_STICKY, + CLIENT_STICKY, + client_sticky }, { _NET_WM_STATE_MAXIMIZED_VERT, CLIENT_VMAXIMIZED, client_vmaximize }, @@ -364,6 +414,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[_NET_WM_STATE_STICKY]) + client_sticky(cc); if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_HORZ]) client_hmaximize(cc); if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_VERT]) @@ -388,10 +440,13 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc) if (oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_HORZ] && oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_VERT] && oatoms[i] != ewmh[_NET_WM_STATE_FULLSCREEN] && + oatoms[i] != ewmh[_NET_WM_STATE_STICKY] && oatoms[i] != ewmh[_NET_WM_STATE_DEMANDS_ATTENTION]) atoms[j++] = oatoms[i]; } free(oatoms); + if (cc->flags & CLIENT_STICKY) + atoms[j++] = ewmh[_NET_WM_STATE_STICKY]; if (cc->flags & CLIENT_FULLSCREEN) atoms[j++] = ewmh[_NET_WM_STATE_FULLSCREEN]; else { |