cvsimport

* refs/heads/master:
  Fixed memory leak in xu_get_strprop.
  Prevent out of boundary write with configuration files in which too many quoted arguments are stored for other window managers.
  Allow configuring a percentage window size of the master window during htile/vtile actions. From Uwe Werler, with a few manpage tweaks.
  zap stray tabs
  Instead of using _NET_ACTIVE_WINDOW on restart, use the pointer location to determine what client to set active. Reduces a round trip for every window.
  Add support for SIGINT/SIGTERM.
  Simplify conditional construct.
  Trim event_mask to those that the root window actually needs.
  No need to lookup current client early; move to right before it is needed.
  Recommit 1.259, but now with TAILQ_FOREACH_SAFE.
  Revert previous. Causes a crash as reported by Tom Murphy.
  Simplify list markup.
  Plug two memory leaks. Also get rid of a variable that is no longer necessary.
  Remove ColormaskChange from event-mask since there's no event handler.
  Unrelated style fixes, consistency changes and sorting, appropriate dosage/removal of wrappers, simplification of name queue, client cycle joins other kb/mb bound functions.
This commit is contained in:
Leah Neukirchen 2020-05-14 23:39:56 +02:00
commit 3a570bb679
15 changed files with 541 additions and 522 deletions

View File

@ -44,6 +44,7 @@ struct screen_q Screenq = TAILQ_HEAD_INITIALIZER(Screenq);
struct conf Conf;
volatile sig_atomic_t cwm_status;
__dead void usage(void);
static void sighdlr(int);
static int x_errorhandler(Display *, XErrorEvent *);
static int x_init(const char *);
@ -88,11 +89,12 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
if (signal(SIGCHLD, sighdlr) == SIG_ERR)
if (signal(SIGCHLD, sighdlr) == SIG_ERR ||
signal(SIGHUP, sighdlr) == SIG_ERR ||
signal(SIGINT, sighdlr) == SIG_ERR ||
signal(SIGTERM, sighdlr) == SIG_ERR)
err(1, "signal");
if (signal(SIGHUP, sighdlr) == SIG_ERR)
err(1, "signal");
if (parse_config(Conf.conf_file, &Conf) == -1) {
warnx("error parsing config file");
if (nflag)
@ -126,7 +128,7 @@ main(int argc, char **argv)
u_exec(fallback);
}
return(0);
return 0;
}
static int
@ -144,7 +146,7 @@ x_init(const char *dpyname)
Conf.xrandr = XRRQueryExtension(X_Dpy, &Conf.xrandr_event_base, &i);
conf_atoms();
xu_atom_init();
conf_cursor(&Conf);
for (i = 0; i < ScreenCount(X_Dpy); i++)
@ -182,7 +184,7 @@ static int
x_wmerrorhandler(Display *dpy, XErrorEvent *e)
{
errx(1, "root window unavailable - perhaps another wm is running?");
return(0);
return 0;
}
static int
@ -198,7 +200,7 @@ x_errorhandler(Display *dpy, XErrorEvent *e)
warnx("%s(0x%x): %s", req, (unsigned int)e->resourceid, msg);
#endif
return(0);
return 0;
}
static void
@ -217,6 +219,10 @@ sighdlr(int sig)
case SIGHUP:
cwm_status = CWM_EXEC_WM;
break;
case SIGINT:
case SIGTERM:
cwm_status = CWM_QUIT;
break;
}
errno = save_errno;

View File

