mirror of
https://github.com/leahneukirchen/cwm.git
synced 2023-08-10 21:13:12 +03:00
cvsimport
This commit is contained in:
241
group.c
241
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 */
|
||||
}
|
||||
|
||||
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_show(struct screen_ctx *sc, struct group_ctx *gc)
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user