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

View File

@ -199,6 +199,7 @@ struct client_ctx {
#define CLIENT_WM_TAKE_FOCUS 0x0200 #define CLIENT_WM_TAKE_FOCUS 0x0200
#define CLIENT_URGENCY 0x0400 #define CLIENT_URGENCY 0x0400
#define CLIENT_FULLSCREEN 0x0800 #define CLIENT_FULLSCREEN 0x0800
#define CLIENT_STICKY 0x1000
#define CLIENT_HIGHLIGHT (CLIENT_GROUP | CLIENT_UNGROUP) #define CLIENT_HIGHLIGHT (CLIENT_GROUP | CLIENT_UNGROUP)
#define CLIENT_MAXFLAGS (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED) #define CLIENT_MAXFLAGS (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED)
@ -222,10 +223,8 @@ TAILQ_HEAD(cycle_entry_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;
int shortcut; char *name;
int hidden; int num;
int nhidden;
int highstack;
}; };
TAILQ_HEAD(group_ctx_q, group_ctx); TAILQ_HEAD(group_ctx_q, group_ctx);
@ -263,9 +262,7 @@ struct screen_ctx {
struct group_ctx groups[CALMWM_NGROUPS]; struct group_ctx groups[CALMWM_NGROUPS];
struct group_ctx_q groupq; struct group_ctx_q groupq;
int group_hideall; int group_hideall;
int group_nonames;
struct group_ctx *group_active; struct group_ctx *group_active;
char **group_names;
}; };
TAILQ_HEAD(screen_ctx_q, screen_ctx); TAILQ_HEAD(screen_ctx_q, screen_ctx);
@ -316,8 +313,6 @@ struct conf {
int snapdist; int snapdist;
struct gap gap; struct gap gap;
char *color[CWM_COLOR_NITEMS]; char *color[CWM_COLOR_NITEMS];
char termpath[MAXPATHLEN];
char lockpath[MAXPATHLEN];
char known_hosts[MAXPATHLEN]; char known_hosts[MAXPATHLEN];
#define CONF_FONT "sans-serif:pixelsize=14:bold" #define CONF_FONT "sans-serif:pixelsize=14:bold"
char *font; char *font;
@ -371,7 +366,8 @@ enum {
_NET_WM_DESKTOP, _NET_WM_DESKTOP,
_NET_CLOSE_WINDOW, _NET_CLOSE_WINDOW,
_NET_WM_STATE, _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_VERT,
_NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_HORZ,
_NET_WM_STATE_FULLSCREEN, _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_setactive(struct client_ctx *);
void client_setname(struct client_ctx *); void client_setname(struct client_ctx *);
int client_snapcalc(int, int, int, int, int); int client_snapcalc(int, int, int, int, int);
void client_sticky(struct client_ctx *);
void client_transient(struct client_ctx *); void client_transient(struct client_ctx *);
void client_unhide(struct client_ctx *); void client_unhide(struct client_ctx *);
void client_urgency(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_alltoggle(struct screen_ctx *);
void group_autogroup(struct client_ctx *); void group_autogroup(struct client_ctx *);
void group_cycle(struct screen_ctx *, int); 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_hidetoggle(struct screen_ctx *, int);
void group_init(struct screen_ctx *); void group_init(struct screen_ctx *);
void group_menu(struct screen_ctx *);
void group_movetogroup(struct client_ctx *, int); void group_movetogroup(struct client_ctx *, int);
void group_only(struct screen_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(struct client_ctx *);
void group_sticky_toggle_enter(struct client_ctx *); void group_sticky_toggle_enter(struct client_ctx *);
void group_sticky_toggle_exit(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_raise(struct client_ctx *, union arg *);
void kbfunc_client_rcycle(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_search(struct client_ctx *, union arg *);
void kbfunc_client_sticky(struct client_ctx *, union arg *);
void kbfunc_client_vmaximize(struct client_ctx *, void kbfunc_client_vmaximize(struct client_ctx *,
union arg *); union arg *);
void kbfunc_cmdexec(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_showing_desktop(struct screen_ctx *);
void xu_ewmh_net_virtual_roots(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_current_desktop(struct screen_ctx *, long);
void xu_ewmh_net_desktop_names(struct screen_ctx *, char *, void xu_ewmh_net_desktop_names(struct screen_ctx *);
int);
void xu_ewmh_net_wm_desktop(struct client_ctx *); void xu_ewmh_net_wm_desktop(struct client_ctx *);
Atom *xu_ewmh_get_net_wm_state(struct client_ctx *, int *); 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; 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 void
client_fullscreen(struct client_ctx *cc) client_fullscreen(struct client_ctx *cc)
{ {
@ -468,6 +479,9 @@ client_ptrsave(struct client_ctx *cc)
void void
client_hide(struct client_ctx *cc) client_hide(struct client_ctx *cc)
{ {
if (cc->flags & CLIENT_STICKY)
return;
XUnmapWindow(X_Dpy, cc->win); XUnmapWindow(X_Dpy, cc->win);
cc->active = 0; cc->active = 0;
@ -481,6 +495,9 @@ client_hide(struct client_ctx *cc)
void void
client_unhide(struct client_ctx *cc) client_unhide(struct client_ctx *cc)
{ {
if (cc->flags & CLIENT_STICKY)
return;
XMapRaised(X_Dpy, cc->win); XMapRaised(X_Dpy, cc->win);
cc->flags &= ~CLIENT_HIDDEN; cc->flags &= ~CLIENT_HIDDEN;
@ -869,7 +886,7 @@ client_transient(struct client_ctx *cc)
if (XGetTransientForHint(X_Dpy, cc->win, &trans)) { if (XGetTransientForHint(X_Dpy, cc->win, &trans)) {
if ((tc = client_find(trans)) && tc->group) { if ((tc = client_find(trans)) && tc->group) {
group_movetogroup(cc, tc->group->shortcut); group_movetogroup(cc, tc->group->num);
if (tc->flags & CLIENT_IGNORE) if (tc->flags & CLIENT_IGNORE)
cc->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; struct cmd *cmd;
/* "term" and "lock" have special meanings. */ cmd = xmalloc(sizeof(*cmd));
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->name = xstrdup(name);
if (strlcpy(cmd->path, path, sizeof(cmd->path)) >= sizeof(cmd->path)) {
cmd->name = xstrdup(name); free(cmd->name);
if (strlcpy(cmd->path, path, sizeof(cmd->path)) >= free(cmd);
sizeof(cmd->path)) return(0);
return (0);
TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry);
} }
return (1);
conf_cmd_remove(c, name);
TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry);
return(1);
} }
static void static void
@ -78,7 +70,7 @@ conf_cmd_remove(struct conf *c, const char *name)
} }
} }
void void
conf_autogroup(struct conf *c, int no, const char *val) conf_autogroup(struct conf *c, int num, const char *val)
{ {
struct autogroupwin *aw; struct autogroupwin *aw;
char *p; char *p;
@ -93,7 +85,7 @@ conf_autogroup(struct conf *c, int no, const char *val)
aw->name = xstrdup(val); aw->name = xstrdup(val);
aw->class = xstrdup(p); aw->class = xstrdup(p);
} }
aw->num = no; aw->num = num;
TAILQ_INSERT_TAIL(&c->autogroupq, aw, entry); TAILQ_INSERT_TAIL(&c->autogroupq, aw, entry);
} }
@ -204,6 +196,7 @@ static const struct {
{ "CM-g", "grouptoggle" }, { "CM-g", "grouptoggle" },
{ "CM-f", "fullscreen" }, { "CM-f", "fullscreen" },
{ "CM-m", "maximize" }, { "CM-m", "maximize" },
{ "CM-s", "sticky" },
{ "CM-equal", "vmaximize" }, { "CM-equal", "vmaximize" },
{ "CMS-equal", "hmaximize" }, { "CMS-equal", "hmaximize" },
{ "CMS-f", "freeze" }, { "CMS-f", "freeze" },
@ -250,8 +243,6 @@ conf_init(struct conf *c)
{ {
unsigned int i; unsigned int i;
(void)memset(c, 0, sizeof(*c));
c->bwidth = CONF_BWIDTH; c->bwidth = CONF_BWIDTH;
c->mamount = CONF_MAMOUNT; c->mamount = CONF_MAMOUNT;
c->snapdist = CONF_SNAPDIST; c->snapdist = CONF_SNAPDIST;
@ -346,7 +337,7 @@ static const struct {
void (*handler)(struct client_ctx *, union arg *); void (*handler)(struct client_ctx *, union arg *);
int flags; int flags;
union arg argument; union arg argument;
} name_to_kbfunc[] = { } name_to_func[] = {
{ "lower", kbfunc_client_lower, CWM_WIN, {0} }, { "lower", kbfunc_client_lower, CWM_WIN, {0} },
{ "raise", kbfunc_client_raise, CWM_WIN, {0} }, { "raise", kbfunc_client_raise, CWM_WIN, {0} },
{ "search", kbfunc_client_search, 0, {0} }, { "search", kbfunc_client_search, 0, {0} },
@ -391,6 +382,7 @@ static const struct {
{ "rcycleingroup", kbfunc_client_cycle, CWM_WIN, { "rcycleingroup", kbfunc_client_cycle, CWM_WIN,
{.i = CWM_RCYCLE|CWM_INGROUP} }, {.i = CWM_RCYCLE|CWM_INGROUP} },
{ "grouptoggle", kbfunc_client_grouptoggle, CWM_WIN, {0}}, { "grouptoggle", kbfunc_client_grouptoggle, CWM_WIN, {0}},
{ "sticky", kbfunc_client_sticky, CWM_WIN, {0} },
{ "fullscreen", kbfunc_client_fullscreen, CWM_WIN, {0} }, { "fullscreen", kbfunc_client_fullscreen, CWM_WIN, {0} },
{ "maximize", kbfunc_client_maximize, CWM_WIN, {0} }, { "maximize", kbfunc_client_maximize, CWM_WIN, {0} },
{ "vmaximize", kbfunc_client_vmaximize, CWM_WIN, {0} }, { "vmaximize", kbfunc_client_vmaximize, CWM_WIN, {0} },
@ -453,6 +445,15 @@ static const struct {
{.i = (CWM_RIGHT|CWM_PTRMOVE|CWM_BIGMOVE)} }, {.i = (CWM_RIGHT|CWM_PTRMOVE|CWM_BIGMOVE)} },
{ "htile", kbfunc_tile, CWM_WIN, {.i = CWM_TILE_HORIZ} }, { "htile", kbfunc_tile, CWM_WIN, {.i = CWM_TILE_HORIZ} },
{ "vtile", kbfunc_tile, CWM_WIN, {.i = CWM_TILE_VERT} }, { "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 { static const struct {
@ -510,13 +511,13 @@ conf_bind_kbd(struct conf *c, const char *bind, const char *cmd)
return (1); return (1);
} }
for (i = 0; i < nitems(name_to_kbfunc); i++) { for (i = 0; i < nitems(name_to_func); i++) {
if (strcmp(name_to_kbfunc[i].tag, cmd) != 0) if (strcmp(name_to_func[i].tag, cmd) != 0)
continue; continue;
kb->callback = name_to_kbfunc[i].handler; kb->callback = name_to_func[i].handler;
kb->flags = name_to_kbfunc[i].flags; kb->flags = name_to_func[i].flags;
kb->argument = name_to_kbfunc[i].argument; kb->argument = name_to_func[i].argument;
kb->argtype |= ARG_INT; kb->argtype |= ARG_INT;
TAILQ_INSERT_TAIL(&c->keybindingq, kb, entry); TAILQ_INSERT_TAIL(&c->keybindingq, kb, entry);
return (1); 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 int
conf_bind_mouse(struct conf *c, const char *bind, const char *cmd) 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); return (1);
} }
for (i = 0; i < nitems(name_to_mousefunc); i++) { for (i = 0; i < nitems(name_to_func); i++) {
if (strcmp(name_to_mousefunc[i].tag, cmd) != 0) if (strcmp(name_to_func[i].tag, cmd) != 0)
continue; continue;
mb->callback = name_to_mousefunc[i].handler; mb->callback = name_to_func[i].handler;
mb->flags = name_to_mousefunc[i].flags; mb->flags = name_to_func[i].flags;
mb->argument = name_to_mousefunc[i].argument; mb->argument = name_to_func[i].argument;
TAILQ_INSERT_TAIL(&c->mousebindingq, mb, entry); TAILQ_INSERT_TAIL(&c->mousebindingq, mb, entry);
return (1); return (1);
} }
@ -690,6 +672,7 @@ static char *ewmhints[] = {
"_NET_WM_DESKTOP", "_NET_WM_DESKTOP",
"_NET_CLOSE_WINDOW", "_NET_CLOSE_WINDOW",
"_NET_WM_STATE", "_NET_WM_STATE",
"_NET_WM_STATE_STICKY",
"_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_VERT",
"_NET_WM_STATE_MAXIMIZED_HORZ", "_NET_WM_STATE_MAXIMIZED_HORZ",
"_NET_WM_STATE_FULLSCREEN", "_NET_WM_STATE_FULLSCREEN",

4
cwm.1
View File

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

View File

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

241
group.c
View File

@ -33,13 +33,10 @@
#include "calmwm.h" #include "calmwm.h"
static void group_assign(struct group_ctx *, struct client_ctx *); static void group_assign(struct group_ctx *, struct client_ctx *);
static void group_hide(struct screen_ctx *, struct group_ctx *); static void group_restack(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 *, long); 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", "nogroup", "one", "two", "three", "four", "five", "six",
"seven", "eight", "nine" "seven", "eight", "nine"
}; };
@ -47,63 +44,62 @@ const char *shortcut_to_name[] = {
static void static void
group_assign(struct group_ctx *gc, struct client_ctx *cc) 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) if (cc->group != NULL)
TAILQ_REMOVE(&cc->group->clients, cc, group_entry); TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
TAILQ_INSERT_TAIL(&gc->clients, cc, group_entry);
cc->group = gc; cc->group = gc;
if (cc->group != NULL)
TAILQ_INSERT_TAIL(&gc->clients, cc, group_entry);
xu_ewmh_net_wm_desktop(cc); xu_ewmh_net_wm_desktop(cc);
} }
static void void
group_hide(struct screen_ctx *sc, struct group_ctx *gc) group_hide(struct screen_ctx *sc, struct group_ctx *gc)
{ {
struct client_ctx *cc; struct client_ctx *cc;
screen_updatestackingorder(sc); screen_updatestackingorder(sc);
gc->nhidden = 0; TAILQ_FOREACH(cc, &gc->clients, group_entry)
gc->highstack = 0;
TAILQ_FOREACH(cc, &gc->clients, group_entry) {
client_hide(cc); client_hide(cc);
gc->nhidden++; }
if (cc->stackingorder > gc->highstack)
gc->highstack = cc->stackingorder; void
} group_show(struct screen_ctx *sc, struct group_ctx *gc)
gc->hidden = 1; /* XXX: equivalent to gc->nhidden > 0 */ {
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 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; struct client_ctx *cc;
Window *winlist; Window *winlist;
int i, lastempty = -1; int i, lastempty = -1;
int nwins = 0, highstack = 0;
gc->highstack = 0;
TAILQ_FOREACH(cc, &gc->clients, group_entry) { TAILQ_FOREACH(cc, &gc->clients, group_entry) {
if (cc->stackingorder > gc->highstack) if (cc->stackingorder > highstack)
gc->highstack = cc->stackingorder; highstack = cc->stackingorder;
} }
winlist = xcalloc((gc->highstack + 1), sizeof(*winlist)); winlist = xcalloc((highstack + 1), sizeof(*winlist));
/* /* Invert the stacking order for XRestackWindows(). */
* Invert the stacking order as XRestackWindows() expects them
* top-to-bottom.
*/
TAILQ_FOREACH(cc, &gc->clients, group_entry) { TAILQ_FOREACH(cc, &gc->clients, group_entry) {
winlist[gc->highstack - cc->stackingorder] = cc->win; winlist[highstack - cc->stackingorder] = cc->win;
client_unhide(cc); nwins++;
} }
/* Un-sparseify */ /* Un-sparseify */
for (i = 0; i <= gc->highstack; i++) { for (i = 0; i <= highstack; i++) {
if (!winlist[i] && lastempty == -1) if (!winlist[i] && lastempty == -1)
lastempty = i; lastempty = i;
else if (winlist[i] && lastempty != -1) { 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); free(winlist);
gc->hidden = 0;
group_setactive(sc, gc->shortcut);
} }
void void
@ -127,19 +120,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].name = xstrdup(num_to_name[i]);
sc->groups[i].shortcut = i; sc->groups[i].num = i;
TAILQ_INSERT_TAIL(&sc->groupq, &sc->groups[i], entry); 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_desktop_viewport(sc);
xu_ewmh_net_wm_number_of_desktops(sc); xu_ewmh_net_wm_number_of_desktops(sc);
xu_ewmh_net_showing_desktop(sc); xu_ewmh_net_showing_desktop(sc);
@ -148,15 +137,6 @@ group_init(struct screen_ctx *sc)
group_setactive(sc, 1); 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 static void
group_setactive(struct screen_ctx *sc, long idx) 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); errx(1, "group_movetogroup: index out of range (%d)", idx);
gc = &sc->groups[idx]; gc = &sc->groups[idx];
if (cc->group == gc) if (cc->group == gc)
return; return;
if (gc->hidden) { if (group_hidden_state(gc))
client_hide(cc); client_hide(cc);
gc->nhidden++;
}
group_assign(gc, cc); 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 int
group_fix_hidden_state(struct group_ctx *gc) group_hidden_state(struct group_ctx *gc)
{ {
struct client_ctx *cc; struct client_ctx *cc;
int same = 0; int hidden = 0, same = 0;
TAILQ_FOREACH(cc, &gc->clients, group_entry) { 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++; same++;
} }
if (same == 0) if (same == 0)
gc->hidden = !gc->hidden; hidden = !hidden;
return(hidden);
} }
void void
@ -238,9 +221,8 @@ group_hidetoggle(struct screen_ctx *sc, int idx)
errx(1, "group_hidetoggle: index out of range (%d)", idx); errx(1, "group_hidetoggle: index out of range (%d)", idx);
gc = &sc->groups[idx]; gc = &sc->groups[idx];
group_fix_hidden_state(gc);
if (gc->hidden) if (group_hidden_state(gc))
group_show(sc, gc); group_show(sc, gc);
else { else {
group_hide(sc, gc); 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); errx(1, "group_only: index out of range (%d)", idx);
TAILQ_FOREACH(gc, &sc->groupq, entry) { TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->shortcut == idx) if (gc->num == idx)
group_show(sc, gc); group_show(sc, gc);
else else
group_hide(sc, gc); group_hide(sc, gc);
@ -288,7 +270,7 @@ group_cycle(struct screen_ctx *sc, int flags)
if (!TAILQ_EMPTY(&gc->clients) && showgroup == NULL) if (!TAILQ_EMPTY(&gc->clients) && showgroup == NULL)
showgroup = gc; showgroup = gc;
else if (!gc->hidden) else if (!group_hidden_state(gc))
group_hide(sc, gc); group_hide(sc, gc);
} }
@ -297,39 +279,10 @@ group_cycle(struct screen_ctx *sc, int flags)
group_hide(sc, sc->group_active); group_hide(sc, sc->group_active);
if (showgroup->hidden) if (group_hidden_state(showgroup))
group_show(sc, showgroup); group_show(sc, showgroup);
else else
group_setactive(sc, showgroup->shortcut); group_setactive(sc, showgroup->num);
}
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);
} }
void void
@ -352,36 +305,38 @@ 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, both_match = 0; int num = -2, both_match = 0;
long *grpno; long *grpnum;
if (cc->ch.res_class == NULL || cc->ch.res_name == NULL) if (cc->ch.res_class == NULL || cc->ch.res_name == NULL)
return; return;
if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP], if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP],
XA_CARDINAL, 1, (unsigned char **)&grpno) > 0) { XA_CARDINAL, 1, (unsigned char **)&grpnum) > 0) {
if (*grpno == -1) num = *grpnum;
no = 0; if (num > CALMWM_NGROUPS || num < -1)
else if (*grpno > CALMWM_NGROUPS || *grpno < 0) num = CALMWM_NGROUPS - 1;
no = CALMWM_NGROUPS - 1; XFree(grpnum);
else
no = *grpno;
XFree(grpno);
} else { } else {
TAILQ_FOREACH(aw, &Conf.autogroupq, entry) { TAILQ_FOREACH(aw, &Conf.autogroupq, entry) {
if (strcmp(aw->class, cc->ch.res_class) == 0) { if (strcmp(aw->class, cc->ch.res_class) == 0) {
if ((aw->name != NULL) && if ((aw->name != NULL) &&
(strcmp(aw->name, cc->ch.res_name) == 0)) { (strcmp(aw->name, cc->ch.res_name) == 0)) {
no = aw->num; num = aw->num;
both_match = 1; both_match = 1;
} else if (aw->name == NULL && !both_match) } 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) { TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->shortcut == no) { if (gc->num == num) {
group_assign(gc, cc); group_assign(gc, cc);
return; return;
} }
@ -392,71 +347,3 @@ group_autogroup(struct client_ctx *cc)
else else
group_assign(NULL, cc); 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; cc = (struct client_ctx *)mi->ctx;
if (cc->flags & CLIENT_HIDDEN) if (cc->flags & CLIENT_HIDDEN)
client_unhide(cc); client_unhide(cc);
if (old_cc) if (old_cc)
client_ptrsave(old_cc); client_ptrsave(old_cc);
client_ptrwarp(cc); client_ptrwarp(cc);
@ -214,13 +213,23 @@ kbfunc_cmdexec(struct client_ctx *cc, union arg *arg)
void void
kbfunc_term(struct client_ctx *cc, union arg *arg) 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 void
kbfunc_lock(struct client_ctx *cc, union arg *arg) 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 void
@ -310,12 +319,13 @@ void
kbfunc_ssh(struct client_ctx *cc, union arg *arg) kbfunc_ssh(struct client_ctx *cc, union arg *arg)
{ {
struct screen_ctx *sc = cc->sc; struct screen_ctx *sc = cc->sc;
struct cmd *cmd;
struct menu *mi; struct menu *mi;
struct menu_q menuq; struct menu_q menuq;
FILE *fp; FILE *fp;
char *buf, *lbuf, *p; char *buf, *lbuf, *p;
char hostbuf[MAXHOSTNAMELEN]; char hostbuf[MAXHOSTNAMELEN];
char cmd[256]; char path[MAXPATHLEN];
int l; int l;
size_t len; size_t len;
@ -324,6 +334,11 @@ kbfunc_ssh(struct client_ctx *cc, union arg *arg)
return; return;
} }
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
if (strcmp(cmd->name, "term") == 0)
break;
}
TAILQ_INIT(&menuq); TAILQ_INIT(&menuq);
lbuf = NULL; lbuf = NULL;
@ -356,10 +371,10 @@ kbfunc_ssh(struct client_ctx *cc, union arg *arg)
search_match_exec, NULL)) != NULL) { search_match_exec, NULL)) != NULL) {
if (mi->text[0] == '\0') if (mi->text[0] == '\0')
goto out; goto out;
l = snprintf(cmd, sizeof(cmd), "%s -T '[ssh] %s' -e ssh %s", l = snprintf(path, sizeof(path), "%s -T '[ssh] %s' -e ssh %s",
Conf.termpath, mi->text, mi->text); cmd->path, mi->text, mi->text);
if (l != -1 && l < sizeof(cmd)) if (l != -1 && l < sizeof(path))
u_spawn(cmd); u_spawn(path);
} }
out: out:
if (mi != NULL && mi->dummy) if (mi != NULL && mi->dummy)
@ -432,6 +447,12 @@ kbfunc_client_movetogroup(struct client_ctx *cc, union arg *arg)
group_movetogroup(cc, arg->i); group_movetogroup(cc, arg->i);
} }
void
kbfunc_client_sticky(struct client_ctx *cc, union arg *arg)
{
client_sticky(cc);
}
void void
kbfunc_client_fullscreen(struct client_ctx *cc, union arg *arg) 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. * even if dummy is zero, we need to return something.
*/ */
if ((mi = TAILQ_FIRST(resultq)) == NULL) { if ((mi = TAILQ_FIRST(resultq)) == NULL) {
mi = xmalloc(sizeof *mi); mi = xmalloc(sizeof(*mi));
(void)strlcpy(mi->text, (void)strlcpy(mi->text,
mc->searchstr, sizeof(mi->text)); mc->searchstr, sizeof(mi->text));
mi->dummy = 1; mi->dummy = 1;
@ -302,7 +302,7 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq,
mc->list = !mc->list; mc->list = !mc->list;
break; break;
case CTL_ABORT: case CTL_ABORT:
mi = xmalloc(sizeof *mi); mi = xmalloc(sizeof(*mi));
mi->text[0] = '\0'; mi->text[0] = '\0';
mi->dummy = 1; mi->dummy = 1;
mi->abort = 1; mi->abort = 1;

View File

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

View File

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

View File

@ -196,7 +196,7 @@ xev_handle_propertynotify(XEvent *ee)
TAILQ_FOREACH(sc, &Screenq, entry) { TAILQ_FOREACH(sc, &Screenq, entry) {
if (sc->rootwin == e->window) { if (sc->rootwin == e->window) {
if (e->atom == ewmh[_NET_DESKTOP_NAMES]) 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 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], 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 */ /* Application Window Properties */
void void
xu_ewmh_net_wm_desktop(struct client_ctx *cc) 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], 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 * Atom *
@ -323,6 +370,9 @@ xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action,
int property; int property;
void (*toggle)(struct client_ctx *); void (*toggle)(struct client_ctx *);
} handlers[] = { } handlers[] = {
{ _NET_WM_STATE_STICKY,
CLIENT_STICKY,
client_sticky },
{ _NET_WM_STATE_MAXIMIZED_VERT, { _NET_WM_STATE_MAXIMIZED_VERT,
CLIENT_VMAXIMIZED, CLIENT_VMAXIMIZED,
client_vmaximize }, 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); atoms = xu_ewmh_get_net_wm_state(cc, &n);
for (i = 0; i < n; i++) { 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]) if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_HORZ])
client_hmaximize(cc); client_hmaximize(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_VERT]) 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] && if (oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_HORZ] &&
oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_VERT] && oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_VERT] &&
oatoms[i] != ewmh[_NET_WM_STATE_FULLSCREEN] && oatoms[i] != ewmh[_NET_WM_STATE_FULLSCREEN] &&
oatoms[i] != ewmh[_NET_WM_STATE_STICKY] &&
oatoms[i] != ewmh[_NET_WM_STATE_DEMANDS_ATTENTION]) oatoms[i] != ewmh[_NET_WM_STATE_DEMANDS_ATTENTION])
atoms[j++] = oatoms[i]; atoms[j++] = oatoms[i];
} }
free(oatoms); free(oatoms);
if (cc->flags & CLIENT_STICKY)
atoms[j++] = ewmh[_NET_WM_STATE_STICKY];
if (cc->flags & CLIENT_FULLSCREEN) if (cc->flags & CLIENT_FULLSCREEN)
atoms[j++] = ewmh[_NET_WM_STATE_FULLSCREEN]; atoms[j++] = ewmh[_NET_WM_STATE_FULLSCREEN];
else { else {