@ -84,7 +84,6 @@ size_t strlcpy(char *, const char *, size_t);
#define CWM_UP_LEFT (CWM_UP | CWM_LEFT)
#define CWM_DOWN_RIGHT (CWM_DOWN | CWM_RIGHT)
#define CWM_DOWN_LEFT (CWM_DOWN | CWM_LEFT)
#define DIRECTIONMASK (CWM_UP | CWM_DOWN | CWM_LEFT | CWM_RIGHT)
#define CWM_CYCLE_FORWARD 0x0001
#define CWM_CYCLE_REVERSE 0x0002
@ -121,11 +120,6 @@ struct geom {
int w;
int h;
};
enum apply_gap {
CWM_NOGAP = 0,
CWM_GAP
};
struct gap {
int top;
int bottom;
@ -197,8 +191,9 @@ struct client_ctx {
struct name_q nameq;
char *name;
char *label;
XClassHint ch;
XWMHints *wmh;
char *res_class; /* class hint */
char *res_name; /* class hint */
int initial_state; /* wm hint */
};
TAILQ_HEAD(client_q, client_ctx);
@ -317,6 +312,8 @@ struct conf {
int bwidth;
int mamount;
int snapdist;
int htile;
int vtile;
struct gap gap;
char *color[CWM_COLOR_NITEMS];
char *font;
@ -413,38 +410,36 @@ extern struct conf Conf;
void usage(void);
void client_applysizehints(struct client_ctx *);
void client_apply_sizehints(struct client_ctx *);
void client_close(struct client_ctx *);
void client_config(struct client_ctx *);
struct client_ctx *client_current(struct screen_ctx *);
void client_cycle(struct screen_ctx *, int);
void client_remove(struct client_ctx *);
void client_draw_border(struct client_ctx *);
struct client_ctx *client_find(Window);
long client_get_wm_state(struct client_ctx *);
void client_getsizehints(struct client_ctx *);
void client_get_sizehints(struct client_ctx *);
void client_hide(struct client_ctx *);
void client_htile(struct client_ctx *);
int client_inbound(struct client_ctx *, int, int);
struct client_ctx *client_init(Window, struct screen_ctx *);
void client_lower(struct client_ctx *);
void client_msg(struct client_ctx *, Atom, Time);
void client_move(struct client_ctx *);
void client_mtf(struct client_ctx *);
int client_inbound(struct client_ctx *, int, int);
struct client_ctx *client_init(Window, struct screen_ctx *, int);
struct client_ctx *client_next(struct client_ctx *);
struct client_ctx *client_prev(struct client_ctx *);
void client_ptr_inbound(struct client_ctx *, int);
void client_ptrsave(struct client_ctx *);
void client_ptrwarp(struct client_ctx *);
void client_ptr_save(struct client_ctx *);
void client_ptr_warp(struct client_ctx *);
void client_raise(struct client_ctx *);
void client_remove(struct client_ctx *);
void client_resize(struct client_ctx *, int);
void client_close(struct client_ctx *);
void client_set_wm_state(struct client_ctx *, long);
void client_setactive(struct client_ctx *);
void client_setname(struct client_ctx *);
void client_set_active(struct client_ctx *);
void client_set_name(struct client_ctx *);
void client_show(struct client_ctx *);
int client_snapcalc(int, int, int, int, int);
void client_toggle_freeze(struct client_ctx *);
void client_toggle_fullscreen(struct client_ctx *);
void client_toggle_hidden(struct client_ctx *);
void client_toggle_hmaximize(struct client_ctx *);
void client_toggle_fullscreen(struct client_ctx *);
void client_toggle_freeze(struct client_ctx *);
void client_toggle_maximize(struct client_ctx *);
void client_toggle_skip_pager(struct client_ctx *);
void client_toggle_skip_taskbar(struct client_ctx *);
@ -474,16 +469,16 @@ void group_update_names(struct screen_ctx *);
void search_match_client(struct menu_q *, struct menu_q *,
char *);
void search_match_cmd(struct menu_q *, struct menu_q *,
char *);
void search_match_exec(struct menu_q *, struct menu_q *,
char *);
void search_match_group(struct menu_q *, struct menu_q *,
char *);
void search_match_path(struct menu_q *, struct menu_q *,
char *);
void search_match_text(struct menu_q *, struct menu_q *,
char *);
void search_match_cmd(struct menu_q *, struct menu_q *,
char *);
void search_match_group(struct menu_q *, struct menu_q *,
char *);
void search_match_wm(struct menu_q *, struct menu_q *,
char *);
void search_print_client(struct menu *, int);
@ -493,19 +488,18 @@ void search_print_text(struct menu *, int);
void search_print_wm(struct menu *, int);
struct region_ctx *region_find(struct screen_ctx *, int, int);
struct screen_ctx *screen_find(Window);
struct geom screen_area(struct screen_ctx *, int, int,
enum apply_gap);
void screen_init(int);
void screen_update_geometry(struct screen_ctx *);
void screen_updatestackingorder(struct screen_ctx *);
void screen_assert_clients_within(struct screen_ctx *);
struct geom screen_area(struct screen_ctx *, int, int, int);
struct screen_ctx *screen_find(Window);
void screen_init(int);
void screen_prop_win_create(struct screen_ctx *, Window);
void screen_prop_win_destroy(struct screen_ctx *);
void screen_prop_win_draw(struct screen_ctx *,
const char *, ...)
__attribute__((__format__ (printf, 2, 3)))
__attribute__((__nonnull__ (2)));
void screen_update_geometry(struct screen_ctx *);
void screen_updatestackingorder(struct screen_ctx *);
void kbfunc_cwm_status(void *, struct cargs *);
void kbfunc_ptrmove(void *, struct cargs *);
@ -554,7 +548,6 @@ void menuq_clear(struct menu_q *);
int parse_config(const char *, struct conf *);
void conf_atoms(void);
void conf_autogroup(struct conf *, int, const char *,
const char *);
int conf_bind_key(struct conf *, const char *,
@ -577,12 +570,16 @@ void conf_group(struct screen_ctx *);
void xev_process(void);
int xu_getprop(Window, Atom, Atom, long, unsigned char **);
int xu_getstrprop(Window, Atom, char **);
void xu_ptr_getpos(Window, int *, int *);
void xu_ptr_setpos(Window, int, int);
int xu_get_prop(Window, Atom, Atom, long, unsigned char **);
int xu_get_strprop(Window, Atom, char **);
void xu_ptr_get(Window, int *, int *);
void xu_ptr_set(Window, int, int);
void xu_get_wm_state(Window, long *);
void xu_set_wm_state(Window, long);
void xu_send_clientmsg(Window, Atom, Time);
void xu_xorcolor(XftColor, XftColor, XftColor *);
void xu_atom_init(void);
void xu_ewmh_net_supported(struct screen_ctx *);
void xu_ewmh_net_supported_wm_check(struct screen_ctx *);
void xu_ewmh_net_desktop_geometry(struct screen_ctx *);
@ -591,14 +588,13 @@ void xu_ewmh_net_workarea(struct screen_ctx *);
void xu_ewmh_net_client_list(struct screen_ctx *);
void xu_ewmh_net_client_list_stacking(struct screen_ctx *);
void xu_ewmh_net_active_window(struct screen_ctx *, Window);
Window xu_ewmh_get_net_active_window(struct screen_ctx *);
void xu_ewmh_net_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 *);
void xu_ewmh_net_desktop_names(struct screen_ctx *);
void xu_ewmh_net_wm_desktop(struct client_ctx *);
int xu_ewmh_get_net_wm_desktop(struct client_ctx *, long *);
void xu_ewmh_set_net_wm_desktop(struct client_ctx *);
Atom *xu_ewmh_get_net_wm_state(struct client_ctx *, int *);
void xu_ewmh_handle_net_wm_state_msg(struct client_ctx *,
int, Atom , Atom);

373
client.c
View File

@ -31,34 +31,31 @@
#include "calmwm.h"
static struct client_ctx *client_next(struct client_ctx *);
static struct client_ctx *client_prev(struct client_ctx *);
static void client_placecalc(struct client_ctx *);
static void client_wm_protocols(struct client_ctx *);
static void client_class_hint(struct client_ctx *);
static void client_placement(struct client_ctx *);
static void client_mwm_hints(struct client_ctx *);
static void client_wm_protocols(struct client_ctx *);
struct client_ctx *
client_init(Window win, struct screen_ctx *sc, int active)
client_init(Window win, struct screen_ctx *sc)
{
struct client_ctx *cc;
XWindowAttributes wattr;
int mapped;
Window rwin, cwin;
int x, y, wx, wy;
unsigned int mask;
long state;
if (win == None)
return(NULL);
return NULL;
if (!XGetWindowAttributes(X_Dpy, win, &wattr))
return(NULL);
return NULL;
if (sc == NULL) {
if ((sc = screen_find(wattr.root)) == NULL)
return(NULL);
return NULL;
mapped = 1;
} else {
if (wattr.override_redirect || wattr.map_state != IsViewable)
return(NULL);
return NULL;
mapped = wattr.map_state != IsUnmapped;
}
@ -67,12 +64,15 @@ client_init(Window win, struct screen_ctx *sc, int active)
cc = xmalloc(sizeof(*cc));
cc->sc = sc;
cc->win = win;
cc->name = NULL;
cc->label = NULL;
cc->gc = NULL;
cc->res_class = NULL;
cc->res_name = NULL;
cc->flags = 0;
cc->stackingorder = 0;
cc->initial_state = 0;
memset(&cc->hint, 0, sizeof(cc->hint));
memset(&cc->ch, 0, sizeof(cc->ch));
TAILQ_INIT(&cc->nameq);
cc->geom.x = wattr.x;
@ -83,13 +83,13 @@ client_init(Window win, struct screen_ctx *sc, int active)
cc->obwidth = wattr.border_width;
cc->bwidth = Conf.bwidth;
client_setname(cc);
client_set_name(cc);
conf_client(cc);
XGetClassHint(X_Dpy, cc->win, &cc->ch);
client_wm_hints(cc);
client_class_hint(cc);
client_wm_protocols(cc);
client_getsizehints(cc);
client_get_sizehints(cc);
client_transient(cc);
client_mwm_hints(cc);
@ -101,18 +101,14 @@ client_init(Window win, struct screen_ctx *sc, int active)
cc->ptr.y = cc->geom.h / 2;
if (wattr.map_state != IsViewable) {
client_placecalc(cc);
client_placement(cc);
client_resize(cc, 0);
if ((cc->wmh) && (cc->wmh->flags & StateHint))
client_set_wm_state(cc, cc->wmh->initial_state);
} else {
if ((active == 0) && (XQueryPointer(X_Dpy, cc->win, &rwin,
&cwin, &x, &y, &wx, &wy, &mask)) && (cwin != None))
active = 1;
if (cc->initial_state)
xu_set_wm_state(cc->win, cc->initial_state);
}
XSelectInput(X_Dpy, cc->win, ColormapChangeMask | EnterWindowMask |
PropertyChangeMask | KeyReleaseMask);
XSelectInput(X_Dpy, cc->win,
EnterWindowMask | PropertyChangeMask | KeyReleaseMask);
XAddToSaveSet(X_Dpy, cc->win);
@ -125,7 +121,8 @@ client_init(Window win, struct screen_ctx *sc, int active)
xu_ewmh_net_client_list_stacking(sc);
xu_ewmh_restore_net_wm_state(cc);
if (client_get_wm_state(cc) == IconicState)
xu_get_wm_state(cc->win, &state);
if (state == IconicState)
client_hide(cc);
else
client_show(cc);
@ -148,10 +145,29 @@ out:
XSync(X_Dpy, False);
XUngrabServer(X_Dpy);
if (active)
client_setactive(cc);
return cc;
}
return(cc);
struct client_ctx *
client_current(struct screen_ctx *sc)
{
struct screen_ctx *_sc;
struct client_ctx *cc;
if (sc) {
TAILQ_FOREACH(cc, &sc->clientq, entry) {
if (cc->flags & CLIENT_ACTIVE)
return cc;
}
} else {
TAILQ_FOREACH(_sc, &Screenq, entry) {
TAILQ_FOREACH(cc, &_sc->clientq, entry) {
if (cc->flags & CLIENT_ACTIVE)
return cc;
}
}
}
return NULL;
}
struct client_ctx *
@ -163,10 +179,30 @@ client_find(Window win)
TAILQ_FOREACH(sc, &Screenq, entry) {
TAILQ_FOREACH(cc, &sc->clientq, entry) {
if (cc->win == win)
return(cc);
return cc;
}
}
return(NULL);
return NULL;
}
struct client_ctx *
client_next(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
struct client_ctx *newcc;
return(((newcc = TAILQ_NEXT(cc, entry)) != NULL) ?
newcc : TAILQ_FIRST(&sc->clientq));
}
struct client_ctx *
client_prev(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
struct client_ctx *newcc;
return(((newcc = TAILQ_PREV(cc, client_q, entry)) != NULL) ?
newcc : TAILQ_LAST(&sc->clientq, client_q));
}
void
@ -189,18 +225,15 @@ client_remove(struct client_ctx *cc)
free(wn);
}
if (cc->ch.res_class)
XFree(cc->ch.res_class);
if (cc->ch.res_name)
XFree(cc->ch.res_name);
if (cc->wmh)
XFree(cc->wmh);
free(cc->name);
free(cc->label);
free(cc->res_class);
free(cc->res_name);
free(cc);
}
void
client_setactive(struct client_ctx *cc)
client_set_active(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
struct client_ctx *oldcc;
@ -216,7 +249,7 @@ client_setactive(struct client_ctx *cc)
RevertToPointerRoot, CurrentTime);
}
if (cc->flags & CLIENT_WM_TAKE_FOCUS)
client_msg(cc, cwmh[WM_TAKE_FOCUS], Last_Event_Time);
xu_send_clientmsg(cc->win, cwmh[WM_TAKE_FOCUS], Last_Event_Time);
if ((oldcc = client_current(sc)) != NULL) {
oldcc->flags &= ~CLIENT_ACTIVE;
@ -234,28 +267,6 @@ client_setactive(struct client_ctx *cc)
xu_ewmh_net_active_window(sc, cc->win);
}
struct client_ctx *
client_current(struct screen_ctx *sc)
{
struct screen_ctx *_sc;
struct client_ctx *cc;
if (sc) {
TAILQ_FOREACH(cc, &sc->clientq, entry) {
if (cc->flags & CLIENT_ACTIVE)
return(cc);
}
} else {
TAILQ_FOREACH(_sc, &Screenq, entry) {
TAILQ_FOREACH(cc, &_sc->clientq, entry) {
if (cc->flags & CLIENT_ACTIVE)
return(cc);
}
}
}
return(NULL);
}
void
client_toggle_freeze(struct client_ctx *cc)
{
@ -316,7 +327,7 @@ client_toggle_fullscreen(struct client_ctx *cc)
area = screen_area(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_NOGAP);
cc->geom.y + cc->geom.h / 2, 0);
cc->bwidth = 0;
cc->geom = area;
@ -354,7 +365,7 @@ client_toggle_maximize(struct client_ctx *cc)
area = screen_area(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
cc->geom.y + cc->geom.h / 2, 1);
cc->geom.x = area.x;
cc->geom.y = area.y;
@ -388,7 +399,7 @@ client_toggle_vmaximize(struct client_ctx *cc)
area = screen_area(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
cc->geom.y + cc->geom.h / 2, 1);
cc->geom.y = area.y;
cc->geom.h = area.h - (cc->bwidth * 2);
@ -420,7 +431,7 @@ client_toggle_hmaximize(struct client_ctx *cc)
area = screen_area(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
cc->geom.y + cc->geom.h / 2, 1);
cc->geom.x = area.x;
cc->geom.w = area.w - (cc->bwidth * 2);
@ -491,7 +502,7 @@ void
client_ptr_inbound(struct client_ctx *cc, int getpos)
{
if (getpos)
xu_ptr_getpos(cc->win, &cc->ptr.x, &cc->ptr.y);
xu_ptr_get(cc->win, &cc->ptr.x, &cc->ptr.y);
if (cc->ptr.x < 0)
cc->ptr.x = 0;
@ -502,21 +513,21 @@ client_ptr_inbound(struct client_ctx *cc, int getpos)
else if (cc->ptr.y > cc->geom.h - 1)
cc->ptr.y = cc->geom.h - 1;
client_ptrwarp(cc);
client_ptr_warp(cc);
}
void
client_ptrwarp(struct client_ctx *cc)
client_ptr_warp(struct client_ctx *cc)
{
xu_ptr_setpos(cc->win, cc->ptr.x, cc->ptr.y);
xu_ptr_set(cc->win, cc->ptr.x, cc->ptr.y);
}
void
client_ptrsave(struct client_ctx *cc)
client_ptr_save(struct client_ctx *cc)
{
int x, y;
xu_ptr_getpos(cc->win, &x, &y);
xu_ptr_get(cc->win, &x, &y);
if (client_inbound(cc, x, y)) {
cc->ptr.x = x;
cc->ptr.y = y;
@ -536,7 +547,7 @@ client_hide(struct client_ctx *cc)
xu_ewmh_net_active_window(cc->sc, None);
}
cc->flags |= CLIENT_HIDDEN;
client_set_wm_state(cc, IconicState);
xu_set_wm_state(cc->win, IconicState);
}
void
@ -545,7 +556,7 @@ client_show(struct client_ctx *cc)
XMapRaised(X_Dpy, cc->win);
cc->flags &= ~CLIENT_HIDDEN;
client_set_wm_state(cc, NormalState);
xu_set_wm_state(cc->win, NormalState);
client_draw_border(cc);
}
@ -584,6 +595,23 @@ client_draw_border(struct client_ctx *cc)
XSetWindowBorder(X_Dpy, cc->win, pixel);
}
static void
client_class_hint(struct client_ctx *cc)
{
XClassHint ch;
if (XGetClassHint(X_Dpy, cc->win, &ch)) {
if (ch.res_class) {
cc->res_class = xstrdup(ch.res_class);
XFree(ch.res_class);
}
if (ch.res_name) {
cc->res_name = xstrdup(ch.res_name);
XFree(ch.res_name);
}
}
}
static void
client_wm_protocols(struct client_ctx *cc)
{
@ -604,149 +632,62 @@ client_wm_protocols(struct client_ctx *cc)
void
client_wm_hints(struct client_ctx *cc)
{
if ((cc->wmh = XGetWMHints(X_Dpy, cc->win)) == NULL)
return;
if ((cc->wmh->flags & InputHint) && (cc->wmh->input))
cc->flags |= CLIENT_INPUT;
if ((cc->wmh->flags & XUrgencyHint))
client_urgency(cc);
}
void
client_msg(struct client_ctx *cc, Atom proto, Time ts)
{
XClientMessageEvent cm;
(void)memset(&cm, 0, sizeof(cm));
cm.type = ClientMessage;
cm.window = cc->win;
cm.message_type = cwmh[WM_PROTOCOLS];
cm.format = 32;
cm.data.l[0] = proto;
cm.data.l[1] = ts;
XSendEvent(X_Dpy, cc->win, False, NoEventMask, (XEvent *)&cm);
XWMHints *wmh;
if ((wmh = XGetWMHints(X_Dpy, cc->win)) != NULL) {
if ((wmh->flags & InputHint) && (wmh->input))
cc->flags |= CLIENT_INPUT;
if ((wmh->flags & XUrgencyHint))
client_urgency(cc);
if ((wmh->flags & StateHint))
cc->initial_state = wmh->initial_state;
XFree(wmh);
}
}
void
client_close(struct client_ctx *cc)
{
if (cc->flags & CLIENT_WM_DELETE_WINDOW)
client_msg(cc, cwmh[WM_DELETE_WINDOW], CurrentTime);
xu_send_clientmsg(cc->win, cwmh[WM_DELETE_WINDOW], CurrentTime);
else
XKillClient(X_Dpy, cc->win);
}
void
client_setname(struct client_ctx *cc)
client_set_name(struct client_ctx *cc)
{
struct winname *wn;
char *newname;
struct winname *wn, *wnnxt;
int i = 0;
if (!xu_getstrprop(cc->win, ewmh[_NET_WM_NAME], &newname))
if (!xu_getstrprop(cc->win, XA_WM_NAME, &newname))
newname = xstrdup("");
free(cc->name);
if (!xu_get_strprop(cc->win, ewmh[_NET_WM_NAME], &cc->name))
if (!xu_get_strprop(cc->win, XA_WM_NAME, &cc->name))
cc->name = xstrdup("");
TAILQ_FOREACH(wn, &cc->nameq, entry) {
if (strcmp(wn->name, newname) == 0) {
/* Move to the last since we got a hit. */
TAILQ_FOREACH_SAFE(wn, &cc->nameq, entry, wnnxt) {
if (strcmp(wn->name, cc->name) == 0) {
TAILQ_REMOVE(&cc->nameq, wn, entry);
TAILQ_INSERT_TAIL(&cc->nameq, wn, entry);
goto match;
free(wn->name);
free(wn);
}
i++;
}
wn = xmalloc(sizeof(*wn));
wn->name = newname;
wn->name = xstrdup(cc->name);
TAILQ_INSERT_TAIL(&cc->nameq, wn, entry);
match:
cc->name = wn->name;
/* Do some garbage collection. */
TAILQ_FOREACH(wn, &cc->nameq, entry)
i++;
if (i > Conf.nameqlen) {
/* Garbage collection. */
if ((i + 1) > Conf.nameqlen) {
wn = TAILQ_FIRST(&cc->nameq);
TAILQ_REMOVE(&cc->nameq, wn, entry);
free(wn->name);
free(wn);
i--;
}
}
void
client_cycle(struct screen_ctx *sc, int flags)
{
struct client_ctx *newcc, *oldcc, *prevcc;
int again = 1;
if (TAILQ_EMPTY(&sc->clientq))
return;
prevcc = TAILQ_FIRST(&sc->clientq);
oldcc = client_current(sc);
if (oldcc == NULL)
oldcc = (flags & CWM_CYCLE_REVERSE) ?
TAILQ_LAST(&sc->clientq, client_q) :
TAILQ_FIRST(&sc->clientq);
newcc = oldcc;
while (again) {
again = 0;
newcc = (flags & CWM_CYCLE_REVERSE) ? client_prev(newcc) :
client_next(newcc);
/* Only cycle visible and non-ignored windows. */
if ((newcc->flags & (CLIENT_SKIP_CYCLE)) ||
((flags & CWM_CYCLE_INGROUP) &&
(newcc->gc != oldcc->gc)))
again = 1;
/* Is oldcc the only non-hidden window? */
if (newcc == oldcc) {
if (again)
return; /* No windows visible. */
break;
}
}
/* Reset when cycling mod is released. XXX I hate this hack */
sc->cycling = 1;
client_ptrsave(oldcc);
client_raise(prevcc);
client_raise(newcc);
if (!client_inbound(newcc, newcc->ptr.x, newcc->ptr.y)) {
newcc->ptr.x = newcc->geom.w / 2;
newcc->ptr.y = newcc->geom.h / 2;
}
client_ptrwarp(newcc);
}
static struct client_ctx *
client_next(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
struct client_ctx *newcc;
return(((newcc = TAILQ_NEXT(cc, entry)) != NULL) ?
newcc : TAILQ_FIRST(&sc->clientq));
}
static struct client_ctx *
client_prev(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
struct client_ctx *newcc;
return(((newcc = TAILQ_PREV(cc, client_q, entry)) != NULL) ?
newcc : TAILQ_LAST(&sc->clientq, client_q));
}
static void
client_placecalc(struct client_ctx *cc)
client_placement(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
@ -769,8 +710,8 @@ client_placecalc(struct client_ctx *cc)
struct geom area;
int xmouse, ymouse, xslack, yslack;
xu_ptr_getpos(sc->rootwin, &xmouse, &ymouse);
area = screen_area(sc, xmouse, ymouse, CWM_GAP);
xu_ptr_get(sc->rootwin, &xmouse, &ymouse);
area = screen_area(sc, xmouse, ymouse, 1);
xmouse = MAX(MAX(xmouse, area.x) - cc->geom.w / 2, area.x);
ymouse = MAX(MAX(ymouse, area.y) - cc->geom.h / 2, area.y);
@ -803,7 +744,7 @@ client_mtf(struct client_ctx *cc)
}
void
client_getsizehints(struct client_ctx *cc)
client_get_sizehints(struct client_ctx *cc)
{
long tmp;
XSizeHints size;
@ -851,7 +792,7 @@ client_getsizehints(struct client_ctx *cc)
}
void
client_applysizehints(struct client_ctx *cc)
client_apply_sizehints(struct client_ctx *cc)
{
Bool baseismin;
@ -902,7 +843,7 @@ client_mwm_hints(struct client_ctx *cc)
{
struct mwm_hints *mwmh;
if (xu_getprop(cc->win, cwmh[_MOTIF_WM_HINTS],
if (xu_get_prop(cc->win, cwmh[_MOTIF_WM_HINTS],
cwmh[_MOTIF_WM_HINTS], MWM_HINTS_ELEMENTS,
(unsigned char **)&mwmh) == MWM_HINTS_ELEMENTS) {
if (mwmh->flags & MWM_FLAGS_DECORATIONS &&
@ -952,15 +893,15 @@ client_snapcalc(int n0, int n1, int e0, int e1, int snapdist)
/* possible to snap in both directions */
if (s0 != 0 && s1 != 0)
if (abs(s0) < abs(s1))
return(s0);
return s0;
else
return(s1);
return s1;
else if (s0 != 0)
return(s0);
return s0;
else if (s1 != 0)
return(s1);
return s1;
else
return(0);
return 0;
}
void
@ -974,7 +915,7 @@ client_htile(struct client_ctx *cc)
i = n = 0;
area = screen_area(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
cc->geom.y + cc->geom.h / 2, 1);
TAILQ_FOREACH(ci, &sc->clientq, entry) {
if (ci->gc != cc->gc)
@ -999,9 +940,10 @@ client_htile(struct client_ctx *cc)
cc->geom.x = area.x;
cc->geom.y = area.y;
cc->geom.w = area.w - (cc->bwidth * 2);
cc->geom.h = (area.h - (cc->bwidth * 2)) / 2;
if (Conf.htile > 0)
cc->geom.h = ((area.h - (cc->bwidth * 2)) * Conf.htile) / 100;
client_resize(cc, 1);
client_ptrwarp(cc);
client_ptr_warp(cc);
mh = cc->geom.h + (cc->bwidth * 2);
x = area.x;
@ -1042,7 +984,7 @@ client_vtile(struct client_ctx *cc)
i = n = 0;
area = screen_area(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
cc->geom.y + cc->geom.h / 2, 1);
TAILQ_FOREACH(ci, &sc->clientq, entry) {
if (ci->gc != cc->gc)
@ -1066,10 +1008,11 @@ client_vtile(struct client_ctx *cc)
cc->flags &= ~CLIENT_VMAXIMIZED;
cc->geom.x = area.x;
cc->geom.y = area.y;
cc->geom.w = (area.w - (cc->bwidth * 2)) / 2;
if (Conf.vtile > 0)
cc->geom.w = ((area.w - (cc->bwidth * 2)) * Conf.vtile) / 100;
cc->geom.h = area.h - (cc->bwidth * 2);
client_resize(cc, 1);
client_ptrwarp(cc);
client_ptr_warp(cc);
mw = cc->geom.w + (cc->bwidth * 2);
y = area.y;
@ -1098,25 +1041,3 @@ client_vtile(struct client_ctx *cc)
client_resize(ci, 1);
}
}
long
client_get_wm_state(struct client_ctx *cc)
{
long *p, state = -1;
if (xu_getprop(cc->win, cwmh[WM_STATE], cwmh[WM_STATE], 2L,
(unsigned char **)&p) > 0) {
state = *p;
XFree(p);
}
return(state);
}
void
client_set_wm_state(struct client_ctx *cc, long state)
{
long data[] = { state, None };
XChangeProperty(X_Dpy, cc->win, cwmh[WM_STATE], cwmh[WM_STATE], 32,
PropModeReplace, (unsigned char *)data, 2);
}

74
conf.c
View File

@ -32,7 +32,7 @@
#include "calmwm.h"
static const char *conf_bind_getmask(const char *, unsigned int *);
static const char *conf_bind_mask(const char *, unsigned int *);
static void conf_unbind_key(struct conf *, struct bind_ctx *);
static void conf_unbind_mouse(struct conf *, struct bind_ctx *);
@ -281,6 +281,8 @@ conf_init(struct conf *c)
c->stickygroups = 0;
c->bwidth = 1;
c->mamount = 1;
c->htile = 50;
c->vtile = 50;
c->snapdist = 0;
c->ngroups = 0;
c->nameqlen = 5;
@ -517,7 +519,7 @@ conf_group(struct screen_ctx *sc)
}
static const char *
conf_bind_getmask(const char *name, unsigned int *mask)
conf_bind_mask(const char *name, unsigned int *mask)
{
char *dash;
const char *ch;
@ -525,13 +527,13 @@ conf_bind_getmask(const char *name, unsigned int *mask)
*mask = 0;
if ((dash = strchr(name, '-')) == NULL)
return(name);
return name;
for (i = 0; i < nitems(bind_mods); i++) {
if ((ch = strchr(name, bind_mods[i].ch)) != NULL && ch < dash)
*mask |= bind_mods[i].mask;
}
/* Skip past modifiers. */
return(dash + 1);
return (dash + 1);
}
int
@ -544,20 +546,20 @@ conf_bind_key(struct conf *c, const char *bind, const char *cmd)
if ((strcmp(bind, "all") == 0) && (cmd == NULL)) {
conf_unbind_key(c, NULL);
return(1);
return 1;
}
kb = xmalloc(sizeof(*kb));
key = conf_bind_getmask(bind, &kb->modmask);
key = conf_bind_mask(bind, &kb->modmask);
kb->press.keysym = XStringToKeysym(key);
if (kb->press.keysym == NoSymbol) {
warnx("unknown symbol: %s", key);
free(kb);
return(0);
return 0;
}
conf_unbind_key(c, kb);
if (cmd == NULL) {
free(kb);
return(1);
return 1;
}
cargs = xcalloc(1, sizeof(*cargs));
for (i = 0; i < nitems(name_to_func); i++) {
@ -575,7 +577,7 @@ conf_bind_key(struct conf *c, const char *bind, const char *cmd)
out:
kb->cargs = cargs;
TAILQ_INSERT_TAIL(&c->keybindq, kb, entry);
return(1);
return 1;
}
static void
@ -605,20 +607,20 @@ conf_bind_mouse(struct conf *c, const char *bind, const char *cmd)
if ((strcmp(bind, "all") == 0) && (cmd == NULL)) {
conf_unbind_mouse(c, NULL);
return(1);
return 1;
}
mb = xmalloc(sizeof(*mb));
button = conf_bind_getmask(bind, &mb->modmask);
button = conf_bind_mask(bind, &mb->modmask);
mb->press.button = strtonum(button, Button1, Button5, &errstr);
if (errstr) {
warnx("button number is %s: %s", errstr, button);
free(mb);
return(0);
return 0;
}
conf_unbind_mouse(c, mb);
if (cmd == NULL) {
free(mb);
return(1);
return 1;
}
cargs = xcalloc(1, sizeof(*cargs));
for (i = 0; i < nitems(name_to_func); i++) {
@ -636,7 +638,7 @@ conf_bind_mouse(struct conf *c, const char *bind, const char *cmd)
out:
mb->cargs = cargs;
TAILQ_INSERT_TAIL(&c->mousebindq, mb, entry);
return(1);
return 1;
}
static void
@ -696,47 +698,3 @@ conf_grab_mouse(Window win)
}
}
}
static char *cwmhints[] = {
"WM_STATE",
"WM_DELETE_WINDOW",
"WM_TAKE_FOCUS",
"WM_PROTOCOLS",
"_MOTIF_WM_HINTS",
"UTF8_STRING",
"WM_CHANGE_STATE",
};
static char *ewmhints[] = {
"_NET_SUPPORTED",
"_NET_SUPPORTING_WM_CHECK",
"_NET_ACTIVE_WINDOW",
"_NET_CLIENT_LIST",
"_NET_CLIENT_LIST_STACKING",
"_NET_NUMBER_OF_DESKTOPS",
"_NET_CURRENT_DESKTOP",
"_NET_DESKTOP_VIEWPORT",
"_NET_DESKTOP_GEOMETRY",
"_NET_VIRTUAL_ROOTS",
"_NET_SHOWING_DESKTOP",
"_NET_DESKTOP_NAMES",
"_NET_WORKAREA",
"_NET_WM_NAME",
"_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_HIDDEN",
"_NET_WM_STATE_FULLSCREEN",
"_NET_WM_STATE_DEMANDS_ATTENTION",
"_NET_WM_STATE_SKIP_PAGER",
"_NET_WM_STATE_SKIP_TASKBAR",
"_CWM_WM_STATE_FREEZE",
};
void
conf_atoms(void)
{
XInternAtoms(X_Dpy, cwmhints, nitems(cwmhints), False, cwmh);
XInternAtoms(X_Dpy, ewmhints, nitems(ewmhints), False, ewmh);
}

49
cwmrc.5
View File

@ -37,10 +37,8 @@ Arguments containing whitespace should be surrounded by double quotes
.Pq \&" .
.Pp
The following options are accepted:
.Pp
.Bl -tag -width Ds -compact
.It Ic autogroup Ar group windowclass
.It Ic autogroup Ar group windowname,windowclass
.Bl -tag -width Ds
.It Ic autogroup Ar group Oo Ar windowname , Oc Ns Ar windowclass
Automatically add new windows to
.Ar group
if their class property matches
@ -62,7 +60,6 @@ used to override
The name and class values, respectively, for existing windows
are both set in the WM_CLASS property and may be obtained using
.Xr xprop 1 .
.Pp
.It Ic bind-key Ar key function
Bind or rebind key
.Ar key
@ -93,7 +90,6 @@ The
may either be one from the
.Sx BIND FUNCTION LIST
(see below) or the command line that is to be executed.
.Pp
.It Ic bind-mouse Ar button function
Bind or rebind button
.Ar button
@ -128,38 +124,27 @@ The
may be taken from the
.Sx BIND FUNCTION LIST
(see below) or the command line that is to be executed.
.Pp
.It Ic borderwidth Ar pixels
Set the window border width to
.Ar pixels .
.Pp
.It Ic color activeborder Ar color
Set the color of the active border.
.Pp
.It Ic color font Ar color
Set menu font color.
.Pp
.It Ic color selfont Ar color
Set font color for selected menu item.
.Pp
.It Ic color groupborder Ar color
Set the color of the border while grouping a window.
.Pp
.It Ic color inactiveborder Ar color
Set the color of the inactive border.
.Pp
.It Ic color menubg Ar color
Set menu background color.
.Pp
.It Ic color menufg Ar color
Set menu foreground color.
.Pp
.It Ic color urgencyborder Ar color
Set the color of the border of a window indicating urgency.
.Pp
.It Ic color ungroupborder Ar color
Set the color of the border while ungrouping a window.
.Pp
.It Ic command Ar name path
Every
.Ar name
@ -183,13 +168,11 @@ The defaults are
and
.Xr xlock 1 ,
respectively.
.Pp
.It Ic fontname Ar font
Change the default
.Ar font
for
.Xr Xft 3 .
.Pp
.It Ic gap Ar top bottom left right
Define a
.Dq gap
@ -200,28 +183,30 @@ This
can be used for applications such as
.Xr xclock 1 ,
where the user may wish to remain visible.
.Pp
.It Ic htile Ar percent
Set the percentage of screen the master window should occupy
after calling
.Ic window-htile .
If set to 0, the horizontal size of the master window will
remain unchanged.
The default is 50.
.It Ic ignore Ar windowname
Ignore, and do not warp to, windows with the name
.Ar windowname
when drawing borders and cycling through windows.
.Pp
.It Ic moveamount Ar pixels
Set a default size for the keyboard movement bindings,
in pixels.
The default is 1.
.Pp
.It Ic snapdist Ar pixels
Minimum distance to snap-to adjacent edge, in pixels.
The default is 0.
.Pp
.It Ic sticky Ic yes Ns \&| Ns Ic no
Toggle sticky group mode.
The default behavior for new windows is to not assign any group.
By enabling sticky group mode,
.Xr cwm 1
will assign new windows to the currently selected group.
.Pp
.It Ic unbind-key Ar key
Unbind function bound to
.Ar key .
@ -230,7 +215,6 @@ A special
keyword
.Dq all
can be used to unbind all keys.
.Pp
.It Ic unbind-mouse Ar button
Unbind function bound to
.Ar button .
@ -239,6 +223,13 @@ A special
keyword
.Dq all
can be used to unbind all buttons.
.It Ic vtile Ar percent
Set the percentage of screen the master window should occupy
after calling
.Ic window-vtile .
If set to 0, the vertical size of the master window will
remain unchanged.
The default is 50.
.It Ic wm Ar name path
Every
.Ar name
@ -326,11 +317,15 @@ Vertically maximize current window (gap + border honored).
Horizontally maximize current window (gap + border honored).
.It window-htile
Current window is placed at the top of the screen, maximized
horizontally and resized to half of the vertical screen space.
horizontally and resized to
.Ar htile
(default half) of the vertical screen space.
Other windows in its group share remaining screen space.
.It window-vtile
Current window is placed on the left of the screen, maximized vertically
and resized to half of the horizontal screen space.
and resized to
.Ar vtile
(default half) of the horizontal screen space.
Other windows in its group share remaining screen space.
.It window-move
Move current window.

46
group.c
View File

@ -35,7 +35,7 @@
static struct group_ctx *group_next(struct group_ctx *);
static struct group_ctx *group_prev(struct group_ctx *);
static void group_restack(struct group_ctx *);
static void group_setactive(struct group_ctx *);
static void group_set_active(struct group_ctx *);
void
group_assign(struct group_ctx *gc, struct client_ctx *cc)
@ -45,7 +45,7 @@ group_assign(struct group_ctx *gc, struct client_ctx *cc)
cc->gc = gc;
xu_ewmh_net_wm_desktop(cc);
xu_ewmh_set_net_wm_desktop(cc);
}
void
@ -79,7 +79,7 @@ group_show(struct group_ctx *gc)
client_show(cc);
}
group_restack(gc);
group_setactive(gc);
group_set_active(gc);
}
static void
@ -134,11 +134,11 @@ group_init(struct screen_ctx *sc, int num, const char *name)
TAILQ_INSERT_TAIL(&sc->groupq, gc, entry);
if (num == 1)
group_setactive(gc);
group_set_active(gc);
}
void
group_setactive(struct group_ctx *gc)
group_set_active(struct group_ctx *gc)
{
struct screen_ctx *sc = gc->sc;
@ -190,9 +190,9 @@ group_holds_only_sticky(struct group_ctx *gc)
if (cc->gc != gc)
continue;
if (!(cc->flags & CLIENT_STICKY))
return(0);
return 0;
}
return(1);
return 1;
}
int
@ -205,9 +205,9 @@ group_holds_only_hidden(struct group_ctx *gc)
if (cc->gc != gc)
continue;
if (!(cc->flags & (CLIENT_HIDDEN | CLIENT_STICKY)))
return(0);
return 0;
}
return(1);
return 1;
}
void
@ -297,7 +297,7 @@ group_cycle(struct screen_ctx *sc, int flags)
if (group_holds_only_hidden(showgroup))
group_show(showgroup);
else
group_setactive(showgroup);
group_set_active(showgroup);
}
static struct group_ctx *
@ -326,23 +326,21 @@ group_restore(struct client_ctx *cc)
struct screen_ctx *sc = cc->sc;
struct group_ctx *gc;
int num;
long *grpnum;
long grpnum;
if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP], XA_CARDINAL, 1L,
(unsigned char **)&grpnum) <= 0)
return(0);
if (!xu_ewmh_get_net_wm_desktop(cc, &grpnum))
return 0;
num = (*grpnum == -1) ? 0 : *grpnum;
num = (grpnum == -1) ? 0 : grpnum;
num = MIN(num, (Conf.ngroups - 1));
XFree(grpnum);
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == num) {
group_assign(gc, cc);
return(1);
return 1;
}
}
return(0);
return 0;
}
int
@ -353,13 +351,13 @@ group_autogroup(struct client_ctx *cc)
struct group_ctx *gc;
int num = -1, both_match = 0;
if (cc->ch.res_class == NULL || cc->ch.res_name == NULL)
return(0);
if (cc->res_class == NULL || cc->res_name == NULL)
return 0;
TAILQ_FOREACH(ag, &Conf.autogroupq, entry) {
if (strcmp(ag->class, cc->ch.res_class) == 0) {
if (strcmp(ag->class, cc->res_class) == 0) {
if ((ag->name != NULL) &&
(strcmp(ag->name, cc->ch.res_name) == 0)) {
(strcmp(ag->name, cc->res_name) == 0)) {
num = ag->num;
both_match = 1;
} else if (ag->name == NULL && !both_match)
@ -370,8 +368,8 @@ group_autogroup(struct client_ctx *cc)
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == num) {
group_assign(gc, cc);
return(1);
return 1;
}
}
return(0);
return 0;
}

