2007-04-27 11:58:48 -06:00
|
|
|
/*
|
|
|
|
* calmwm - the calm window manager
|
|
|
|
*
|
|
|
|
* Copyright (c) 2004 Andy Adamson <dros@monkey.org>
|
|
|
|
* Copyright (c) 2004,2005 Marius Aamodt Eriksen <marius@monkey.org>
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
2007-05-28 12:34:27 -06:00
|
|
|
* $Id: group.c,v 1.2 2007/05/28 18:34:27 jasper Exp $
|
2007-04-27 11:58:48 -06:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "headers.h"
|
|
|
|
#include "calmwm.h"
|
|
|
|
|
|
|
|
#define CALMWM_NGROUPS 9
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
int Groupmode = 0;
|
|
|
|
int Groupnamemode = 0;
|
|
|
|
struct group_ctx *Group_active = NULL;
|
|
|
|
struct group_ctx *Group_current = NULL;
|
|
|
|
struct group_ctx Groups[CALMWM_NGROUPS];
|
|
|
|
char Group_name[256];
|
|
|
|
int Groupfocusset = 0;
|
|
|
|
Window Groupfocuswin;
|
|
|
|
int Groupfocusrevert;
|
|
|
|
int Grouphideall = 0;
|
|
|
|
struct group_ctx_q Groupq;
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
#define GroupMask (KeyPressMask|ExposureMask)
|
|
|
|
|
|
|
|
static char *shortcut_to_name[] = {
|
|
|
|
"XXX", "one", "two", "three",
|
|
|
|
"four", "five", "six", "seven",
|
|
|
|
"eight", "nine",
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
_group_add(struct group_ctx *gc, struct client_ctx *cc)
|
|
|
|
{
|
|
|
|
if (cc == NULL || gc == NULL)
|
|
|
|
errx(1, "_group_add: a ctx is NULL");
|
|
|
|
|
|
|
|
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;
|
|
|
|
cc->groupcommit = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_group_remove(struct client_ctx *cc)
|
|
|
|
{
|
|
|
|
if (cc == NULL || cc->group == NULL)
|
|
|
|
errx(1, "_group_remove: a ctx is NULL");
|
|
|
|
|
|
|
|
TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
|
|
|
|
cc->group = NULL;
|
|
|
|
cc->groupcommit = 0;
|
|
|
|
cc->highlight = 0;
|
|
|
|
client_draw_border(cc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_group_commit(struct group_ctx *gc)
|
|
|
|
{
|
|
|
|
struct client_ctx *cc;
|
|
|
|
|
|
|
|
if (gc == NULL)
|
|
|
|
errx(1, "_group_commit: ctx is null");
|
|
|
|
|
|
|
|
TAILQ_FOREACH(cc, &gc->clients, group_entry)
|
|
|
|
cc->groupcommit = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_group_purge(struct group_ctx *gc)
|
|
|
|
{
|
|
|
|
struct client_ctx *cc;
|
|
|
|
|
|
|
|
if (gc == NULL)
|
|
|
|
errx(1, "_group_commit: ctx is null");
|
|
|
|
|
|
|
|
TAILQ_FOREACH(cc, &gc->clients, group_entry)
|
|
|
|
if (cc->groupcommit == 0)
|
|
|
|
_group_remove(cc);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
_group_hide(struct group_ctx *gc)
|
|
|
|
{
|
|
|
|
struct client_ctx *cc;
|
|
|
|
|
|
|
|
screen_updatestackingorder();
|
|
|
|
|
|
|
|
gc->nhidden = 0;
|
|
|
|
gc->highstack = 0;
|
|
|
|
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
|
|
|
|
_group_show(struct group_ctx *gc)
|
|
|
|
{
|
|
|
|
struct client_ctx *cc;
|
|
|
|
Window *winlist;
|
|
|
|
u_int i;
|
|
|
|
int lastempty = -1;
|
|
|
|
|
|
|
|
winlist = (Window *) xcalloc(sizeof(*winlist) * (gc->highstack + 1));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Invert the stacking order as XRestackWindows() expects them
|
|
|
|
* top-to-bottom.
|
|
|
|
*/
|
|
|
|
TAILQ_FOREACH(cc, &gc->clients, group_entry) {
|
|
|
|
winlist[gc->highstack - cc->stackingorder] = cc->pwin;
|
|
|
|
client_unhide(cc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Un-sparseify */
|
|
|
|
for (i = 0; i <= gc->highstack; i++) {
|
|
|
|
if (!winlist[i] && lastempty == -1)
|
|
|
|
lastempty = i;
|
|
|
|
else if (winlist[i] && lastempty != -1) {
|
|
|
|
winlist[lastempty] = winlist[i];
|
|
|
|
if (++lastempty == i)
|
|
|
|
lastempty = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
XRestackWindows(X_Dpy, winlist, gc->nhidden);
|
2007-04-27 11:58:48 -06:00
|
|
|
xfree(winlist);
|
|
|
|
|
|
|
|
gc->hidden = 0;
|
2007-05-28 12:34:27 -06:00
|
|
|
Group_active = gc;
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
_group_destroy(struct group_ctx *gc)
|
|
|
|
{
|
|
|
|
struct client_ctx *cc;
|
|
|
|
|
|
|
|
if (gc->name != NULL) {
|
|
|
|
xfree(gc->name);
|
|
|
|
gc->name = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((cc = TAILQ_FIRST(&gc->clients)) != NULL) {
|
|
|
|
TAILQ_REMOVE(&gc->clients, cc, group_entry);
|
|
|
|
cc->group = NULL;
|
|
|
|
cc->groupcommit = 0;
|
|
|
|
cc->highlight = 0;
|
|
|
|
client_draw_border(cc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
group_init(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
TAILQ_INIT(&Groupq);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
for (i = 0; i < CALMWM_NGROUPS; i++) {
|
2007-05-28 12:34:27 -06:00
|
|
|
TAILQ_INIT(&Groups[i].clients);
|
|
|
|
Groups[i].hidden = 0;
|
|
|
|
Groups[i].shortcut = i + 1;
|
|
|
|
TAILQ_INSERT_TAIL(&Groupq, &Groups[i], entry);
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
Group_current = Group_active = &Groups[0];
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* manipulate the 'current group'
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* set current group to the first empty group
|
|
|
|
* returns 0 on success, -1 if there are no empty groups
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
group_new(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0; i < CALMWM_NGROUPS; i++) {
|
2007-05-28 12:34:27 -06:00
|
|
|
if (TAILQ_EMPTY(&Groups[i].clients)) {
|
|
|
|
Group_current = &Groups[i];
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* change the current group */
|
|
|
|
int
|
|
|
|
group_select(int idx)
|
|
|
|
{
|
2007-05-28 12:34:27 -06:00
|
|
|
struct group_ctx *gc = Group_current;
|
2007-04-27 11:58:48 -06:00
|
|
|
struct client_ctx *cc;
|
|
|
|
|
|
|
|
if (idx < 0 || idx >= CALMWM_NGROUPS)
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
TAILQ_FOREACH(cc, &gc->clients, group_entry) {
|
|
|
|
cc->highlight = 0;
|
|
|
|
client_draw_border(cc);
|
|
|
|
}
|
|
|
|
|
|
|
|
_group_commit(gc);
|
2007-05-28 12:34:27 -06:00
|
|
|
Group_current = &Groups[idx];
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
group_display_draw(screen_current());
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* enter group mode */
|
|
|
|
void
|
|
|
|
group_enter(void)
|
|
|
|
{
|
2007-05-28 12:34:27 -06:00
|
|
|
if (Groupmode != 0)
|
2007-04-27 11:58:48 -06:00
|
|
|
errx(1, "group_enter called twice");
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
if (Group_current == NULL)
|
|
|
|
Group_current = &Groups[0];
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
/* setup input buffer */
|
2007-05-28 12:34:27 -06:00
|
|
|
Group_name[0] = '\0';
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
Groupmode = 1;
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
group_display_init(screen_current());
|
|
|
|
group_display_draw(screen_current());
|
|
|
|
}
|
|
|
|
|
|
|
|
/* exit group mode */
|
|
|
|
void
|
|
|
|
group_exit(int commit)
|
|
|
|
{
|
2007-05-28 12:34:27 -06:00
|
|
|
struct group_ctx *gc = Group_current;
|
2007-04-27 11:58:48 -06:00
|
|
|
struct client_ctx *cc;
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
if (Groupmode != 1)
|
2007-04-27 11:58:48 -06:00
|
|
|
errx(1, "group_exit called twice");
|
|
|
|
|
|
|
|
TAILQ_FOREACH(cc, &gc->clients, group_entry) {
|
|
|
|
cc->highlight = 0;
|
|
|
|
client_draw_border(cc);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (commit) {
|
|
|
|
_group_commit(gc);
|
|
|
|
} else {
|
|
|
|
/* abort */
|
|
|
|
_group_purge(gc);
|
|
|
|
if (!TAILQ_EMPTY(&gc->clients))
|
|
|
|
_group_destroy(gc);
|
|
|
|
}
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
XUnmapWindow(X_Dpy, screen_current()->groupwin);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
if (Groupnamemode) {
|
|
|
|
XSetInputFocus(X_Dpy, Groupfocuswin, Groupfocusrevert,
|
2007-04-27 11:58:48 -06:00
|
|
|
CurrentTime);
|
2007-05-28 12:34:27 -06:00
|
|
|
Groupfocusset = 0;
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
Groupmode = Groupnamemode = 0;
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
group_click(struct client_ctx *cc)
|
|
|
|
{
|
2007-05-28 12:34:27 -06:00
|
|
|
struct group_ctx *gc = Group_current;
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
if (gc == cc->group)
|
|
|
|
_group_remove(cc);
|
|
|
|
else
|
|
|
|
_group_add(gc, cc);
|
|
|
|
group_display_draw(screen_current());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Used to add a newly mapped window to the active group */
|
|
|
|
|
|
|
|
void
|
|
|
|
group_sticky(struct client_ctx *cc)
|
|
|
|
{
|
2007-05-28 12:34:27 -06:00
|
|
|
_group_add(Group_active, cc);
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
group_sticky_toggle_enter(struct client_ctx *cc)
|
|
|
|
{
|
2007-05-28 12:34:27 -06:00
|
|
|
struct group_ctx *gc = Group_active;
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
if (gc == cc->group) {
|
|
|
|
_group_remove(cc);
|
|
|
|
cc->highlight = CLIENT_HIGHLIGHT_RED;
|
|
|
|
} else {
|
|
|
|
_group_add(gc, cc);
|
|
|
|
cc->highlight = CLIENT_HIGHLIGHT_BLUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
client_draw_border(cc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
group_sticky_toggle_exit(struct client_ctx *cc)
|
|
|
|
{
|
|
|
|
cc->highlight = 0;
|
|
|
|
client_draw_border(cc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* selection list display
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
|
|
|
group_display_init(struct screen_ctx *sc)
|
|
|
|
{
|
2007-05-28 12:34:27 -06:00
|
|
|
sc->groupwin = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0,
|
2007-04-27 11:58:48 -06:00
|
|
|
1, 1, 1, sc->blackpixl, sc->whitepixl);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
group_display_draw(struct screen_ctx *sc)
|
|
|
|
{
|
2007-05-28 12:34:27 -06:00
|
|
|
struct group_ctx *gc = Group_current;
|
2007-04-27 11:58:48 -06:00
|
|
|
int x, y, dx, dy, fontheight, titlelen;
|
|
|
|
struct client_ctx *cc;
|
|
|
|
char titlebuf[1024];
|
|
|
|
struct fontdesc *font = DefaultFont;
|
|
|
|
|
|
|
|
snprintf(titlebuf, sizeof(titlebuf), "Editing group %d", gc->shortcut);
|
|
|
|
|
|
|
|
x = y = 0;
|
|
|
|
|
|
|
|
fontheight = font_ascent(font) + font_descent(font) + 1;
|
|
|
|
dx = titlelen = font_width(font, titlebuf, strlen(titlebuf));
|
|
|
|
dy = fontheight;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(cc, &gc->clients, group_entry) {
|
|
|
|
cc->highlight = CLIENT_HIGHLIGHT_BLUE;
|
|
|
|
client_draw_border(cc);
|
|
|
|
}
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
XMoveResizeWindow(X_Dpy, sc->groupwin, x, y, dx, dy);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
/* XXX */
|
2007-05-28 12:34:27 -06:00
|
|
|
XSelectInput(X_Dpy, sc->groupwin, GroupMask);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
XMapRaised(X_Dpy, sc->groupwin);
|
|
|
|
XClearWindow(X_Dpy, sc->groupwin);
|
2007-04-27 11:58:48 -06:00
|
|
|
font_draw(font, titlebuf, strlen(titlebuf), sc->groupwin,
|
|
|
|
0, font_ascent(font) + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
group_display_keypress(KeyCode k)
|
|
|
|
{
|
2007-05-28 12:34:27 -06:00
|
|
|
struct group_ctx * gc = Group_current;
|
2007-04-27 11:58:48 -06:00
|
|
|
char chr;
|
|
|
|
enum ctltype ctl;
|
|
|
|
int len;
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
if (!Groupnamemode)
|
2007-04-27 11:58:48 -06:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (input_keycodetrans(k, 0, &ctl, &chr, 1) < 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
switch (ctl) {
|
|
|
|
case CTL_ERASEONE:
|
2007-05-28 12:34:27 -06:00
|
|
|
if ((len = strlen(Group_name)) > 0)
|
|
|
|
Group_name[len - 1] = '\0';
|
2007-04-27 11:58:48 -06:00
|
|
|
break;
|
|
|
|
case CTL_RETURN:
|
|
|
|
if (gc->name != NULL)
|
|
|
|
xfree(gc->name);
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
gc->name = xstrdup(Group_name);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
group_exit(1);
|
|
|
|
return;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chr != '\0')
|
2007-05-28 12:34:27 -06:00
|
|
|
snprintf(Group_name, sizeof(Group_name), "%s%c",
|
|
|
|
Group_name, chr);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
out:
|
|
|
|
group_display_draw(screen_current());
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if group_hidetoggle would produce no effect, toggle the group's hidden state
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
_group_fix_hidden_state(struct group_ctx *gc)
|
|
|
|
{
|
|
|
|
struct client_ctx *cc;
|
|
|
|
int same = 0;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(cc, &gc->clients, group_entry) {
|
|
|
|
if (gc->hidden == ((cc->flags & CLIENT_HIDDEN) ? 1 : 0))
|
|
|
|
same++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (same == 0)
|
|
|
|
gc->hidden = !gc->hidden;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
group_hidetoggle(int idx)
|
|
|
|
{
|
|
|
|
struct group_ctx *gc;
|
|
|
|
#ifdef notyet
|
|
|
|
char buf[128];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (idx < 0 || idx >= CALMWM_NGROUPS)
|
|
|
|
err(1, "group_hidetoggle: index out of range (%d)", idx);
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
gc = &Groups[idx];
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
_group_fix_hidden_state(gc);
|
|
|
|
|
|
|
|
if (gc->hidden)
|
|
|
|
_group_show(gc);
|
|
|
|
else {
|
|
|
|
_group_hide(gc);
|
|
|
|
if (TAILQ_EMPTY(&gc->clients))
|
2007-05-28 12:34:27 -06:00
|
|
|
Group_active = gc;
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef notyet
|
|
|
|
snprintf(buf, sizeof(buf), "Group %d", idx + 1);
|
|
|
|
screen_infomsg(buf);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#define GROUP_NEXT(gc, fwd) (fwd) ? \
|
|
|
|
TAILQ_NEXT(gc, entry) : TAILQ_PREV(gc, group_ctx_q, entry)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Jump to the next/previous active group. If none exist, then just
|
|
|
|
* stay put.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
group_slide(int fwd)
|
|
|
|
{
|
|
|
|
struct group_ctx *gc, *showgroup = NULL;
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
assert(Group_active != NULL);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
gc = Group_active;
|
2007-04-27 11:58:48 -06:00
|
|
|
for (;;) {
|
|
|
|
gc = GROUP_NEXT(gc, fwd);
|
|
|
|
if (gc == NULL)
|
2007-05-28 12:34:27 -06:00
|
|
|
gc = fwd ? TAILQ_FIRST(&Groupq) :
|
|
|
|
TAILQ_LAST(&Groupq, group_ctx_q);
|
|
|
|
if (gc == Group_active)
|
2007-04-27 11:58:48 -06:00
|
|
|
break;
|
|
|
|
|
|
|
|
if (!TAILQ_EMPTY(&gc->clients) && showgroup == NULL)
|
|
|
|
showgroup = gc;
|
|
|
|
else if (!gc->hidden)
|
|
|
|
_group_hide(gc);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (showgroup == NULL)
|
|
|
|
return;
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
_group_hide(Group_active);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
if (showgroup->hidden)
|
|
|
|
_group_show(showgroup);
|
|
|
|
else
|
2007-05-28 12:34:27 -06:00
|
|
|
Group_active = showgroup;
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* called when a client is deleted */
|
|
|
|
void
|
|
|
|
group_client_delete(struct client_ctx *cc)
|
|
|
|
{
|
|
|
|
if (cc->group == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
|
|
|
|
cc->group = NULL; /* he he */
|
|
|
|
cc->groupcommit = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
group_menu(XButtonEvent *e)
|
|
|
|
{
|
|
|
|
struct menu_q menuq;
|
|
|
|
struct menu *mi;
|
|
|
|
int i;
|
|
|
|
struct group_ctx *gc;
|
|
|
|
|
|
|
|
TAILQ_INIT(&menuq);
|
|
|
|
|
|
|
|
for (i = 0; i < CALMWM_NGROUPS; i++) {
|
2007-05-28 12:34:27 -06:00
|
|
|
gc = &Groups[i];
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
if (TAILQ_EMPTY(&gc->clients))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (gc->name == NULL)
|
|
|
|
gc->name = xstrdup(shortcut_to_name[gc->shortcut]);
|
|
|
|
|
|
|
|
XCALLOC(mi, struct menu);
|
|
|
|
if (gc->hidden)
|
|
|
|
snprintf(mi->text, sizeof(mi->text), "%d: [%s]",
|
|
|
|
gc->shortcut, gc->name);
|
|
|
|
else
|
|
|
|
snprintf(mi->text, sizeof(mi->text), "%d: %s",
|
|
|
|
gc->shortcut, gc->name);
|
|
|
|
mi->ctx = gc;
|
|
|
|
TAILQ_INSERT_TAIL(&menuq, mi, entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TAILQ_EMPTY(&menuq))
|
|
|
|
return;
|
|
|
|
|
|
|
|
mi = (struct menu *)grab_menu(e, &menuq);
|
|
|
|
|
|
|
|
if (mi == NULL || mi->ctx == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
gc = (struct group_ctx *)mi->ctx;
|
|
|
|
|
|
|
|
if (gc->hidden)
|
|
|
|
_group_show(gc);
|
|
|
|
else
|
|
|
|
_group_hide(gc);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
while ((mi = TAILQ_FIRST(&menuq)) != NULL) {
|
|
|
|
TAILQ_REMOVE(&menuq, mi, entry);
|
|
|
|
xfree(mi);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
group_namemode(void)
|
|
|
|
{
|
2007-05-28 12:34:27 -06:00
|
|
|
Groupnamemode = 1;
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
group_display_draw(screen_current());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
group_alltoggle(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0; i < CALMWM_NGROUPS; i++) {
|
2007-05-28 12:34:27 -06:00
|
|
|
if (Grouphideall)
|
|
|
|
_group_show(&Groups[i]);
|
2007-04-27 11:58:48 -06:00
|
|
|
else
|
2007-05-28 12:34:27 -06:00
|
|
|
_group_hide(&Groups[i]);
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
if (Grouphideall)
|
|
|
|
Grouphideall = 0;
|
2007-04-27 11:58:48 -06:00
|
|
|
else
|
2007-05-28 12:34:27 -06:00
|
|
|
Grouphideall = 1;
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
group_deletecurrent(void)
|
|
|
|
{
|
2007-05-28 12:34:27 -06:00
|
|
|
_group_destroy(Group_current);
|
|
|
|
XUnmapWindow(X_Dpy, screen_current()->groupwin);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
Groupmode = Groupnamemode = 0;
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
group_done(void)
|
|
|
|
{
|
2007-05-28 12:34:27 -06:00
|
|
|
struct group_ctx *gc = Group_current;
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
if (gc->name != NULL)
|
|
|
|
xfree(gc->name);
|
|
|
|
|
|
|
|
gc->name = xstrdup(shortcut_to_name[gc->shortcut]);
|
|
|
|
|
|
|
|
group_exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
group_autogroup(struct client_ctx *cc)
|
|
|
|
{
|
|
|
|
struct autogroupwin *aw;
|
|
|
|
struct group_ctx *gc;
|
|
|
|
char group[CALMWM_MAXNAMELEN];
|
|
|
|
|
|
|
|
if (cc->app_class == NULL || cc->app_name == NULL)
|
|
|
|
return;
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
TAILQ_FOREACH(aw, &Conf.autogroupq, entry) {
|
2007-04-27 11:58:48 -06:00
|
|
|
if (strcmp(aw->class, cc->app_class) == 0 &&
|
|
|
|
(aw->name == NULL || strcmp(aw->name, cc->app_name) == 0)) {
|
|
|
|
strlcpy(group, aw->group, sizeof(group));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-05-28 12:34:27 -06:00
|
|
|
TAILQ_FOREACH(gc, &Groupq, entry) {
|
2007-04-27 11:58:48 -06:00
|
|
|
if (strcmp(shortcut_to_name[gc->shortcut], group) == 0)
|
|
|
|
_group_add(gc, cc);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|