cvsimport

This commit is contained in:
Christian Neukirchen 2014-09-07 15:47:44 +00:00
commit 9e560bd745
14 changed files with 270 additions and 283 deletions

View File

@ -48,7 +48,7 @@ struct conf Conf;
const char *homedir;
volatile sig_atomic_t cwm_status;
static void sigchld_cb(int);
static void sighdlr(int);
static int x_errorhandler(Display *, XErrorEvent *);
static void x_init(const char *);
static void x_restart(char **);
@ -84,7 +84,7 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
if (signal(SIGCHLD, sigchld_cb) == SIG_ERR)
if (signal(SIGCHLD, sighdlr) == SIG_ERR)
err(1, "signal");
if ((homedir = getenv("HOME")) == NULL || *homedir == '\0') {
@ -205,16 +205,19 @@ x_errorhandler(Display *dpy, XErrorEvent *e)
}
static void
sigchld_cb(int which)
sighdlr(int sig)
{
pid_t pid;
int save_errno = errno;
int status;
int save_errno = errno, status;
/* Collect dead children. */
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
(pid < 0 && errno == EINTR))
;
switch (sig) {
case SIGCHLD:
/* Collect dead children. */
while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0 ||
(pid < 0 && errno == EINTR))
;
break;
}
errno = save_errno;
}

View File