View File

@ -62,7 +62,7 @@ kbfunc_amount(int flags, int amt, int *mx, int *my)
if (flags & CWM_BIGAMOUNT)
amt *= CWM_FACTOR;
switch (flags & DIRECTIONMASK) {
switch (flags & (CWM_UP | CWM_DOWN | CWM_LEFT | CWM_RIGHT)) {
case CWM_UP:
*my -= amt;
break;
@ -87,8 +87,8 @@ kbfunc_ptrmove(void *ctx, struct cargs *cargs)
kbfunc_amount(cargs->flag, Conf.mamount, &mx, &my);
xu_ptr_getpos(sc->rootwin, &x, &y);
xu_ptr_setpos(sc->rootwin, x + mx, y + my);
xu_ptr_get(sc->rootwin, &x, &y);
xu_ptr_set(sc->rootwin, x + mx, y + my);
}
void
@ -135,7 +135,7 @@ kbfunc_client_move_kb(void *ctx, struct cargs *cargs)
area = screen_area(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
cc->geom.y + cc->geom.h / 2, 1);
cc->geom.x += client_snapcalc(cc->geom.x,
cc->geom.x + cc->geom.w + (cc->bwidth * 2),
area.x, area.x + area.w, sc->snapdist);
@ -186,7 +186,7 @@ kbfunc_client_move_mb(void *ctx, struct cargs *cargs)
area = screen_area(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
cc->geom.y + cc->geom.h / 2, 1);
cc->geom.x += client_snapcalc(cc->geom.x,
cc->geom.x + cc->geom.w + (cc->bwidth * 2),
area.x, area.x + area.w, sc->snapdist);
@ -250,9 +250,9 @@ kbfunc_client_resize_mb(void *ctx, struct cargs *cargs)
return;
client_raise(cc);
client_ptrsave(cc);
client_ptr_save(cc);
xu_ptr_setpos(cc->win, cc->geom.w, cc->geom.h);
xu_ptr_set(cc->win, cc->geom.w, cc->geom.h);
if (XGrabPointer(X_Dpy, cc->win, False, MOUSEMASK,
GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_RESIZE],
@ -272,7 +272,7 @@ kbfunc_client_resize_mb(void *ctx, struct cargs *cargs)
cc->geom.w = ev.xmotion.x;
cc->geom.h = ev.xmotion.y;
client_applysizehints(cc);
client_apply_sizehints(cc);
client_resize(cc, 1);
screen_prop_win_draw(sc,
"%4d x %-4d", cc->dim.w, cc->dim.h);
@ -301,7 +301,7 @@ kbfunc_client_snap(void *ctx, struct cargs *cargs)
area = screen_area(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
cc->geom.y + cc->geom.h / 2, 1);
flags = cargs->flag;
while (flags) {
@ -337,7 +337,7 @@ kbfunc_client_close(void *ctx, struct cargs *cargs)
void
kbfunc_client_lower(void *ctx, struct cargs *cargs)
{
client_ptrsave(ctx);
client_ptr_save(ctx);
client_lower(ctx);
}
@ -405,13 +405,55 @@ void
kbfunc_client_cycle(void *ctx, struct cargs *cargs)
{
struct screen_ctx *sc = ctx;
struct client_ctx *newcc, *oldcc, *prevcc;
int again = 1, flags = cargs->flag;
/* For X apps that ignore/steal events. */
if (cargs->xev == CWM_XEV_KEY)
XGrabKeyboard(X_Dpy, sc->rootwin, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
client_cycle(sc, cargs->flag);
if (TAILQ_EMPTY(&sc->clientq))
return;
prevcc = TAILQ_FIRST(&sc->clientq);
oldcc = client_current(sc);
if (oldcc == NULL)
oldcc = (flags & CWM_CYCLE_REVERSE) ?
TAILQ_LAST(&sc->clientq, client_q) :
TAILQ_FIRST(&sc->clientq);
newcc = oldcc;
while (again) {
again = 0;
newcc = (flags & CWM_CYCLE_REVERSE) ? client_prev(newcc) :
client_next(newcc);
/* Only cycle visible and non-ignored windows. */
if ((newcc->flags & (CLIENT_SKIP_CYCLE)) ||
((flags & CWM_CYCLE_INGROUP) &&
(newcc->gc != oldcc->gc)))
again = 1;
/* Is oldcc the only non-hidden window? */
if (newcc == oldcc) {
if (again)
return; /* No windows visible. */
break;
}
}
/* Reset when cycling mod is released. XXX I hate this hack */
sc->cycling = 1;
client_ptr_save(oldcc);
client_raise(prevcc);
client_raise(newcc);
if (!client_inbound(newcc, newcc->ptr.x, newcc->ptr.y)) {
newcc->ptr.x = newcc->geom.w / 2;
newcc->ptr.y = newcc->geom.h / 2;
}
client_ptr_warp(newcc);
}
void
@ -470,20 +512,15 @@ kbfunc_menu_client(void *ctx, struct cargs *cargs)
struct client_ctx *cc, *old_cc;
struct menu *mi;
struct menu_q menuq;
int all = (cargs->flag & CWM_MENU_WINDOW_ALL);
int mflags = 0;
if (cargs->xev == CWM_XEV_BTN)
mflags |= CWM_MENU_LIST;
old_cc = client_current(sc);
TAILQ_INIT(&menuq);
TAILQ_FOREACH(cc, &sc->clientq, entry) {
if (!all) {
if (cc->flags & CLIENT_HIDDEN)
menuq_add(&menuq, cc, NULL);
} else
if ((cargs->flag & CWM_MENU_WINDOW_ALL) ||
(cc->flags & CLIENT_HIDDEN))
menuq_add(&menuq, cc, NULL);
}
@ -491,9 +528,9 @@ kbfunc_menu_client(void *ctx, struct cargs *cargs)
search_match_client, search_print_client)) != NULL) {
cc = (struct client_ctx *)mi->ctx;
client_show(cc);
if (old_cc)
client_ptrsave(old_cc);
client_ptrwarp(cc);
if ((old_cc = client_current(sc)) != NULL)
client_ptr_save(old_cc);
client_ptr_warp(cc);
}
menuq_clear(&menuq);

36
menu.c
View File

@ -94,7 +94,7 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt,
TAILQ_INIT(&resultq);
xu_ptr_getpos(sc->rootwin, &xsave, &ysave);
xu_ptr_get(sc->rootwin, &xsave, &ysave);
(void)memset(&mc, 0, sizeof(mc));
mc.sc = sc;
@ -129,7 +129,7 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt,
CurrentTime) != GrabSuccess) {
XftDrawDestroy(mc.xftdraw);
XDestroyWindow(X_Dpy, mc.win);
return(NULL);
return NULL;
}
XGetInputFocus(X_Dpy, &focuswin, &focusrevert);
@ -178,14 +178,14 @@ out:
XSetInputFocus(X_Dpy, focuswin, focusrevert, CurrentTime);
/* restore if user didn't move */
xu_ptr_getpos(sc->rootwin, &xcur, &ycur);
xu_ptr_get(sc->rootwin, &xcur, &ycur);
if (xcur == mc.geom.x && ycur == mc.geom.y)
xu_ptr_setpos(sc->rootwin, xsave, ysave);
xu_ptr_set(sc->rootwin, xsave, ysave);
XUngrabPointer(X_Dpy, CurrentTime);
XUngrabKeyboard(X_Dpy, CurrentTime);
return(mi);
return mi;
}
static struct menu *
@ -213,7 +213,7 @@ menu_complete_path(struct menu_ctx *mc)
menuq_clear(&menuq);
return(mr);
return mr;
}
static struct menu *
@ -228,7 +228,7 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq,
wchar_t wc;
if (menu_keycode(&e->xkey, &ctl, chr) < 0)
return(NULL);
return NULL;
switch (ctl) {
case CTL_ERASEONE:
@ -269,7 +269,7 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq,
mi->dummy = 1;
}
mi->abort = 0;
return(mi);
return mi;
case CTL_WIPE:
mc->searchstr[0] = '\0';
mc->changed = 1;
@ -284,7 +284,7 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq,
if ((mc->flags & CWM_MENU_FILE) &&
(strncmp(mc->searchstr, mi->text,
strlen(mi->text))) == 0)
return(menu_complete_path(mc));
return menu_complete_path(mc);
/*
* Put common prefix of the results into searchstr
@ -309,7 +309,7 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq,
mi->text[0] = '\0';
mi->dummy = 1;
mi->abort = 1;
return(mi);
return mi;
default:
break;
}
@ -327,7 +327,7 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq,
mc->listing = 0;
}
return(NULL);
return NULL;
}
static void
@ -368,7 +368,7 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq)
mc->num++;
}
area = screen_area(sc, mc->geom.x, mc->geom.y, CWM_GAP);
area = screen_area(sc, mc->geom.x, mc->geom.y, 1);
area.w += area.x - Conf.bwidth * 2;
area.h += area.y - Conf.bwidth * 2;
@ -390,7 +390,7 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq)
}
if (mc->geom.x != xsave || mc->geom.y != ysave)
xu_ptr_setpos(sc->rootwin, mc->geom.x, mc->geom.y);
xu_ptr_set(sc->rootwin, mc->geom.x, mc->geom.y);
XClearWindow(X_Dpy, mc->win);
XMoveResizeWindow(X_Dpy, mc->win, mc->geom.x, mc->geom.y,
@ -478,7 +478,7 @@ menu_handle_release(struct menu_ctx *mc, struct menu_q *resultq, int x, int y)
mi->text[0] = '\0';
mi->dummy = 1;
}
return(mi);
return mi;
}
static int
@ -498,7 +498,7 @@ menu_calc_entry(struct menu_ctx *mc, int x, int y)
if (entry == 0)
entry = -1;
return(entry);
return entry;
}
static int
@ -581,12 +581,12 @@ menu_keycode(XKeyEvent *ev, enum ctltype *ctl, char *chr)
}
if (*ctl != CTL_NONE)
return(0);
return 0;
if (XLookupString(ev, chr, 32, &ks, NULL) < 0)
return(-1);
return -1;
return(0);
return 0;
}
void

18
parse.y
View File

@ -73,7 +73,7 @@ typedef struct {
%token BINDKEY UNBINDKEY BINDMOUSE UNBINDMOUSE
%token FONTNAME STICKY GAP
%token AUTOGROUP COMMAND IGNORE WM
%token YES NO BORDERWIDTH MOVEAMOUNT
%token YES NO BORDERWIDTH MOVEAMOUNT HTILE VTILE
%token COLOR SNAPDIST
%token ACTIVEBORDER INACTIVEBORDER URGENCYBORDER
%token GROUPBORDER UNGROUPBORDER
@ -124,6 +124,20 @@ main : FONTNAME STRING {
}
conf->bwidth = $2;
}
| HTILE NUMBER {
if ($2 < 0 || $2 > 99) {
yyerror("invalid htile percent");
YYERROR;
}
conf->htile = $2;
}
| VTILE NUMBER {
if ($2 < 0 || $2 > 99) {
yyerror("invalid vtile percent");
YYERROR;
}
conf->vtile = $2;
}
| MOVEAMOUNT NUMBER {
if ($2 < 0 || $2 > INT_MAX) {
yyerror("invalid movemount");
@ -318,6 +332,7 @@ lookup(char *s)
{ "fontname", FONTNAME},
{ "gap", GAP},
{ "groupborder", GROUPBORDER},
{ "htile", HTILE},
{ "ignore", IGNORE},
{ "inactiveborder", INACTIVEBORDER},
{ "menubg", MENUBG},
@ -331,6 +346,7 @@ lookup(char *s)
{ "unbind-mouse", UNBINDMOUSE},
{ "ungroupborder", UNGROUPBORDER},
{ "urgencyborder", URGENCYBORDER},
{ "vtile", VTILE},
{ "wm", WM},
{ "yes", YES}
};

View File

@ -33,14 +33,13 @@
#include "calmwm.h"
static struct geom screen_apply_gap(struct screen_ctx *, struct geom);
static void screen_scan(struct screen_ctx *);
void
screen_init(int which)
{
struct screen_ctx *sc;
Window *wins, w0, w1, active = None;
XSetWindowAttributes rootattr;
unsigned int nwins, w;
XSetWindowAttributes attr;
sc = xmalloc(sizeof(*sc));
@ -67,33 +66,46 @@ screen_init(int which)
xu_ewmh_net_number_of_desktops(sc);
xu_ewmh_net_showing_desktop(sc);
xu_ewmh_net_virtual_roots(sc);
active = xu_ewmh_get_net_active_window(sc);
rootattr.cursor = Conf.cursor[CF_NORMAL];
rootattr.event_mask = SubstructureRedirectMask |
SubstructureNotifyMask | PropertyChangeMask | EnterWindowMask |
LeaveWindowMask | ColormapChangeMask | BUTTONMASK;
XChangeWindowAttributes(X_Dpy, sc->rootwin,
(CWEventMask | CWCursor), &rootattr);
/* Deal with existing clients. */
if (XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins)) {
for (w = 0; w < nwins; w++)
(void)client_init(wins[w], sc, (active == wins[w]));
XFree(wins);
}
screen_updatestackingorder(sc);
attr.cursor = Conf.cursor[CF_NORMAL];
attr.event_mask = SubstructureRedirectMask | SubstructureNotifyMask |
EnterWindowMask | PropertyChangeMask | ButtonPressMask;
XChangeWindowAttributes(X_Dpy, sc->rootwin, (CWEventMask | CWCursor), &attr);
if (Conf.xrandr)
XRRSelectInput(X_Dpy, sc->rootwin, RRScreenChangeNotifyMask);
screen_scan(sc);
screen_updatestackingorder(sc);
TAILQ_INSERT_TAIL(&Screenq, sc, entry);
XSync(X_Dpy, False);
}
static void
screen_scan(struct screen_ctx *sc)
{
struct client_ctx *cc, *active = NULL;
Window *wins, w0, w1, rwin, cwin;
unsigned int nwins, i, mask;
int rx, ry, wx, wy;
XQueryPointer(X_Dpy, sc->rootwin, &rwin, &cwin,
&rx, &ry, &wx, &wy, &mask);
if (XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins)) {
for (i = 0; i < nwins; i++) {
if ((cc = client_init(wins[i], sc)) != NULL)
if (cc->win == cwin)
active = cc;
}
XFree(wins);
}
if (active)
client_set_active(active);
}
struct screen_ctx *
screen_find(Window win)
{
@ -101,10 +113,10 @@ screen_find(Window win)
TAILQ_FOREACH(sc, &Screenq, entry) {
if (sc->rootwin == win)
return(sc);
return sc;
}
warnx("%s: failure win 0x%lx", __func__, win);
return(NULL);
return NULL;
}
void
@ -138,11 +150,11 @@ region_find(struct screen_ctx *sc, int x, int y)
break;
}
}
return(rc);
return rc;
}
struct geom
screen_area(struct screen_ctx *sc, int x, int y, enum apply_gap apply_gap)
screen_area(struct screen_ctx *sc, int x, int y, int apply_gap)
{
struct region_ctx *rc;
struct geom area = sc->view;
@ -156,7 +168,7 @@ screen_area(struct screen_ctx *sc, int x, int y, enum apply_gap apply_gap)
}
if (apply_gap)
area = screen_apply_gap(sc, area);
return(area);
return area;
}
void
@ -226,7 +238,7 @@ screen_apply_gap(struct screen_ctx *sc, struct geom geom)
geom.w -= (sc->gap.left + sc->gap.right);
geom.h -= (sc->gap.top + sc->gap.bottom);
return(geom);
return geom;
}
/* Bring back clients which are beyond the screen. */

