From b35cbf81d84c97e7c444aafe491597bd6db6cfab Mon Sep 17 00:00:00 2001 From: oga Date: Fri, 11 Dec 2009 17:51:42 +0000 Subject: Implement _NET_DESKTOP_NAMES, this one was a bit tricky since thespec says that a pager can change the property at any time (most need a clientmessage). So deal with property updates. Needed to shuffle some of the other code around since we can't just use shortcut_to_name[] everywhere now. ok okan@ --- calmwm.h | 17 +++++---- conf.c | 1 - group.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- parse.y | 18 +-------- xevents.c | 11 ++++++ xutil.c | 1 + 6 files changed, 139 insertions(+), 34 deletions(-) diff --git a/calmwm.h b/calmwm.h index 22210aa..212434e 100644 --- a/calmwm.h +++ b/calmwm.h @@ -66,7 +66,6 @@ TAILQ_HEAD(client_ctx_q, client_ctx); struct group_ctx { TAILQ_ENTRY(group_ctx) entry; struct client_ctx_q clients; - const char *name; int shortcut; int hidden; int nhidden; @@ -101,6 +100,8 @@ struct screen_ctx { struct group_ctx groups[CALMWM_NGROUPS]; int group_hideall; struct group_ctx_q groupq; + char **group_names; + int group_nonames; }; TAILQ_HEAD(screen_ctx_q, screen_ctx); @@ -178,11 +179,10 @@ extern const char *shortcut_to_name[]; /* Autogroups */ struct autogroupwin { - TAILQ_ENTRY(autogroupwin) entry; - - char *class; - char *name; - char *group; + TAILQ_ENTRY(autogroupwin) entry; + char *class; + char *name; + int num; }; TAILQ_HEAD(autogroupwin_q, autogroupwin); @@ -475,6 +475,8 @@ void search_match_exec(struct menu_q *, struct menu_q *, char *); void group_init(struct screen_ctx *); +void group_make_autogroup(struct conf *, char *, int); +void group_update_names(struct screen_ctx *); void group_hidetoggle(struct screen_ctx *, int); void group_only(struct screen_ctx *, int); void group_cycle(struct screen_ctx *, int); @@ -538,7 +540,8 @@ extern struct conf Conf; #define _NET_DESKTOP_GEOMETRY cwm_atoms[15] #define _NET_VIRTUAL_ROOTS cwm_atoms[16] #define _NET_SHOWING_DESKTOP cwm_atoms[17] -#define CWM_NO_ATOMS 18 +#define _NET_DESKTOP_NAMES cwm_atoms[18] +#define CWM_NO_ATOMS 19 #define CWM_NETWM_START 7 extern Atom cwm_atoms[CWM_NO_ATOMS]; diff --git a/conf.c b/conf.c index 7e34ced..19a9085 100644 --- a/conf.c +++ b/conf.c @@ -225,7 +225,6 @@ conf_clear(struct conf *c) xfree(ag->class); if (ag->name) xfree(ag->name); - xfree(ag->group); xfree(ag); } diff --git a/group.c b/group.c index e7a21cc..7e46e5e 100644 --- a/group.c +++ b/group.c @@ -28,6 +28,7 @@ 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_setactive(struct screen_ctx *, int); +static void group_set_names(struct screen_ctx *); const char *shortcut_to_name[] = { "nogroup", "one", "two", "three", "four", "five", "six", @@ -47,7 +48,8 @@ group_add(struct group_ctx *gc, struct client_ctx *cc) TAILQ_REMOVE(&cc->group->clients, cc, group_entry); XChangeProperty(X_Dpy, cc->win, _CWM_GRP, XA_STRING, - 8, PropModeReplace, gc->name, strlen(gc->name)); + 8, PropModeReplace, shortcut_to_name[gc->shortcut], + strlen(shortcut_to_name[gc->shortcut])); TAILQ_INSERT_TAIL(&gc->clients, cc, group_entry); cc->group = gc; @@ -131,12 +133,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 + 1; - sc->groups[i].name = shortcut_to_name[sc->groups[i].shortcut]; TAILQ_INSERT_TAIL(&sc->groupq, &sc->groups[i], entry); } @@ -160,6 +165,28 @@ group_init(struct screen_ctx *sc) group_setactive(sc, 0); } +void +group_make_autogroup(struct conf *conf, char *class, int no) +{ + struct autogroupwin *aw; + char *p; + + aw = xcalloc(1, sizeof(*aw)); + + if ((p = strchr(class, ',')) == NULL) { + aw->name = NULL; + aw->class = xstrdup(class); + } else { + *(p++) = '\0'; + aw->name = xstrdup(class); + aw->class = xstrdup(p); + } + aw->num = no; + + TAILQ_INSERT_TAIL(&conf->autogroupq, aw, entry); + +} + static void group_setactive(struct screen_ctx *sc, int idx) { @@ -334,10 +361,10 @@ group_menu(XButtonEvent *e) mi = xcalloc(1, sizeof(*mi)); if (gc->hidden) snprintf(mi->text, sizeof(mi->text), "%d: [%s]", - gc->shortcut, shortcut_to_name[gc->shortcut]); + gc->shortcut, sc->group_names[i]); else snprintf(mi->text, sizeof(mi->text), "%d: %s", - gc->shortcut, shortcut_to_name[gc->shortcut]); + gc->shortcut, sc->group_names[i]); mi->ctx = gc; TAILQ_INSERT_TAIL(&menuq, mi, entry); } @@ -382,31 +409,36 @@ group_autogroup(struct client_ctx *cc) struct screen_ctx *sc = cc->sc; struct autogroupwin *aw; struct group_ctx *gc; + int no = -1, i; unsigned char *grpstr = NULL; - char group[CALMWM_MAXNAMELEN]; if (cc->app_class == NULL || cc->app_name == NULL) return; if (xu_getprop(cc, _CWM_GRP, XA_STRING, (CALMWM_MAXNAMELEN - 1)/sizeof(long), &grpstr) > 0) { - strlcpy(group, grpstr, sizeof(group)); + for (i = 0; i < sizeof(shortcut_to_name) / + sizeof(shortcut_to_name[0]); i++) { + if (strcmp(shortcut_to_name[i], grpstr) == 0) + no = i; + } XFree(grpstr); } else { TAILQ_FOREACH(aw, &Conf.autogroupq, entry) { if (strcmp(aw->class, cc->app_class) == 0 && (aw->name == NULL || strcmp(aw->name, cc->app_name) == 0)) { - strlcpy(group, aw->group, sizeof(group)); + no = aw->num; break; } } } - if (strncmp("nogroup", group, 7) == 0) + /* no group please */ + if (no == 0) return; TAILQ_FOREACH(gc, &sc->groupq, entry) { - if (strcmp(shortcut_to_name[gc->shortcut], group) == 0) { + if (gc->shortcut == no) { group_add(gc, cc); return; } @@ -416,3 +448,78 @@ group_autogroup(struct client_ctx *cc) group_add(sc->group_active, cc); } + +void +group_update_names(struct screen_ctx *sc) +{ + char **strings, *p; + unsigned char *prop_ret; + Atom type_ret; + int format_ret, i = 0, nstrings = 0, n, setnames = 0; + unsigned long bytes_after, num_ret; + + if (XGetWindowProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_NAMES, 0, + 0xffffff, False, UTF8_STRING, &type_ret, &format_ret, + &num_ret, &bytes_after, &prop_ret) == Success && + prop_ret != NULL && format_ret == 8) { + /* failure, just set defaults */ + prop_ret[num_ret - 1] = '\0'; /* paranoia */ + while (i < num_ret) { + if (prop_ret[i++] == '\0') + nstrings++; + } + } + + strings = xmalloc((nstrings < CALMWM_NGROUPS ? CALMWM_NGROUPS : + nstrings) * sizeof(*strings)); + + i = n = 0; + p = 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 = 1; + 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) +{ + unsigned 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; + strlcpy(q, sc->group_names[i], tlen); + tlen -= slen; + q += slen; + } + + XChangeProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_NAMES, + UTF8_STRING, 8, PropModeReplace, p, len); +} diff --git a/parse.y b/parse.y index 435c2a2..c60995c 100644 --- a/parse.y +++ b/parse.y @@ -123,29 +123,13 @@ main : FONTNAME STRING { free($3); } | AUTOGROUP NUMBER STRING { - struct autogroupwin *aw; - char *p; - if ($2 < 0 || $2 > 9) { free($3); yyerror("autogroup number out of range: %d", $2); YYERROR; } - aw = xcalloc(1, sizeof(*aw)); - - if ((p = strchr($3, ',')) == NULL) { - aw->name = NULL; - aw->class = xstrdup($3); - } else { - *(p++) = '\0'; - aw->name = xstrdup($3); - aw->class = xstrdup(p); - } - aw->group = xstrdup(shortcut_to_name[$2]); - - TAILQ_INSERT_TAIL(&conf->autogroupq, aw, entry); - + group_make_autogroup(conf, $3, $2); free($3); } | IGNORE STRING { diff --git a/xevents.c b/xevents.c index d52984a..8956477 100644 --- a/xevents.c +++ b/xevents.c @@ -170,6 +170,7 @@ static void xev_handle_propertynotify(XEvent *ee) { XPropertyEvent *e = &ee->xproperty; + struct screen_ctx *sc; struct client_ctx *cc; if ((cc = client_find(e->window)) != NULL) { @@ -184,7 +185,17 @@ xev_handle_propertynotify(XEvent *ee) /* do nothing */ break; } + } else { + TAILQ_FOREACH(sc, &Screenq, entry) + if (sc->rootwin == e->window) + goto test; + return; + +test: + if (e->atom == _NET_DESKTOP_NAMES) + group_update_names(sc); } + } void diff --git a/xutil.c b/xutil.c index a9e2453..6c7cb26 100644 --- a/xutil.c +++ b/xutil.c @@ -189,6 +189,7 @@ char *atoms[CWM_NO_ATOMS] = { "_NET_DESKTOP_GEOMETRY", "_NET_VIRTUAL_ROOTS", "_NET_SHOWING_DESKTOP", + "_NET_DESKTOP_NAMES", }; void -- cgit 1.4.1