@ -199,6 +199,7 @@ struct client_ctx {
#define CLIENT_WM_TAKE_FOCUS 0x0200
#define CLIENT_URGENCY 0x0400
#define CLIENT_FULLSCREEN 0x0800
#define CLIENT_STICKY 0x1000
#define CLIENT_HIGHLIGHT (CLIENT_GROUP | CLIENT_UNGROUP)
#define CLIENT_MAXFLAGS (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED)
@ -222,10 +223,8 @@ TAILQ_HEAD(cycle_entry_q, client_ctx);
struct group_ctx {
TAILQ_ENTRY(group_ctx) entry;
struct client_ctx_q clients;
int shortcut;
int hidden;
int nhidden;
int highstack;
char *name;
int num;
};
TAILQ_HEAD(group_ctx_q, group_ctx);
@ -263,9 +262,7 @@ struct screen_ctx {
struct group_ctx groups[CALMWM_NGROUPS];
struct group_ctx_q groupq;
int group_hideall;
int group_nonames;
struct group_ctx *group_active;
char **group_names;
};
TAILQ_HEAD(screen_ctx_q, screen_ctx);
@ -316,8 +313,6 @@ struct conf {
int snapdist;
struct gap gap;
char *color[CWM_COLOR_NITEMS];
char termpath[MAXPATHLEN];
char lockpath[MAXPATHLEN];
char known_hosts[MAXPATHLEN];
#define CONF_FONT "sans-serif:pixelsize=14:bold"
char *font;
@ -371,7 +366,8 @@ enum {
_NET_WM_DESKTOP,
_NET_CLOSE_WINDOW,
_NET_WM_STATE,
#define _NET_WM_STATES_NITEMS 4
#define _NET_WM_STATES_NITEMS 5
_NET_WM_STATE_STICKY,
_NET_WM_STATE_MAXIMIZED_VERT,
_NET_WM_STATE_MAXIMIZED_HORZ,
_NET_WM_STATE_FULLSCREEN,
@ -418,6 +414,7 @@ void client_set_wm_state(struct client_ctx *, long);
void client_setactive(struct client_ctx *);
void client_setname(struct client_ctx *);
int client_snapcalc(int, int, int, int, int);
void client_sticky(struct client_ctx *);
void client_transient(struct client_ctx *);
void client_unhide(struct client_ctx *);
void client_urgency(struct client_ctx *);
@ -429,12 +426,13 @@ void client_wm_hints(struct client_ctx *);
void group_alltoggle(struct screen_ctx *);
void group_autogroup(struct client_ctx *);
void group_cycle(struct screen_ctx *, int);
int group_hidden_state(struct group_ctx *);
void group_hide(struct screen_ctx *, struct group_ctx *);
void group_hidetoggle(struct screen_ctx *, int);
void group_init(struct screen_ctx *);
void group_menu(struct screen_ctx *);
void group_movetogroup(struct client_ctx *, int);
void group_only(struct screen_ctx *, int);
void group_set_state(struct screen_ctx *);
void group_show(struct screen_ctx *, struct group_ctx *);
void group_sticky(struct client_ctx *);
void group_sticky_toggle_enter(struct client_ctx *);
void group_sticky_toggle_exit(struct client_ctx *);
@ -487,6 +485,7 @@ void kbfunc_client_nogroup(struct client_ctx *,
void kbfunc_client_raise(struct client_ctx *, union arg *);
void kbfunc_client_rcycle(struct client_ctx *, union arg *);
void kbfunc_client_search(struct client_ctx *, union arg *);
void kbfunc_client_sticky(struct client_ctx *, union arg *);
void kbfunc_client_vmaximize(struct client_ctx *,
union arg *);
void kbfunc_cmdexec(struct client_ctx *, union arg *);
@ -564,8 +563,7 @@ void xu_ewmh_net_wm_number_of_desktops(struct screen_ctx *);
void xu_ewmh_net_showing_desktop(struct screen_ctx *);
void xu_ewmh_net_virtual_roots(struct screen_ctx *);
void xu_ewmh_net_current_desktop(struct screen_ctx *, long);
void xu_ewmh_net_desktop_names(struct screen_ctx *, char *,
int);
void xu_ewmh_net_desktop_names(struct screen_ctx *);
void xu_ewmh_net_wm_desktop(struct client_ctx *);
Atom *xu_ewmh_get_net_wm_state(struct client_ctx *, int *);

View File

@ -238,6 +238,17 @@ client_freeze(struct client_ctx *cc)
cc->flags |= CLIENT_FREEZE;
}
void
client_sticky(struct client_ctx *cc)
{
if (cc->flags & CLIENT_STICKY)
cc->flags &= ~CLIENT_STICKY;
else
cc->flags |= CLIENT_STICKY;
xu_ewmh_set_net_wm_state(cc);
}
void
client_fullscreen(struct client_ctx *cc)
{
@ -468,6 +479,9 @@ client_ptrsave(struct client_ctx *cc)
void
client_hide(struct client_ctx *cc)
{
if (cc->flags & CLIENT_STICKY)
return;
XUnmapWindow(X_Dpy, cc->win);
cc->active = 0;
@ -481,6 +495,9 @@ client_hide(struct client_ctx *cc)
void
client_unhide(struct client_ctx *cc)
{
if (cc->flags & CLIENT_STICKY)
return;
XMapRaised(X_Dpy, cc->win);
cc->flags &= ~CLIENT_HIDDEN;
@ -869,7 +886,7 @@ client_transient(struct client_ctx *cc)
if (XGetTransientForHint(X_Dpy, cc->win, &trans)) {
if ((tc = client_find(trans)) && tc->group) {
group_movetogroup(cc, tc->group->shortcut);
group_movetogroup(cc, tc->group->num);
if (tc->flags & CLIENT_IGNORE)
cc->flags |= CLIENT_IGNORE;
}

89
conf.c
View File

@ -41,27 +41,19 @@ conf_cmd_add(struct conf *c, const char *name, const char *path)
{
struct cmd *cmd;
/* "term" and "lock" have special meanings. */
if (strcmp(name, "term") == 0) {
if (strlcpy(c->termpath, path, sizeof(c->termpath)) >=
sizeof(c->termpath))
return (0);
} else if (strcmp(name, "lock") == 0) {
if (strlcpy(c->lockpath, path, sizeof(c->lockpath)) >=
sizeof(c->lockpath))
return (0);
} else {
conf_cmd_remove(c, name);
cmd = xmalloc(sizeof(*cmd));
cmd = xmalloc(sizeof(*cmd));
cmd->name = xstrdup(name);
if (strlcpy(cmd->path, path, sizeof(cmd->path)) >=
sizeof(cmd->path))
return (0);
TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry);
cmd->name = xstrdup(name);
if (strlcpy(cmd->path, path, sizeof(cmd->path)) >= sizeof(cmd->path)) {
free(cmd->name);
free(cmd);
return(0);
}
return (1);
conf_cmd_remove(c, name);
TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry);
return(1);
}
static void
@ -78,7 +70,7 @@ conf_cmd_remove(struct conf *c, const char *name)
}
}
void
conf_autogroup(struct conf *c, int no, const char *val)
conf_autogroup(struct conf *c, int num, const char *val)
{
struct autogroupwin *aw;
char *p;
@ -93,7 +85,7 @@ conf_autogroup(struct conf *c, int no, const char *val)
aw->name = xstrdup(val);
aw->class = xstrdup(p);
}
aw->num = no;
aw->num = num;
TAILQ_INSERT_TAIL(&c->autogroupq, aw, entry);
}
@ -204,6 +196,7 @@ static const struct {
{ "CM-g", "grouptoggle" },
{ "CM-f", "fullscreen" },
{ "CM-m", "maximize" },
{ "CM-s", "sticky" },
{ "CM-equal", "vmaximize" },
{ "CMS-equal", "hmaximize" },
{ "CMS-f", "freeze" },
@ -250,8 +243,6 @@ conf_init(struct conf *c)
{
unsigned int i;
(void)memset(c, 0, sizeof(*c));
c->bwidth = CONF_BWIDTH;
c->mamount = CONF_MAMOUNT;
c->snapdist = CONF_SNAPDIST;
@ -346,7 +337,7 @@ static const struct {
void (*handler)(struct client_ctx *, union arg *);
int flags;
union arg argument;
} name_to_kbfunc[] = {
} name_to_func[] = {
{ "lower", kbfunc_client_lower, CWM_WIN, {0} },
{ "raise", kbfunc_client_raise, CWM_WIN, {0} },
{ "search", kbfunc_client_search, 0, {0} },
@ -391,6 +382,7 @@ static const struct {
{ "rcycleingroup", kbfunc_client_cycle, CWM_WIN,
{.i = CWM_RCYCLE|CWM_INGROUP} },
{ "grouptoggle", kbfunc_client_grouptoggle, CWM_WIN, {0}},
{ "sticky", kbfunc_client_sticky, CWM_WIN, {0} },
{ "fullscreen", kbfunc_client_fullscreen, CWM_WIN, {0} },
{ "maximize", kbfunc_client_maximize, CWM_WIN, {0} },
{ "vmaximize", kbfunc_client_vmaximize, CWM_WIN, {0} },
@ -453,6 +445,15 @@ static const struct {
{.i = (CWM_RIGHT|CWM_PTRMOVE|CWM_BIGMOVE)} },
{ "htile", kbfunc_tile, CWM_WIN, {.i = CWM_TILE_HORIZ} },
{ "vtile", kbfunc_tile, CWM_WIN, {.i = CWM_TILE_VERT} },
{ "window_lower", kbfunc_client_lower, CWM_WIN, {0} },
{ "window_raise", kbfunc_client_raise, CWM_WIN, {0} },
{ "window_hide", kbfunc_client_hide, CWM_WIN, {0} },
{ "window_move", mousefunc_client_move, CWM_WIN, {0} },
{ "window_resize", mousefunc_client_resize, CWM_WIN, {0} },
{ "window_grouptoggle", mousefunc_client_grouptoggle, CWM_WIN, {0} },
{ "menu_group", mousefunc_menu_group, 0, {0} },
{ "menu_unhide", mousefunc_menu_unhide, 0, {0} },
{ "menu_cmd", mousefunc_menu_cmd, 0, {0} },
};
static const struct {
@ -510,13 +511,13 @@ conf_bind_kbd(struct conf *c, const char *bind, const char *cmd)
return (1);
}
for (i = 0; i < nitems(name_to_kbfunc); i++) {
if (strcmp(name_to_kbfunc[i].tag, cmd) != 0)
for (i = 0; i < nitems(name_to_func); i++) {
if (strcmp(name_to_func[i].tag, cmd) != 0)
continue;
kb->callback = name_to_kbfunc[i].handler;
kb->flags = name_to_kbfunc[i].flags;
kb->argument = name_to_kbfunc[i].argument;
kb->callback = name_to_func[i].handler;
kb->flags = name_to_func[i].flags;
kb->argument = name_to_func[i].argument;
kb->argtype |= ARG_INT;
TAILQ_INSERT_TAIL(&c->keybindingq, kb, entry);
return (1);
@ -548,25 +549,6 @@ conf_unbind_kbd(struct conf *c, struct binding *unbind)
}
}
static const struct {
const char *tag;
void (*handler)(struct client_ctx *, union arg *);
int flags;
union arg argument;
} name_to_mousefunc[] = {
{ "window_lower", kbfunc_client_lower, CWM_WIN, {0} },
{ "window_raise", kbfunc_client_raise, CWM_WIN, {0} },
{ "window_hide", kbfunc_client_hide, CWM_WIN, {0} },
{ "cyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_CYCLE} },
{ "rcyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_RCYCLE} },
{ "window_move", mousefunc_client_move, CWM_WIN, {0} },
{ "window_resize", mousefunc_client_resize, CWM_WIN, {0} },
{ "window_grouptoggle", mousefunc_client_grouptoggle, CWM_WIN, {0} },
{ "menu_group", mousefunc_menu_group, 0, {0} },
{ "menu_unhide", mousefunc_menu_unhide, 0, {0} },
{ "menu_cmd", mousefunc_menu_cmd, 0, {0} },
};
int
conf_bind_mouse(struct conf *c, const char *bind, const char *cmd)
{
@ -593,13 +575,13 @@ conf_bind_mouse(struct conf *c, const char *bind, const char *cmd)
return (1);
}
for (i = 0; i < nitems(name_to_mousefunc); i++) {
if (strcmp(name_to_mousefunc[i].tag, cmd) != 0)
for (i = 0; i < nitems(name_to_func); i++) {
if (strcmp(name_to_func[i].tag, cmd) != 0)
continue;
mb->callback = name_to_mousefunc[i].handler;
mb->flags = name_to_mousefunc[i].flags;
mb->argument = name_to_mousefunc[i].argument;
mb->callback = name_to_func[i].handler;
mb->flags = name_to_func[i].flags;
mb->argument = name_to_func[i].argument;
TAILQ_INSERT_TAIL(&c->mousebindingq, mb, entry);
return (1);
}
@ -690,6 +672,7 @@ static char *ewmhints[] = {
"_NET_WM_DESKTOP",
"_NET_CLOSE_WINDOW",
"_NET_WM_STATE",
"_NET_WM_STATE_STICKY",
"_NET_WM_STATE_MAXIMIZED_VERT",
"_NET_WM_STATE_MAXIMIZED_HORZ",
"_NET_WM_STATE_FULLSCREEN",

4
cwm.1
View File

@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: December 16 2013 $
.Dd $Mdocdate$
.Dt CWM 1
.Os
.Sh NAME
@ -90,6 +90,8 @@ Cycle through active groups.
Reverse cycle through active groups.
.It Ic CMS-f
Toggle freezing geometry of current window.
.It Ic CM-s
Toggle stickiness of current window.
.It Ic CM-f
Toggle full-screen mode of current window.
.It Ic CM-m

View File

@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: December 16 2013 $
.Dd $Mdocdate$
.Dt CWMRC 5
.Os
.Sh NAME
@ -341,6 +341,8 @@ Raise current window.
Label current window.
.It freeze
Freeze current window geometry.
.It sticky
Stick current window to all groups (same as assigning to nogroup).
.It fullscreen
Full-screen current window (gap + border removed).
.It maximize

241
group.c
View File

@ -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);
}

View File

@ -159,7 +159,6 @@ kbfunc_client_search(struct client_ctx *cc, union arg *arg)
cc = (struct client_ctx *)mi->ctx;
if (cc->flags & CLIENT_HIDDEN)
client_unhide(cc);
if (old_cc)
client_ptrsave(old_cc);
client_ptrwarp(cc);
@ -214,13 +213,23 @@ kbfunc_cmdexec(struct client_ctx *cc, union arg *arg)
void
kbfunc_term(struct client_ctx *cc, union arg *arg)
{
u_spawn(Conf.termpath);
struct cmd *cmd;
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
if (strcmp(cmd->name, "term") == 0)
u_spawn(cmd->path);
}
}
void
kbfunc_lock(struct client_ctx *cc, union arg *arg)
{
u_spawn(Conf.lockpath);
struct cmd *cmd;
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
if (strcmp(cmd->name, "lock") == 0)
u_spawn(cmd->path);
}
}
void
@ -310,12 +319,13 @@ void
kbfunc_ssh(struct client_ctx *cc, union arg *arg)
{
struct screen_ctx *sc = cc->sc;
struct cmd *cmd;
struct menu *mi;
struct menu_q menuq;
FILE *fp;
char *buf, *lbuf, *p;
char hostbuf[MAXHOSTNAMELEN];
char cmd[256];
char path[MAXPATHLEN];
int l;
size_t len;
@ -324,6 +334,11 @@ kbfunc_ssh(struct client_ctx *cc, union arg *arg)
return;
}
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
if (strcmp(cmd->name, "term") == 0)
break;
}
TAILQ_INIT(&menuq);
lbuf = NULL;
@ -356,10 +371,10 @@ kbfunc_ssh(struct client_ctx *cc, union arg *arg)
search_match_exec, NULL)) != NULL) {
if (mi->text[0] == '\0')
goto out;
l = snprintf(cmd, sizeof(cmd), "%s -T '[ssh] %s' -e ssh %s",
Conf.termpath, mi->text, mi->text);
if (l != -1 && l < sizeof(cmd))
u_spawn(cmd);
l = snprintf(path, sizeof(path), "%s -T '[ssh] %s' -e ssh %s",
cmd->path, mi->text, mi->text);
if (l != -1 && l < sizeof(path))
u_spawn(path);
}
out:
if (mi != NULL && mi->dummy)
@ -432,6 +447,12 @@ kbfunc_client_movetogroup(struct client_ctx *cc, union arg *arg)
group_movetogroup(cc, arg->i);
}
void
kbfunc_client_sticky(struct client_ctx *cc, union arg *arg)
{
client_sticky(cc);
}
void
kbfunc_client_fullscreen(struct client_ctx *cc, union arg *arg)
{

4
menu.c
View File

@ -260,7 +260,7 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq,
* even if dummy is zero, we need to return something.
*/
if ((mi = TAILQ_FIRST(resultq)) == NULL) {
mi = xmalloc(sizeof *mi);
mi = xmalloc(sizeof(*mi));
(void)strlcpy(mi->text,
mc->searchstr, sizeof(mi->text));
mi->dummy = 1;
@ -302,7 +302,7 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq,
mc->list = !mc->list;
break;
case CTL_ABORT:
mi = xmalloc(sizeof *mi);
mi = xmalloc(sizeof(*mi));
mi->text[0] = '\0';
mi->dummy = 1;
mi->abort = 1;

View File

@ -181,7 +181,30 @@ mousefunc_client_grouptoggle(struct client_ctx *cc, union arg *arg)
void
mousefunc_menu_group(struct client_ctx *cc, union arg *arg)
{
group_menu(cc->sc);
struct screen_ctx *sc = cc->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,
group_hidden_state(gc) ? "%d: [%s]" : "%d: %s",
gc->num, gc->name);
}
if (TAILQ_EMPTY(&menuq))
return;
if ((mi = menu_filter(sc, &menuq, NULL, NULL, 0,
NULL, NULL)) != NULL) {
gc = (struct group_ctx *)mi->ctx;
(group_hidden_state(gc)) ?
group_show(sc, gc) : group_hide(sc, gc);
}
menuq_clear(&menuq);
}
void
@ -196,16 +219,15 @@ mousefunc_menu_unhide(struct client_ctx *cc, union arg *arg)
old_cc = client_current();
TAILQ_INIT(&menuq);
TAILQ_FOREACH(cc, &Clientq, entry)
TAILQ_FOREACH(cc, &Clientq, entry) {
if (cc->flags & CLIENT_HIDDEN) {
wname = (cc->label) ? cc->label : cc->name;
if (wname == NULL)
continue;
menuq_add(&menuq, cc, "(%d) %s",
cc->group->shortcut, wname);
cc->group ? cc->group->num : 0, wname);
}
}
if (TAILQ_EMPTY(&menuq))
return;
@ -213,7 +235,6 @@ mousefunc_menu_unhide(struct client_ctx *cc, union arg *arg)
NULL, NULL)) != NULL) {
cc = (struct client_ctx *)mi->ctx;
client_unhide(cc);
if (old_cc != NULL)
client_ptrsave(old_cc);
client_ptrwarp(cc);
@ -233,7 +254,6 @@ mousefunc_menu_cmd(struct client_ctx *cc, union arg *arg)
TAILQ_INIT(&menuq);
TAILQ_FOREACH(cmd, &Conf.cmdq, entry)
menuq_add(&menuq, cmd, "%s", cmd->name);
if (TAILQ_EMPTY(&menuq))
return;

View File

@ -69,7 +69,6 @@ screen_init(int which)
XFree(wins);
}
screen_updatestackingorder(sc);
group_set_state(sc);
if (HasRandr)
XRRSelectInput(X_Dpy, sc->rootwin, RRScreenChangeNotifyMask);
@ -105,7 +104,7 @@ screen_updatestackingorder(struct screen_ctx *sc)
if ((cc = client_find(wins[i])) == NULL ||
cc->flags & CLIENT_HIDDEN)
continue;
cc->stackingorder = s++;
}
XFree(wins);
@ -142,7 +141,7 @@ screen_update_geometry(struct screen_ctx *sc)
{
XineramaScreenInfo *info = NULL;
struct region_ctx *region;
int info_no = 0, i;
int info_num = 0, i;
sc->view.x = 0;
sc->view.y = 0;
@ -156,13 +155,13 @@ screen_update_geometry(struct screen_ctx *sc)
/* RandR event may have a CTRC added or removed. */
if (XineramaIsActive(X_Dpy))
info = XineramaQueryScreens(X_Dpy, &info_no);
info = XineramaQueryScreens(X_Dpy, &info_num);
while ((region = TAILQ_FIRST(&sc->regionq)) != NULL) {
TAILQ_REMOVE(&sc->regionq, region, entry);
free(region);
}
for (i = 0; i < info_no; i++) {
for (i = 0; i < info_num; i++) {
region = xmalloc(sizeof(*region));
region->num = i;
region->area.x = info[i].x_org;

View File

@ -143,7 +143,7 @@ search_print_client(struct menu *mi, int list)
cc->matchname = cc->name;
(void)snprintf(mi->print, sizeof(mi->print), "(%d) %c%s",
cc->group->shortcut, flag, cc->matchname);
cc->group ? cc->group->num : 0, flag, cc->matchname);
if (!list && cc->matchname != cc->name &&
strlen(mi->print) < sizeof(mi->print) - 1) {

View File

@ -196,7 +196,7 @@ xev_handle_propertynotify(XEvent *ee)
TAILQ_FOREACH(sc, &Screenq, entry) {
if (sc->rootwin == e->window) {
if (e->atom == ewmh[_NET_DESKTOP_NAMES])
group_update_names(sc);
xu_ewmh_net_desktop_names(sc);
}
}
}

63
xutil.c
View File

@ -281,20 +281,67 @@ xu_ewmh_net_current_desktop(struct screen_ctx *sc, long idx)
}
void
xu_ewmh_net_desktop_names(struct screen_ctx *sc, char *data, int n)
xu_ewmh_net_desktop_names(struct screen_ctx *sc)
{
struct group_ctx *gc;
char *p, *q;
unsigned char *prop_ret;
int i = 0, j = 0, nstrings = 0, n = 0;
size_t len = 0, tlen, slen;
/* Let group names be overwritten if _NET_DESKTOP_NAMES is set. */
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++;
}
}
p = (char *)prop_ret;
while (n < nstrings) {
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == n) {
free(gc->name);
gc->name = xstrdup(p);
p += strlen(p) + 1;
break;
}
}
n++;
}
if (prop_ret != NULL)
XFree(prop_ret);
TAILQ_FOREACH(gc, &sc->groupq, entry)
len += strlen(gc->name) + 1;
q = p = xcalloc(len, sizeof(*p));
tlen = len;
TAILQ_FOREACH(gc, &sc->groupq, entry) {
slen = strlen(gc->name) + 1;
(void)strlcpy(q, gc->name, tlen);
tlen -= slen;
q += slen;
}
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_DESKTOP_NAMES],
cwmh[UTF8_STRING], 8, PropModeReplace, (unsigned char *)data, n);
cwmh[UTF8_STRING], 8, PropModeReplace, (unsigned char *)p, len);
}
/* Application Window Properties */
void
xu_ewmh_net_wm_desktop(struct client_ctx *cc)
{
long no = cc->group->shortcut;
long num = 0xffffffff;
if (cc->group)
num = cc->group->num;
XChangeProperty(X_Dpy, cc->win, ewmh[_NET_WM_DESKTOP],
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&no, 1);
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&num, 1);
}
Atom *
@ -323,6 +370,9 @@ xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action,
int property;
void (*toggle)(struct client_ctx *);
} handlers[] = {
{ _NET_WM_STATE_STICKY,
CLIENT_STICKY,
client_sticky },
{ _NET_WM_STATE_MAXIMIZED_VERT,
CLIENT_VMAXIMIZED,
client_vmaximize },
@ -364,6 +414,8 @@ xu_ewmh_restore_net_wm_state(struct client_ctx *cc)
atoms = xu_ewmh_get_net_wm_state(cc, &n);
for (i = 0; i < n; i++) {
if (atoms[i] == ewmh[_NET_WM_STATE_STICKY])
client_sticky(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_HORZ])
client_hmaximize(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_VERT])
@ -388,10 +440,13 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc)
if (oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_HORZ] &&
oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_VERT] &&
oatoms[i] != ewmh[_NET_WM_STATE_FULLSCREEN] &&
oatoms[i] != ewmh[_NET_WM_STATE_STICKY] &&
oatoms[i] != ewmh[_NET_WM_STATE_DEMANDS_ATTENTION])
atoms[j++] = oatoms[i];
}
free(oatoms);
if (cc->flags & CLIENT_STICKY)
atoms[j++] = ewmh[_NET_WM_STATE_STICKY];
if (cc->flags & CLIENT_FULLSCREEN)
atoms[j++] = ewmh[_NET_WM_STATE_FULLSCREEN];
else {