View File

@ -46,13 +46,13 @@ match_substr(char *sub, char *str, int zeroidx)
unsigned int n, flen;
if (sub == NULL || str == NULL)
return(0);
return 0;
len = strlen(str);
sublen = strlen(sub);
if (sublen > len)
return(0);
return 0;
if (zeroidx)
flen = 0;
@ -61,9 +61,9 @@ match_substr(char *sub, char *str, int zeroidx)
for (n = 0; n <= flen; n++)
if (strncasecmp(sub, str + n, sublen) == 0)
return(1);
return 1;
return(0);
return 0;
}
void
@ -94,7 +94,7 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
}
/* Match on window resource class. */
if ((tier < 0) && match_substr(search, cc->ch.res_class, 0))
if ((tier < 0) && match_substr(search, cc->res_class, 0))
tier = 2;
if (tier < 0)

8
util.c
View File

@ -53,7 +53,7 @@ u_exec(char *argstr)
{
#define MAXARGLEN 20
char *args[MAXARGLEN], **ap = args;
char **end = &args[MAXARGLEN - 1], *tmp;
char **end = &args[MAXARGLEN - 2], *tmp;
char *s = argstr;
while (ap < end && (*ap = strsep(&argstr, " \t")) != NULL) {
@ -92,12 +92,12 @@ u_argv(char * const *argv)
char *p;
if (argv == 0)
return(NULL);
return NULL;
for (i = 0; argv[i]; i++)
siz += strlen(argv[i]) + 1;
if (siz == 0)
return(NULL);
return NULL;
p = xmalloc(siz);
strlcpy(p, argv[0], siz);
@ -105,7 +105,7 @@ u_argv(char * const *argv)
strlcat(p, " ", siz);
strlcat(p, argv[i], siz);
}
return(p);
return p;
}
static void

