diff options
-rw-r--r-- | calmwm.c | 22 | ||||
-rw-r--r-- | calmwm.h | 78 | ||||
-rw-r--r-- | client.c | 373 | ||||
-rw-r--r-- | conf.c | 74 | ||||
-rw-r--r-- | cwmrc.5 | 49 | ||||
-rw-r--r-- | group.c | 46 | ||||
-rw-r--r-- | kbfunc.c | 79 | ||||
-rw-r--r-- | menu.c | 36 | ||||
-rw-r--r-- | parse.y | 18 | ||||
-rw-r--r-- | screen.c | 64 | ||||
-rw-r--r-- | search.c | 10 | ||||
-rw-r--r-- | util.c | 8 | ||||
-rw-r--r-- | xevents.c | 20 | ||||
-rw-r--r-- | xmalloc.c | 12 | ||||
-rw-r--r-- | xutil.c | 172 |
15 files changed, 540 insertions, 521 deletions
diff --git a/calmwm.c b/calmwm.c index 4111d95..04acc2e 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 *); @@ -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; diff --git a/calmwm.h b/calmwm.h index bd34cb2..95e3c8d 100644 --- a/calmwm.h +++ b/calmwm.h @@ -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); +void screen_assert_clients_within(struct screen_ctx *); +struct geom screen_area(struct screen_ctx *, int, 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 *); 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); diff --git a/client.c b/client.c index 2384f59..821da25 100644 --- a/client.c +++ b/client.c @@ -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; +} + +struct client_ctx * +client_current(struct screen_ctx *sc) +{ + struct screen_ctx *_sc; + struct client_ctx *cc; - return(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); } @@ -585,6 +596,23 @@ client_draw_border(struct client_ctx *cc) } 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) { Atom *p; @@ -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); -} diff --git a/conf.c b/conf.c index 7d1233d..53ca295 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 *); @@ -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); -} diff --git a/cwmrc.5 b/cwmrc.5 index 5208d29..ab70d25 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,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. diff --git a/group.c b/group.c index 164ef44..59eae73 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 551ccc7..2d5d1ce 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -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); diff --git a/menu.c b/menu.c index c9b4b0e..1d84ab7 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/parse.y b/parse.y index f115cd4..383b2dd 100644 --- a/parse.y +++ b/parse.y @@ -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} }; diff --git a/screen.c b/screen.c index 4ef86d5..59b6eff 100644 --- a/screen.c +++ b/screen.c @@ -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. */ diff --git a/search.c b/search.c index 06a08b7..12dde97 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 781308f..97b5641 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) { @@ -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 fbd93c5..5e138aa 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); + 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) { diff --git a/xmalloc.c b/xmalloc.c index 1041648..54867ae 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 5445357..c8f74fd 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; @@ -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; -} |