mirror of
https://github.com/leahneukirchen/cwm.git
synced 2023-08-10 21:13:12 +03:00
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@
This commit is contained in:
parent
9b04930f24
commit
b35cbf81d8
17
calmwm.h
17
calmwm.h
@ -66,7 +66,6 @@ TAILQ_HEAD(client_ctx_q, client_ctx);
|
|||||||
struct group_ctx {
|
struct group_ctx {
|
||||||
TAILQ_ENTRY(group_ctx) entry;
|
TAILQ_ENTRY(group_ctx) entry;
|
||||||
struct client_ctx_q clients;
|
struct client_ctx_q clients;
|
||||||
const char *name;
|
|
||||||
int shortcut;
|
int shortcut;
|
||||||
int hidden;
|
int hidden;
|
||||||
int nhidden;
|
int nhidden;
|
||||||
@ -101,6 +100,8 @@ struct screen_ctx {
|
|||||||
struct group_ctx groups[CALMWM_NGROUPS];
|
struct group_ctx groups[CALMWM_NGROUPS];
|
||||||
int group_hideall;
|
int group_hideall;
|
||||||
struct group_ctx_q groupq;
|
struct group_ctx_q groupq;
|
||||||
|
char **group_names;
|
||||||
|
int group_nonames;
|
||||||
};
|
};
|
||||||
|
|
||||||
TAILQ_HEAD(screen_ctx_q, screen_ctx);
|
TAILQ_HEAD(screen_ctx_q, screen_ctx);
|
||||||
@ -178,11 +179,10 @@ extern const char *shortcut_to_name[];
|
|||||||
|
|
||||||
/* Autogroups */
|
/* Autogroups */
|
||||||
struct autogroupwin {
|
struct autogroupwin {
|
||||||
TAILQ_ENTRY(autogroupwin) entry;
|
TAILQ_ENTRY(autogroupwin) entry;
|
||||||
|
char *class;
|
||||||
char *class;
|
char *name;
|
||||||
char *name;
|
int num;
|
||||||
char *group;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TAILQ_HEAD(autogroupwin_q, autogroupwin);
|
TAILQ_HEAD(autogroupwin_q, autogroupwin);
|
||||||
@ -475,6 +475,8 @@ void search_match_exec(struct menu_q *, struct menu_q *,
|
|||||||
char *);
|
char *);
|
||||||
|
|
||||||
void group_init(struct screen_ctx *);
|
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_hidetoggle(struct screen_ctx *, int);
|
||||||
void group_only(struct screen_ctx *, int);
|
void group_only(struct screen_ctx *, int);
|
||||||
void group_cycle(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_DESKTOP_GEOMETRY cwm_atoms[15]
|
||||||
#define _NET_VIRTUAL_ROOTS cwm_atoms[16]
|
#define _NET_VIRTUAL_ROOTS cwm_atoms[16]
|
||||||
#define _NET_SHOWING_DESKTOP cwm_atoms[17]
|
#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
|
#define CWM_NETWM_START 7
|
||||||
|
|
||||||
extern Atom cwm_atoms[CWM_NO_ATOMS];
|
extern Atom cwm_atoms[CWM_NO_ATOMS];
|
||||||
|
1
conf.c
1
conf.c
@ -225,7 +225,6 @@ conf_clear(struct conf *c)
|
|||||||
xfree(ag->class);
|
xfree(ag->class);
|
||||||
if (ag->name)
|
if (ag->name)
|
||||||
xfree(ag->name);
|
xfree(ag->name);
|
||||||
xfree(ag->group);
|
|
||||||
xfree(ag);
|
xfree(ag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
125
group.c
125
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_show(struct screen_ctx *, struct group_ctx *);
|
||||||
static void group_fix_hidden_state(struct group_ctx *);
|
static void group_fix_hidden_state(struct group_ctx *);
|
||||||
static void group_setactive(struct screen_ctx *, int);
|
static void group_setactive(struct screen_ctx *, int);
|
||||||
|
static void group_set_names(struct screen_ctx *);
|
||||||
|
|
||||||
const char *shortcut_to_name[] = {
|
const char *shortcut_to_name[] = {
|
||||||
"nogroup", "one", "two", "three", "four", "five", "six",
|
"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);
|
TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
|
||||||
|
|
||||||
XChangeProperty(X_Dpy, cc->win, _CWM_GRP, XA_STRING,
|
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);
|
TAILQ_INSERT_TAIL(&gc->clients, cc, group_entry);
|
||||||
cc->group = gc;
|
cc->group = gc;
|
||||||
@ -131,12 +133,15 @@ group_init(struct screen_ctx *sc)
|
|||||||
|
|
||||||
TAILQ_INIT(&sc->groupq);
|
TAILQ_INIT(&sc->groupq);
|
||||||
sc->group_hideall = 0;
|
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++) {
|
for (i = 0; i < CALMWM_NGROUPS; i++) {
|
||||||
TAILQ_INIT(&sc->groups[i].clients);
|
TAILQ_INIT(&sc->groups[i].clients);
|
||||||
sc->groups[i].hidden = 0;
|
sc->groups[i].hidden = 0;
|
||||||
sc->groups[i].shortcut = i + 1;
|
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);
|
TAILQ_INSERT_TAIL(&sc->groupq, &sc->groups[i], entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,6 +165,28 @@ group_init(struct screen_ctx *sc)
|
|||||||
group_setactive(sc, 0);
|
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
|
static void
|
||||||
group_setactive(struct screen_ctx *sc, int idx)
|
group_setactive(struct screen_ctx *sc, int idx)
|
||||||
{
|
{
|
||||||
@ -334,10 +361,10 @@ group_menu(XButtonEvent *e)
|
|||||||
mi = xcalloc(1, sizeof(*mi));
|
mi = xcalloc(1, sizeof(*mi));
|
||||||
if (gc->hidden)
|
if (gc->hidden)
|
||||||
snprintf(mi->text, sizeof(mi->text), "%d: [%s]",
|
snprintf(mi->text, sizeof(mi->text), "%d: [%s]",
|
||||||
gc->shortcut, shortcut_to_name[gc->shortcut]);
|
gc->shortcut, sc->group_names[i]);
|
||||||
else
|
else
|
||||||
snprintf(mi->text, sizeof(mi->text), "%d: %s",
|
snprintf(mi->text, sizeof(mi->text), "%d: %s",
|
||||||
gc->shortcut, shortcut_to_name[gc->shortcut]);
|
gc->shortcut, sc->group_names[i]);
|
||||||
mi->ctx = gc;
|
mi->ctx = gc;
|
||||||
TAILQ_INSERT_TAIL(&menuq, mi, entry);
|
TAILQ_INSERT_TAIL(&menuq, mi, entry);
|
||||||
}
|
}
|
||||||
@ -382,31 +409,36 @@ group_autogroup(struct client_ctx *cc)
|
|||||||
struct screen_ctx *sc = cc->sc;
|
struct screen_ctx *sc = cc->sc;
|
||||||
struct autogroupwin *aw;
|
struct autogroupwin *aw;
|
||||||
struct group_ctx *gc;
|
struct group_ctx *gc;
|
||||||
|
int no = -1, i;
|
||||||
unsigned char *grpstr = NULL;
|
unsigned char *grpstr = NULL;
|
||||||
char group[CALMWM_MAXNAMELEN];
|
|
||||||
|
|
||||||
if (cc->app_class == NULL || cc->app_name == NULL)
|
if (cc->app_class == NULL || cc->app_name == NULL)
|
||||||
return;
|
return;
|
||||||
if (xu_getprop(cc, _CWM_GRP, XA_STRING,
|
if (xu_getprop(cc, _CWM_GRP, XA_STRING,
|
||||||
(CALMWM_MAXNAMELEN - 1)/sizeof(long), &grpstr) > 0) {
|
(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);
|
XFree(grpstr);
|
||||||
} else {
|
} else {
|
||||||
TAILQ_FOREACH(aw, &Conf.autogroupq, entry) {
|
TAILQ_FOREACH(aw, &Conf.autogroupq, entry) {
|
||||||
if (strcmp(aw->class, cc->app_class) == 0 &&
|
if (strcmp(aw->class, cc->app_class) == 0 &&
|
||||||
(aw->name == NULL ||
|
(aw->name == NULL ||
|
||||||
strcmp(aw->name, cc->app_name) == 0)) {
|
strcmp(aw->name, cc->app_name) == 0)) {
|
||||||
strlcpy(group, aw->group, sizeof(group));
|
no = aw->num;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp("nogroup", group, 7) == 0)
|
/* no group please */
|
||||||
|
if (no == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TAILQ_FOREACH(gc, &sc->groupq, entry) {
|
TAILQ_FOREACH(gc, &sc->groupq, entry) {
|
||||||
if (strcmp(shortcut_to_name[gc->shortcut], group) == 0) {
|
if (gc->shortcut == no) {
|
||||||
group_add(gc, cc);
|
group_add(gc, cc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -416,3 +448,78 @@ group_autogroup(struct client_ctx *cc)
|
|||||||
group_add(sc->group_active, 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);
|
||||||
|
}
|
||||||
|
18
parse.y
18
parse.y
@ -123,29 +123,13 @@ main : FONTNAME STRING {
|
|||||||
free($3);
|
free($3);
|
||||||
}
|
}
|
||||||
| AUTOGROUP NUMBER STRING {
|
| AUTOGROUP NUMBER STRING {
|
||||||
struct autogroupwin *aw;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if ($2 < 0 || $2 > 9) {
|
if ($2 < 0 || $2 > 9) {
|
||||||
free($3);
|
free($3);
|
||||||
yyerror("autogroup number out of range: %d", $2);
|
yyerror("autogroup number out of range: %d", $2);
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
aw = xcalloc(1, sizeof(*aw));
|
group_make_autogroup(conf, $3, $2);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
free($3);
|
free($3);
|
||||||
}
|
}
|
||||||
| IGNORE STRING {
|
| IGNORE STRING {
|
||||||
|
11
xevents.c
11
xevents.c
@ -170,6 +170,7 @@ static void
|
|||||||
xev_handle_propertynotify(XEvent *ee)
|
xev_handle_propertynotify(XEvent *ee)
|
||||||
{
|
{
|
||||||
XPropertyEvent *e = &ee->xproperty;
|
XPropertyEvent *e = &ee->xproperty;
|
||||||
|
struct screen_ctx *sc;
|
||||||
struct client_ctx *cc;
|
struct client_ctx *cc;
|
||||||
|
|
||||||
if ((cc = client_find(e->window)) != NULL) {
|
if ((cc = client_find(e->window)) != NULL) {
|
||||||
@ -184,7 +185,17 @@ xev_handle_propertynotify(XEvent *ee)
|
|||||||
/* do nothing */
|
/* do nothing */
|
||||||
break;
|
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
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user