View File

@ -84,13 +84,13 @@ xev_handle_maprequest(XEvent *ee)
return;
if ((old_cc = client_current(sc)) != NULL)
client_ptrsave(old_cc);
client_ptr_save(old_cc);
if ((cc = client_find(e->window)) == NULL)
cc = client_init(e->window, NULL, 0);
cc = client_init(e->window, NULL);
if ((cc != NULL) && (!(cc->flags & CLIENT_IGNORE)))
client_ptrwarp(cc);
client_ptr_warp(cc);
}
static void
@ -103,7 +103,7 @@ xev_handle_unmapnotify(XEvent *ee)
if ((cc = client_find(e->window)) != NULL) {
if (e->send_event) {
client_set_wm_state(cc, WithdrawnState);
xu_set_wm_state(cc->win, WithdrawnState);
} else {
if (!(cc->flags & CLIENT_HIDDEN))
client_remove(cc);
@ -191,10 +191,10 @@ xev_handle_propertynotify(XEvent *ee)
if ((cc = client_find(e->window)) != NULL) {
switch (e->atom) {
case XA_WM_NORMAL_HINTS:
client_getsizehints(cc);
client_get_sizehints(cc);
break;
case XA_WM_NAME:
client_setname(cc);
client_set_name(cc);
break;
case XA_WM_HINTS:
client_wm_hints(cc);
@ -208,7 +208,7 @@ xev_handle_propertynotify(XEvent *ee)
break;
default:
if (e->atom == ewmh[_NET_WM_NAME])
client_setname(cc);
client_set_name(cc);
break;
}
} else {
@ -230,7 +230,7 @@ xev_handle_enternotify(XEvent *ee)
Last_Event_Time = e->time;
if ((cc = client_find(e->window)) != NULL)
client_setactive(cc);
client_set_active(cc);
}
static void
@ -399,9 +399,9 @@ xev_handle_clientmessage(XEvent *ee)
} else if (e->message_type == ewmh[_NET_ACTIVE_WINDOW]) {
if ((cc = client_find(e->window)) != NULL) {
if ((old_cc = client_current(NULL)) != NULL)
client_ptrsave(old_cc);
client_ptr_save(old_cc);
client_show(cc);
client_ptrwarp(cc);
client_ptr_warp(cc);
}
} else if (e->message_type == ewmh[_NET_WM_DESKTOP]) {
if ((cc = client_find(e->window)) != NULL) {

View File

@ -43,7 +43,7 @@ xmalloc(size_t siz)
if ((p = malloc(siz)) == NULL)
err(1, "malloc");
return(p);
return p;
}
void *
@ -58,7 +58,7 @@ xcalloc(size_t no, size_t siz)
if ((p = calloc(no, siz)) == NULL)
err(1, "calloc");
return(p);
return p;
}
void *
@ -70,7 +70,7 @@ xreallocarray(void *ptr, size_t nmemb, size_t size)
if (p == NULL)
errx(1, "xreallocarray: out of memory (new_size %zu bytes)",
nmemb * size);
return(p);
return p;
}
char *
@ -81,7 +81,7 @@ xstrdup(const char *str)
if ((p = strdup(str)) == NULL)
err(1, "strdup");
return(p);
return p;
}
int
@ -94,7 +94,7 @@ xasprintf(char **ret, const char *fmt, ...)
i = xvasprintf(ret, fmt, ap);
va_end(ap);
return(i);
return i;
}
int
@ -106,5 +106,5 @@ xvasprintf(char **ret, const char *fmt, va_list ap)
if (i == -1)
err(1, "vasprintf");
return(i);
return i;
}

