From 96275a835d34b0e17da0c4d3bad294620f82d4d5 Mon Sep 17 00:00:00 2001 From: okan Date: Thu, 27 Feb 2020 14:56:39 +0000 Subject: [PATCH 01/15] Unrelated style fixes, consistency changes and sorting, appropriate dosage/removal of wrappers, simplification of name queue, client cycle joins other kb/mb bound functions. --- calmwm.c | 9 +- calmwm.h | 81 ++++++------- client.c | 353 ++++++++++++++++++++++-------------------------------- conf.c | 72 +++-------- group.c | 46 ++++--- kbfunc.c | 68 +++++++++-- menu.c | 36 +++--- screen.c | 38 +++--- search.c | 10 +- util.c | 6 +- xevents.c | 18 +-- xmalloc.c | 12 +- xutil.c | 158 +++++++++++++++++++----- 13 files changed, 463 insertions(+), 444 deletions(-) diff --git a/calmwm.c b/calmwm.c index b1c23ed..3900dbc 100644 --- a/calmwm.c +++ b/calmwm.c @@ -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 *); @@ -124,7 +125,7 @@ main(int argc, char **argv) u_exec(fallback); } - return(0); + return 0; } static int @@ -142,7 +143,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++) @@ -180,7 +181,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 @@ -196,7 +197,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 diff --git a/calmwm.h b/calmwm.h index ac4cd3b..b15a39e 100644 --- a/calmwm.h +++ b/calmwm.h @@ -63,7 +63,6 @@ #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 @@ -100,11 +99,6 @@ struct geom { int w; int h; }; - -enum apply_gap { - CWM_NOGAP = 0, - CWM_GAP -}; struct gap { int top; int bottom; @@ -176,8 +170,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); @@ -390,40 +385,36 @@ extern Atom ewmh[EWMH_NITEMS]; extern struct screen_q Screenq; extern struct conf Conf; -__dead 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 *); -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); +void client_lower(struct client_ctx *); +void client_move(struct client_ctx *); +void client_mtf(struct client_ctx *); +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 *); @@ -453,16 +444,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); @@ -472,19 +463,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 *); @@ -533,7 +523,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 *, @@ -556,12 +545,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 *); @@ -576,8 +569,8 @@ 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); diff --git a/client.c b/client.c index 5ad328f..a2104ea 100644 --- a/client.c +++ b/client.c @@ -31,11 +31,10 @@ #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) @@ -46,19 +45,20 @@ client_init(Window win, struct screen_ctx *sc, int active) 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 +67,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 +86,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,10 +104,10 @@ 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); + if (cc->initial_state) + xu_set_wm_state(cc->win, cc->initial_state); } else { if ((active == 0) && (XQueryPointer(X_Dpy, cc->win, &rwin, &cwin, &x, &y, &wx, &wy, &mask)) && (cwin != None)) @@ -125,7 +128,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); @@ -149,9 +153,31 @@ out: XUngrabServer(X_Dpy); if (active) - client_setactive(cc); + client_set_active(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 +189,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 +235,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 +259,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 +277,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 +337,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 +375,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 +409,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 +441,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 +512,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 +523,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 +557,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 +566,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 +605,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 +642,60 @@ 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; int i = 0; - if (!xu_getstrprop(cc->win, ewmh[_NET_WM_NAME], &newname)) - if (!xu_getstrprop(cc->win, XA_WM_NAME, &newname)) + if (!xu_get_strprop(cc->win, ewmh[_NET_WM_NAME], &newname)) + if (!xu_get_strprop(cc->win, XA_WM_NAME, &newname)) newname = xstrdup(""); TAILQ_FOREACH(wn, &cc->nameq, entry) { - if (strcmp(wn->name, newname) == 0) { - /* Move to the last since we got a hit. */ + if (strcmp(wn->name, newname) == 0) TAILQ_REMOVE(&cc->nameq, wn, entry); - TAILQ_INSERT_TAIL(&cc->nameq, wn, entry); - goto match; - } - } - wn = xmalloc(sizeof(*wn)); - wn->name = newname; - 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) { + } + cc->name = newname; + wn = xmalloc(sizeof(*wn)); + wn->name = xstrdup(newname); + TAILQ_INSERT_TAIL(&cc->nameq, wn, entry); + + /* 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 +718,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 +752,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 +800,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 +851,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 +901,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 +923,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) @@ -1001,7 +950,7 @@ client_htile(struct client_ctx *cc) cc->geom.w = area.w - (cc->bwidth * 2); cc->geom.h = (area.h - (cc->bwidth * 2)) / 2; client_resize(cc, 1); - client_ptrwarp(cc); + client_ptr_warp(cc); mh = cc->geom.h + (cc->bwidth * 2); x = area.x; @@ -1042,7 +991,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) @@ -1069,7 +1018,7 @@ client_vtile(struct client_ctx *cc) cc->geom.w = (area.w - (cc->bwidth * 2)) / 2; 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 +1047,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); -} diff --git a/conf.c b/conf.c index 55dc40f..bd06294 100644 --- a/conf.c +++ b/conf.c @@ -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 *); @@ -517,7 +517,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 +525,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 +544,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 +575,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 +605,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 +636,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 +696,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); -} diff --git a/group.c b/group.c index bdec108..de55211 100644 --- a/group.c +++ b/group.c @@ -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; } diff --git a/kbfunc.c b/kbfunc.c index e27e707..f26adfc 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -59,7 +59,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; @@ -84,8 +84,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 @@ -132,7 +132,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); @@ -183,7 +183,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); @@ -247,9 +247,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], @@ -269,7 +269,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); @@ -298,7 +298,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) { @@ -334,7 +334,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); } @@ -402,13 +402,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 @@ -489,8 +531,8 @@ kbfunc_menu_client(void *ctx, struct cargs *cargs) cc = (struct client_ctx *)mi->ctx; client_show(cc); if (old_cc) - client_ptrsave(old_cc); - client_ptrwarp(cc); + client_ptr_save(old_cc); + client_ptr_warp(cc); } menuq_clear(&menuq); diff --git a/menu.c b/menu.c index 60633fc..43b5de8 100644 --- a/menu.c +++ b/menu.c @@ -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 diff --git a/screen.c b/screen.c index 1ddf679..18acc35 100644 --- a/screen.c +++ b/screen.c @@ -33,14 +33,14 @@ #include "calmwm.h" static struct geom screen_apply_gap(struct screen_ctx *, struct geom); +static void screen_scan(struct screen_ctx *, Window); void screen_init(int which) { struct screen_ctx *sc; - Window *wins, w0, w1, active = None; + Window active = None; XSetWindowAttributes rootattr; - unsigned int nwins, w; sc = xmalloc(sizeof(*sc)); @@ -77,13 +77,7 @@ screen_init(int which) 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_scan(sc, active); screen_updatestackingorder(sc); if (Conf.xrandr) @@ -94,6 +88,20 @@ screen_init(int which) XSync(X_Dpy, False); } +static void +screen_scan(struct screen_ctx *sc, Window active) +{ + Window *wins, w0, w1; + unsigned int nwins, i; + + if (XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins)) { + for (i = 0; i < nwins; i++) + (void)client_init(wins[i], sc, (active == wins[i])); + + XFree(wins); + } +} + struct screen_ctx * screen_find(Window win) { @@ -101,10 +109,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 +146,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 +164,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 +234,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. */ diff --git a/search.c b/search.c index 6911436..03f56e3 100644 --- a/search.c +++ b/search.c @@ -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) diff --git a/util.c b/util.c index f0e1d87..7c4bb5e 100644 --- a/util.c +++ b/util.c @@ -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 diff --git a/xevents.c b/xevents.c index c4bff7d..090886a 100644 --- a/xevents.c +++ b/xevents.c @@ -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); 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) { diff --git a/xmalloc.c b/xmalloc.c index 69973de..211d64c 100644 --- a/xmalloc.c +++ b/xmalloc.c @@ -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; } diff --git a/xutil.c b/xutil.c index d0b5111..69da471 100644 --- a/xutil.c +++ b/xutil.c @@ -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; @@ -74,7 +74,7 @@ xu_getstrprop(Window win, Atom atm, char **text) { XGetTextProperty(X_Dpy, win, &prop, atm); if (!prop.nitems) - return(0); + return 0; if (Xutf8TextPropertyToTextList(X_Dpy, &prop, &list, &nitems) == Success && nitems > 0 && *list) { @@ -90,10 +90,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 */ @@ -211,14 +302,14 @@ xu_ewmh_get_net_active_window(struct screen_ctx *sc) long *p; Window win; - if ((xu_getprop(sc->rootwin, ewmh[_NET_ACTIVE_WINDOW], + if ((xu_get_prop(sc->rootwin, ewmh[_NET_ACTIVE_WINDOW], XA_WINDOW, 32, (unsigned char **)&p)) <= 0) - return(None); + return None; win = (Window)*p; XFree(p); - return(win); + return win; } void @@ -270,7 +361,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 +403,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 +433,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 +449,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 +489,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 +580,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; -} From 3d1a8028c2cf9921ba66e7c0e8a76523a4ecde1e Mon Sep 17 00:00:00 2001 From: okan Date: Fri, 28 Feb 2020 13:38:35 +0000 Subject: [PATCH 02/15] Remove ColormaskChange from event-mask since there's no event handler. --- client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client.c b/client.c index a2104ea..653c0d4 100644 --- a/client.c +++ b/client.c @@ -114,8 +114,8 @@ client_init(Window win, struct screen_ctx *sc, int active) active = 1; } - XSelectInput(X_Dpy, cc->win, ColormapChangeMask | EnterWindowMask | - PropertyChangeMask | KeyReleaseMask); + XSelectInput(X_Dpy, cc->win, + EnterWindowMask | PropertyChangeMask | KeyReleaseMask); XAddToSaveSet(X_Dpy, cc->win); From d8c7d877379385cdf30d84498db5e7f2e6da28b9 Mon Sep 17 00:00:00 2001 From: tim Date: Fri, 13 Mar 2020 20:49:13 +0000 Subject: [PATCH 03/15] Plug two memory leaks. Also get rid of a variable that is no longer necessary. OK okan@ --- client.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/client.c b/client.c index 653c0d4..ea97344 100644 --- a/client.c +++ b/client.c @@ -668,21 +668,23 @@ void client_set_name(struct client_ctx *cc) { struct winname *wn; - char *newname; int i = 0; - if (!xu_get_strprop(cc->win, ewmh[_NET_WM_NAME], &newname)) - if (!xu_get_strprop(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) + if (strcmp(wn->name, cc->name) == 0) { TAILQ_REMOVE(&cc->nameq, wn, entry); + free(wn->name); + free(wn); + } i++; } - cc->name = newname; wn = xmalloc(sizeof(*wn)); - wn->name = xstrdup(newname); + wn->name = xstrdup(cc->name); TAILQ_INSERT_TAIL(&cc->nameq, wn, entry); /* Garbage collection. */ From 146fa08e4db93bc8910df5280eaab51a4257ceaf Mon Sep 17 00:00:00 2001 From: tim Date: Fri, 13 Mar 2020 20:50:07 +0000 Subject: [PATCH 04/15] Simplify list markup. OK okan@ schwarze@ --- cwmrc.5 | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/cwmrc.5 b/cwmrc.5 index 5208d29..fb07e2e 100644 --- a/cwmrc.5 +++ b/cwmrc.5 @@ -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,23 @@ This can be used for applications such as .Xr xclock 1 , where the user may wish to remain visible. -.Pp .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 +208,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 . From b9213d0a02de1254358a878cf14ee53f4fb4df0d Mon Sep 17 00:00:00 2001 From: tim Date: Sat, 14 Mar 2020 16:11:09 +0000 Subject: [PATCH 05/15] Revert previous. Causes a crash as reported by Tom Murphy. --- client.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/client.c b/client.c index ea97344..653c0d4 100644 --- a/client.c +++ b/client.c @@ -668,23 +668,21 @@ void client_set_name(struct client_ctx *cc) { struct winname *wn; + char *newname; int i = 0; - 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(""); + if (!xu_get_strprop(cc->win, ewmh[_NET_WM_NAME], &newname)) + if (!xu_get_strprop(cc->win, XA_WM_NAME, &newname)) + newname = xstrdup(""); TAILQ_FOREACH(wn, &cc->nameq, entry) { - if (strcmp(wn->name, cc->name) == 0) { + if (strcmp(wn->name, newname) == 0) TAILQ_REMOVE(&cc->nameq, wn, entry); - free(wn->name); - free(wn); - } i++; } + cc->name = newname; wn = xmalloc(sizeof(*wn)); - wn->name = xstrdup(cc->name); + wn->name = xstrdup(newname); TAILQ_INSERT_TAIL(&cc->nameq, wn, entry); /* Garbage collection. */ From 3b9b98c024dc0100af3a0700d8057b2ea96a6714 Mon Sep 17 00:00:00 2001 From: tim Date: Mon, 16 Mar 2020 17:50:44 +0000 Subject: [PATCH 06/15] Recommit 1.259, but now with TAILQ_FOREACH_SAFE. From and OK okan@ Original commit message: Plug two memory leaks. Also get rid of a variable that is no longer necessary. OK okan@ --- client.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/client.c b/client.c index 653c0d4..21c51bc 100644 --- a/client.c +++ b/client.c @@ -667,22 +667,24 @@ client_close(struct client_ctx *cc) void client_set_name(struct client_ctx *cc) { - struct winname *wn; - char *newname; + struct winname *wn, *wnnxt; int i = 0; - if (!xu_get_strprop(cc->win, ewmh[_NET_WM_NAME], &newname)) - if (!xu_get_strprop(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) + TAILQ_FOREACH_SAFE(wn, &cc->nameq, entry, wnnxt) { + if (strcmp(wn->name, cc->name) == 0) { TAILQ_REMOVE(&cc->nameq, wn, entry); + free(wn->name); + free(wn); + } i++; } - cc->name = newname; wn = xmalloc(sizeof(*wn)); - wn->name = xstrdup(newname); + wn->name = xstrdup(cc->name); TAILQ_INSERT_TAIL(&cc->nameq, wn, entry); /* Garbage collection. */ From 207b71ef1ca478e81fa812e6a1a757e98ac9a344 Mon Sep 17 00:00:00 2001 From: okan Date: Fri, 20 Mar 2020 12:13:20 +0000 Subject: [PATCH 07/15] No need to lookup current client early; move to right before it is needed. --- kbfunc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kbfunc.c b/kbfunc.c index f26adfc..b38610f 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -515,8 +515,6 @@ kbfunc_menu_client(void *ctx, struct cargs *cargs) 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) { @@ -530,7 +528,7 @@ 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) + if ((old_cc = client_current(sc)) != NULL) client_ptr_save(old_cc); client_ptr_warp(cc); } From 49f839e194b990dde123f35435c86cf5baa42c4d Mon Sep 17 00:00:00 2001 From: okan Date: Fri, 20 Mar 2020 15:16:31 +0000 Subject: [PATCH 08/15] Trim event_mask to those that the root window actually needs. --- screen.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/screen.c b/screen.c index 18acc35..b1e70e9 100644 --- a/screen.c +++ b/screen.c @@ -40,7 +40,7 @@ screen_init(int which) { struct screen_ctx *sc; Window active = None; - XSetWindowAttributes rootattr; + XSetWindowAttributes attr; sc = xmalloc(sizeof(*sc)); @@ -69,20 +69,17 @@ screen_init(int which) 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); - - screen_scan(sc, active); - 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, active); + screen_updatestackingorder(sc); + TAILQ_INSERT_TAIL(&Screenq, sc, entry); XSync(X_Dpy, False); From 6c7b8261df821459a7e0e6e04f5b4751132e25e4 Mon Sep 17 00:00:00 2001 From: tim Date: Fri, 20 Mar 2020 18:50:08 +0000 Subject: [PATCH 09/15] Simplify conditional construct. OK okan@ --- kbfunc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/kbfunc.c b/kbfunc.c index b38610f..cbccc56 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -509,7 +509,6 @@ 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) @@ -517,10 +516,8 @@ kbfunc_menu_client(void *ctx, struct cargs *cargs) 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); } From 0a7d8cc5c4bfa8df89c7b876d9f52bea14f37014 Mon Sep 17 00:00:00 2001 From: okan Date: Mon, 23 Mar 2020 20:14:27 +0000 Subject: [PATCH 10/15] Add support for SIGINT/SIGTERM. --- calmwm.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/calmwm.c b/calmwm.c index 3900dbc..a9a9035 100644 --- a/calmwm.c +++ b/calmwm.c @@ -89,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) @@ -216,6 +217,10 @@ sighdlr(int sig) case SIGHUP: cwm_status = CWM_EXEC_WM; break; + case SIGINT: + case SIGTERM: + cwm_status = CWM_QUIT; + break; } errno = save_errno; From 6c20772841684c18d85b45888de01e538f2999b4 Mon Sep 17 00:00:00 2001 From: okan Date: Tue, 24 Mar 2020 14:47:29 +0000 Subject: [PATCH 11/15] 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. --- calmwm.h | 3 +-- client.c | 12 +----------- screen.c | 27 +++++++++++++++++---------- xevents.c | 2 +- xutil.c | 16 ---------------- 5 files changed, 20 insertions(+), 40 deletions(-) diff --git a/calmwm.h b/calmwm.h index b15a39e..6fa5906 100644 --- a/calmwm.h +++ b/calmwm.h @@ -395,7 +395,7 @@ 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 *, int); +struct client_ctx *client_init(Window, struct screen_ctx *); void client_lower(struct client_ctx *); void client_move(struct client_ctx *); void client_mtf(struct client_ctx *); @@ -563,7 +563,6 @@ 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 *); diff --git a/client.c b/client.c index 21c51bc..61b2cf4 100644 --- a/client.c +++ b/client.c @@ -37,14 +37,11 @@ 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) @@ -108,10 +105,6 @@ client_init(Window win, struct screen_ctx *sc, int active) client_resize(cc, 0); if (cc->initial_state) xu_set_wm_state(cc->win, cc->initial_state); - } else { - if ((active == 0) && (XQueryPointer(X_Dpy, cc->win, &rwin, - &cwin, &x, &y, &wx, &wy, &mask)) && (cwin != None)) - active = 1; } XSelectInput(X_Dpy, cc->win, @@ -152,9 +145,6 @@ out: XSync(X_Dpy, False); XUngrabServer(X_Dpy); - if (active) - client_set_active(cc); - return cc; } diff --git a/screen.c b/screen.c index b1e70e9..373ff71 100644 --- a/screen.c +++ b/screen.c @@ -33,13 +33,12 @@ #include "calmwm.h" static struct geom screen_apply_gap(struct screen_ctx *, struct geom); -static void screen_scan(struct screen_ctx *, Window); +static void screen_scan(struct screen_ctx *); void screen_init(int which) { struct screen_ctx *sc; - Window active = None; XSetWindowAttributes attr; sc = xmalloc(sizeof(*sc)); @@ -67,7 +66,6 @@ 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); attr.cursor = Conf.cursor[CF_NORMAL]; attr.event_mask = SubstructureRedirectMask | SubstructureNotifyMask | @@ -77,7 +75,7 @@ screen_init(int which) if (Conf.xrandr) XRRSelectInput(X_Dpy, sc->rootwin, RRScreenChangeNotifyMask); - screen_scan(sc, active); + screen_scan(sc); screen_updatestackingorder(sc); TAILQ_INSERT_TAIL(&Screenq, sc, entry); @@ -86,17 +84,26 @@ screen_init(int which) } static void -screen_scan(struct screen_ctx *sc, Window active) +screen_scan(struct screen_ctx *sc) { - Window *wins, w0, w1; - unsigned int nwins, i; + 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++) - (void)client_init(wins[i], sc, (active == wins[i])); - + 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 * diff --git a/xevents.c b/xevents.c index 090886a..1aaa929 100644 --- a/xevents.c +++ b/xevents.c @@ -87,7 +87,7 @@ xev_handle_maprequest(XEvent *ee) 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_ptr_warp(cc); diff --git a/xutil.c b/xutil.c index 69da471..37af7db 100644 --- a/xutil.c +++ b/xutil.c @@ -296,22 +296,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_get_prop(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) { From 6afdd483c774925dacc39dcc2b290d3bbfacdf21 Mon Sep 17 00:00:00 2001 From: okan Date: Tue, 24 Mar 2020 14:48:29 +0000 Subject: [PATCH 12/15] zap stray tabs --- calmwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calmwm.c b/calmwm.c index a9a9035..af1effb 100644 --- a/calmwm.c +++ b/calmwm.c @@ -94,7 +94,7 @@ main(int argc, char **argv) signal(SIGINT, sighdlr) == SIG_ERR || signal(SIGTERM, sighdlr) == SIG_ERR) err(1, "signal"); - + if (parse_config(Conf.conf_file, &Conf) == -1) { warnx("error parsing config file"); if (nflag) From 6407eb9bc1380d879f354c0331dbb5ea5302fe51 Mon Sep 17 00:00:00 2001 From: okan Date: Thu, 16 Apr 2020 13:32:35 +0000 Subject: [PATCH 13/15] Allow configuring a percentage window size of the master window during htile/vtile actions. From Uwe Werler, with a few manpage tweaks. --- calmwm.h | 2 ++ client.c | 6 ++++-- conf.c | 2 ++ cwmrc.5 | 22 ++++++++++++++++++++-- parse.y | 18 +++++++++++++++++- 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/calmwm.h b/calmwm.h index 6fa5906..9ae2afe 100644 --- a/calmwm.h +++ b/calmwm.h @@ -291,6 +291,8 @@ struct conf { int bwidth; int mamount; int snapdist; + int htile; + int vtile; struct gap gap; char *color[CWM_COLOR_NITEMS]; char *font; diff --git a/client.c b/client.c index 61b2cf4..cfdd048 100644 --- a/client.c +++ b/client.c @@ -940,7 +940,8 @@ 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_ptr_warp(cc); @@ -1007,7 +1008,8 @@ 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_ptr_warp(cc); diff --git a/conf.c b/conf.c index bd06294..a3026cf 100644 --- a/conf.c +++ b/conf.c @@ -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; diff --git a/cwmrc.5 b/cwmrc.5 index fb07e2e..ab70d25 100644 --- a/cwmrc.5 +++ b/cwmrc.5 @@ -183,6 +183,13 @@ This can be used for applications such as .Xr xclock 1 , where the user may wish to remain visible. +.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 @@ -216,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 @@ -303,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. diff --git a/parse.y b/parse.y index 04e7bd4..0138fdb 100644 --- a/parse.y +++ b/parse.y @@ -71,7 +71,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 @@ -122,6 +122,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"); @@ -316,6 +330,7 @@ lookup(char *s) { "fontname", FONTNAME}, { "gap", GAP}, { "groupborder", GROUPBORDER}, + { "htile", HTILE}, { "ignore", IGNORE}, { "inactiveborder", INACTIVEBORDER}, { "menubg", MENUBG}, @@ -329,6 +344,7 @@ lookup(char *s) { "unbind-mouse", UNBINDMOUSE}, { "ungroupborder", UNGROUPBORDER}, { "urgencyborder", URGENCYBORDER}, + { "vtile", VTILE}, { "wm", WM}, { "yes", YES} }; From 3ebe04ee8ea2e5362678a102f6b1a4b418613f20 Mon Sep 17 00:00:00 2001 From: tobias Date: Thu, 16 Apr 2020 17:12:49 +0000 Subject: [PATCH 14/15] Prevent out of boundary write with configuration files in which too many quoted arguments are stored for other window managers. The quotation handling happens within the while loop without checking if the "end" limit has been already reached. If this happens, the final NULL assignment leads to an out of boundary write on stack. OK okan@ --- util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.c b/util.c index 7c4bb5e..904a54c 100644 --- a/util.c +++ b/util.c @@ -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) { From 91c05f94032debb645c14c76c9911ea5cfba5d3c Mon Sep 17 00:00:00 2001 From: tobias Date: Sat, 25 Apr 2020 20:07:28 +0000 Subject: [PATCH 15/15] Fixed memory leak in xu_get_strprop. If a client calls XSetTextProperty for a window to clear all its properties, then allocated memory within libX11 is not freed. OK okan@ --- xutil.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xutil.c b/xutil.c index 37af7db..230a2c5 100644 --- a/xutil.c +++ b/xutil.c @@ -73,8 +73,10 @@ xu_get_strprop(Window win, Atom atm, char **text) { *text = NULL; XGetTextProperty(X_Dpy, win, &prop, atm); - if (!prop.nitems) + if (!prop.nitems) { + XFree(prop.value); return 0; + } if (Xutf8TextPropertyToTextList(X_Dpy, &prop, &list, &nitems) == Success && nitems > 0 && *list) {