summary refs log tree commit diff
diff options
context:
space:
mode:
authoroga <oga>2009-12-11 17:51:42 +0000
committeroga <oga>2009-12-11 17:51:42 +0000
commitb35cbf81d84c97e7c444aafe491597bd6db6cfab (patch)
tree185bdf2bf9abe166225ac24f10759bad29f82b78
parent9b04930f24bb3acc3626f442eff074b6b80821f3 (diff)
downloadcwm-b35cbf81d84c97e7c444aafe491597bd6db6cfab.tar.gz
cwm-b35cbf81d84c97e7c444aafe491597bd6db6cfab.tar.xz
cwm-b35cbf81d84c97e7c444aafe491597bd6db6cfab.zip
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@
-rw-r--r--calmwm.h17
-rw-r--r--conf.c1
-rw-r--r--group.c125
-rw-r--r--parse.y18
-rw-r--r--xevents.c11
-rw-r--r--xutil.c1
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