172
xutil.c
View File

@ -32,7 +32,7 @@
#include "calmwm.h"
void
xu_ptr_getpos(Window win, int *x, int *y)
xu_ptr_get(Window win, int *x, int *y)
{
Window w0, w1;
int tmp0, tmp1;
@ -42,13 +42,13 @@ xu_ptr_getpos(Window win, int *x, int *y)
}
void
xu_ptr_setpos(Window win, int x, int y)
xu_ptr_set(Window win, int x, int y)
{
XWarpPointer(X_Dpy, None, win, 0, 0, 0, 0, x, y);
}
int
xu_getprop(Window win, Atom atm, Atom type, long len, unsigned char **p)
xu_get_prop(Window win, Atom atm, Atom type, long len, unsigned char **p)
{
Atom realtype;
unsigned long n, extra;
@ -56,16 +56,16 @@ xu_getprop(Window win, Atom atm, Atom type, long len, unsigned char **p)
if (XGetWindowProperty(X_Dpy, win, atm, 0L, len, False, type,
&realtype, &format, &n, &extra, p) != Success || *p == NULL)
return(-1);
return -1;
if (n == 0)
XFree(*p);
return(n);
return n;
}
int
xu_getstrprop(Window win, Atom atm, char **text) {
xu_get_strprop(Window win, Atom atm, char **text) {
XTextProperty prop;
char **list;
int nitems = 0;
@ -73,8 +73,10 @@ xu_getstrprop(Window win, Atom atm, char **text) {
*text = NULL;
XGetTextProperty(X_Dpy, win, &prop, atm);
if (!prop.nitems)
return(0);
if (!prop.nitems) {
XFree(prop.value);
return 0;
}
if (Xutf8TextPropertyToTextList(X_Dpy, &prop, &list,
&nitems) == Success && nitems > 0 && *list) {
@ -90,10 +92,101 @@ xu_getstrprop(Window win, Atom atm, char **text) {
}
XFreeStringList(list);
}
XFree(prop.value);
return(nitems);
return nitems;
}
void
xu_send_clientmsg(Window win, Atom proto, Time ts)
{
XClientMessageEvent cm;
(void)memset(&cm, 0, sizeof(cm));
cm.type = ClientMessage;
cm.window = win;
cm.message_type = cwmh[WM_PROTOCOLS];
cm.format = 32;
cm.data.l[0] = proto;
cm.data.l[1] = ts;
XSendEvent(X_Dpy, win, False, NoEventMask, (XEvent *)&cm);
}
void
xu_get_wm_state(Window win, long *state)
{
long *p;
*state = -1;
if (xu_get_prop(win, cwmh[WM_STATE], cwmh[WM_STATE], 2L,
(unsigned char **)&p) > 0) {
*state = *p;
XFree(p);
}
}
void
xu_set_wm_state(Window win, long state)
{
long data[] = { state, None };
XChangeProperty(X_Dpy, win, cwmh[WM_STATE], cwmh[WM_STATE], 32,
PropModeReplace, (unsigned char *)data, 2);
}
void
xu_xorcolor(XftColor a, XftColor b, XftColor *r)
{
r->pixel = a.pixel ^ b.pixel;
r->color.red = a.color.red ^ b.color.red;
r->color.green = a.color.green ^ b.color.green;
r->color.blue = a.color.blue ^ b.color.blue;
r->color.alpha = 0xffff;
}
void
xu_atom_init(void)
{
char *cwmhints[] = {
"WM_STATE",
"WM_DELETE_WINDOW",
"WM_TAKE_FOCUS",
"WM_PROTOCOLS",
"_MOTIF_WM_HINTS",
"UTF8_STRING",
"WM_CHANGE_STATE",
};
char *ewmhints[] = {
"_NET_SUPPORTED",
"_NET_SUPPORTING_WM_CHECK",
"_NET_ACTIVE_WINDOW",
"_NET_CLIENT_LIST",
"_NET_CLIENT_LIST_STACKING",
"_NET_NUMBER_OF_DESKTOPS",
"_NET_CURRENT_DESKTOP",
"_NET_DESKTOP_VIEWPORT",
"_NET_DESKTOP_GEOMETRY",
"_NET_VIRTUAL_ROOTS",
"_NET_SHOWING_DESKTOP",
"_NET_DESKTOP_NAMES",
"_NET_WORKAREA",
"_NET_WM_NAME",
"_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_HIDDEN",
"_NET_WM_STATE_FULLSCREEN",
"_NET_WM_STATE_DEMANDS_ATTENTION",
"_NET_WM_STATE_SKIP_PAGER",
"_NET_WM_STATE_SKIP_TASKBAR",
"_CWM_WM_STATE_FREEZE",
};
XInternAtoms(X_Dpy, cwmhints, nitems(cwmhints), False, cwmh);
XInternAtoms(X_Dpy, ewmhints, nitems(ewmhints), False, ewmh);
}
/* Root Window Properties */
@ -205,22 +298,6 @@ xu_ewmh_net_active_window(struct screen_ctx *sc, Window w)
XA_WINDOW, 32, PropModeReplace, (unsigned char *)&w, 1);
}
Window
xu_ewmh_get_net_active_window(struct screen_ctx *sc)
{
long *p;
Window win;
if ((xu_getprop(sc->rootwin, ewmh[_NET_ACTIVE_WINDOW],
XA_WINDOW, 32, (unsigned char **)&p)) <= 0)
return(None);
win = (Window)*p;
XFree(p);
return(win);
}
void
xu_ewmh_net_number_of_desktops(struct screen_ctx *sc)
{
@ -270,7 +347,7 @@ xu_ewmh_net_desktop_names(struct screen_ctx *sc)
/* Let group names be overwritten if _NET_DESKTOP_NAMES is set. */
if ((j = xu_getprop(sc->rootwin, ewmh[_NET_DESKTOP_NAMES],
if ((j = xu_get_prop(sc->rootwin, ewmh[_NET_DESKTOP_NAMES],
cwmh[UTF8_STRING], 0xffffff, (unsigned char **)&prop_ret)) > 0) {
prop_ret[j - 1] = '\0'; /* paranoia */
while (i < j) {
@ -312,8 +389,21 @@ xu_ewmh_net_desktop_names(struct screen_ctx *sc)
}
/* Application Window Properties */
int
xu_ewmh_get_net_wm_desktop(struct client_ctx *cc, long *n)
{
long *p;
if (xu_get_prop(cc->win, ewmh[_NET_WM_DESKTOP], XA_CARDINAL, 1L,
(unsigned char **)&p) <= 0)
return 0;
*n = *p;
XFree(p);
return 1;
}
void
xu_ewmh_net_wm_desktop(struct client_ctx *cc)
xu_ewmh_set_net_wm_desktop(struct client_ctx *cc)
{
long num = 0xffffffff;
@ -329,15 +419,15 @@ xu_ewmh_get_net_wm_state(struct client_ctx *cc, int *n)
{
Atom *state, *p = NULL;
if ((*n = xu_getprop(cc->win, ewmh[_NET_WM_STATE], XA_ATOM, 64L,
if ((*n = xu_get_prop(cc->win, ewmh[_NET_WM_STATE], XA_ATOM, 64L,
(unsigned char **)&p)) <= 0)
return(NULL);
return NULL;
state = xreallocarray(NULL, *n, sizeof(Atom));
(void)memcpy(state, p, *n * sizeof(Atom));
XFree((char *)p);
return(state);
return state;
}
void
@ -345,9 +435,9 @@ xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action,
Atom first, Atom second)
{
unsigned int i;
static struct handlers {
int atom;
int property;
struct handlers {
Atom atom;
int flag;
void (*toggle)(struct client_ctx *);
} handlers[] = {
{ _NET_WM_STATE_STICKY,
@ -385,11 +475,11 @@ xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action,
continue;
switch (action) {
case _NET_WM_STATE_ADD:
if (!(cc->flags & handlers[i].property))
if (!(cc->flags & handlers[i].flag))
handlers[i].toggle(cc);
break;
case _NET_WM_STATE_REMOVE:
if (cc->flags & handlers[i].property)
if (cc->flags & handlers[i].flag)
handlers[i].toggle(cc);
break;
case _NET_WM_STATE_TOGGLE:
@ -476,13 +566,3 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc)
XDeleteProperty(X_Dpy, cc->win, ewmh[_NET_WM_STATE]);
free(atoms);
}
void
xu_xorcolor(XftColor a, XftColor b, XftColor *r)
{
r->pixel = a.pixel ^ b.pixel;
r->color.red = a.color.red ^ b.color.red;
r->color.green = a.color.green ^ b.color.green;
r->color.blue = a.color.blue ^ b.color.blue;
r->color.alpha = 0xffff;
}