diff --git a/calmwm.c b/calmwm.c index 7fc749b..813d606 100644 --- a/calmwm.c +++ b/calmwm.c @@ -36,18 +36,14 @@ #include "calmwm.h" -Display *X_Dpy; -Time Last_Event_Time = CurrentTime; -Atom cwmh[CWMH_NITEMS]; -Atom ewmh[EWMH_NITEMS]; - -struct screen_ctx_q Screenq = TAILQ_HEAD_INITIALIZER(Screenq); - -int HasRandr, Randr_ev; -struct conf Conf; -const char *homedir; -char *wm_argv; -volatile sig_atomic_t cwm_status; +Display *X_Dpy; +Time Last_Event_Time = CurrentTime; +Atom cwmh[CWMH_NITEMS]; +Atom ewmh[EWMH_NITEMS]; +struct screen_q Screenq = TAILQ_HEAD_INITIALIZER(Screenq); +struct conf Conf; +const char *homedir; +volatile sig_atomic_t cwm_status; static void sighdlr(int); static int x_errorhandler(Display *, XErrorEvent *); @@ -67,7 +63,7 @@ main(int argc, char **argv) warnx("no locale support"); mbtowc(NULL, NULL, MB_CUR_MAX); - wm_argv = u_argv(argv); + Conf.wm_argv = u_argv(argv); while ((ch = getopt(argc, argv, "c:d:")) != -1) { switch (ch) { case 'c': @@ -107,6 +103,7 @@ main(int argc, char **argv) } conf_init(&Conf); + if (conf_path && (parse_config(conf_path, &Conf) == -1)) warnx("config file %s has errors", conf_path); free(conf_path); @@ -123,7 +120,7 @@ main(int argc, char **argv) xev_process(); x_teardown(); if (cwm_status == CWM_EXEC_WM) - u_exec(wm_argv); + u_exec(Conf.wm_argv); return(0); } @@ -141,7 +138,7 @@ x_init(const char *dpyname) XSync(X_Dpy, False); XSetErrorHandler(x_errorhandler); - HasRandr = XRRQueryExtension(X_Dpy, &Randr_ev, &i); + Conf.xrandr = XRRQueryExtension(X_Dpy, &Conf.xrandr_event_base, &i); conf_atoms(); conf_cursor(&Conf); @@ -163,10 +160,9 @@ x_teardown(void) XftColorFree(X_Dpy, DefaultVisual(X_Dpy, sc->which), DefaultColormap(X_Dpy, sc->which), &sc->xftcolor[i]); - XftDrawDestroy(sc->xftdraw); XftFontClose(X_Dpy, sc->xftfont); - XUnmapWindow(X_Dpy, sc->menuwin); - XDestroyWindow(X_Dpy, sc->menuwin); + XftDrawDestroy(sc->menu.xftdraw); + XDestroyWindow(X_Dpy, sc->menu.win); XUngrabKey(X_Dpy, AnyKey, AnyModifier, sc->rootwin); } XUngrabPointer(X_Dpy, CurrentTime); diff --git a/calmwm.h b/calmwm.h index 2936b77..faac8bb 100644 --- a/calmwm.h +++ b/calmwm.h @@ -62,7 +62,6 @@ size_t strlcpy(char *, const char *, size_t); #endif #define CONFFILE ".cwmrc" -#define WMNAME "CWM" #define BUTTONMASK (ButtonPressMask | ButtonReleaseMask) #define MOUSEMASK (BUTTONMASK | PointerMotionMask) @@ -79,49 +78,21 @@ size_t strlcpy(char *, const char *, size_t); #define CWM_BIGAMOUNT 0x0010 #define DIRECTIONMASK (CWM_UP | CWM_DOWN | CWM_LEFT | CWM_RIGHT) -#define CWM_CLIENT_CYCLE 0x0001 -#define CWM_CLIENT_RCYCLE 0x0002 -#define CWM_CLIENT_CYCLE_INGRP 0x0004 +#define CWM_CYCLE_FORWARD 0x0001 +#define CWM_CYCLE_REVERSE 0x0002 +#define CWM_CYCLE_INGROUP 0x0004 -#define CWM_CLIENT_TILE_HORIZ 0x0001 -#define CWM_CLIENT_TILE_VERT 0x0002 - -#define CWM_MENU_EXEC 0x0001 -#define CWM_MENU_EXEC_WM 0x0002 - -#define CWM_MENU_DUMMY 0x0001 -#define CWM_MENU_FILE 0x0002 -#define CWM_MENU_LIST 0x0004 - -#define CWM_GAP 0x0001 -#define CWM_NOGAP 0x0002 - -#define CWM_KBD 0x0001 -#define CWM_MOUSE 0x0002 - -#define CWM_CONTEXT_NONE 0x0000 -#define CWM_CONTEXT_CLIENT 0x0001 -#define CWM_CONTEXT_SCREEN 0x0002 - -#define CWM_QUIT 0x0000 -#define CWM_RUNNING 0x0001 -#define CWM_EXEC_WM 0x0002 - -union arg { - char *c; - int i; -}; -union press { - KeySym keysym; - unsigned int button; +enum cwm_status { + CWM_QUIT, + CWM_RUNNING, + CWM_EXEC_WM }; enum cursor_font { - CF_DEFAULT, - CF_MOVE, CF_NORMAL, - CF_QUESTION, + CF_MOVE, CF_RESIZE, + CF_QUESTION, CF_NITEMS }; enum color { @@ -144,6 +115,10 @@ struct geom { int h; }; +enum apply_gap { + CWM_NOGAP = 0, + CWM_GAP +}; struct gap { int top; int bottom; @@ -155,7 +130,7 @@ struct winname { TAILQ_ENTRY(winname) entry; char *name; }; -TAILQ_HEAD(winname_q, winname); +TAILQ_HEAD(name_q, winname); TAILQ_HEAD(ignore_q, winname); struct client_ctx { @@ -208,33 +183,30 @@ struct client_ctx { #define CLIENT_MAXIMIZED (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED) int flags; int stackingorder; - struct winname_q nameq; -#define CLIENT_MAXNAMEQLEN 5 - int nameqlen; + struct name_q nameq; char *name; char *label; - char *matchname; XClassHint ch; XWMHints *wmh; }; -TAILQ_HEAD(client_ctx_q, client_ctx); +TAILQ_HEAD(client_q, client_ctx); struct group_ctx { TAILQ_ENTRY(group_ctx) entry; struct screen_ctx *sc; char *name; int num; - struct client_ctx_q clientq; + struct client_q clientq; }; -TAILQ_HEAD(group_ctx_q, group_ctx); +TAILQ_HEAD(group_q, group_ctx); -struct autogroupwin { - TAILQ_ENTRY(autogroupwin) entry; - char *class; - char *name; - int num; +struct autogroup { + TAILQ_ENTRY(autogroup) entry; + char *class; + char *name; + int num; }; -TAILQ_HEAD(autogroupwin_q, autogroupwin); +TAILQ_HEAD(autogroup_q, autogroup); struct region_ctx { TAILQ_ENTRY(region_ctx) entry; @@ -243,47 +215,73 @@ struct region_ctx { struct geom view; /* viewable area */ struct geom work; /* workable area, gap-applied */ }; -TAILQ_HEAD(region_ctx_q, region_ctx); +TAILQ_HEAD(region_q, region_ctx); struct screen_ctx { TAILQ_ENTRY(screen_ctx) entry; int which; Window rootwin; - Window menuwin; int cycling; int hideall; int snapdist; struct geom view; /* viewable area */ struct geom work; /* workable area, gap-applied */ struct gap gap; - struct client_ctx_q clientq; - struct region_ctx_q regionq; -#define CALMWM_NGROUPS 10 - struct group_ctx_q groupq; + struct client_q clientq; + struct region_q regionq; + struct group_q groupq; struct group_ctx *group_active; + struct { + Window win; + XftDraw *xftdraw; + } menu; XftColor xftcolor[CWM_COLOR_NITEMS]; - XftDraw *xftdraw; XftFont *xftfont; }; -TAILQ_HEAD(screen_ctx_q, screen_ctx); +TAILQ_HEAD(screen_q, screen_ctx); -struct binding { - TAILQ_ENTRY(binding) entry; - void (*callback)(struct client_ctx *, union arg *); +enum xev { + CWM_XEV_KEY, + CWM_XEV_BTN +}; +union arg { + char *c; + int i; +}; +union press { + KeySym keysym; + unsigned int button; +}; +enum context { + CWM_CONTEXT_NONE, + CWM_CONTEXT_CC, + CWM_CONTEXT_SC +}; +struct bind_ctx { + TAILQ_ENTRY(bind_ctx) entry; + void (*callback)(void *, union arg *, enum xev); union arg argument; unsigned int modmask; union press press; - int context; + enum context context; }; -TAILQ_HEAD(keybinding_q, binding); -TAILQ_HEAD(mousebinding_q, binding); +TAILQ_HEAD(keybind_q, bind_ctx); +TAILQ_HEAD(mousebind_q, bind_ctx); -struct cmd { - TAILQ_ENTRY(cmd) entry; +struct cmd_ctx { + TAILQ_ENTRY(cmd_ctx) entry; char *name; char path[PATH_MAX]; }; -TAILQ_HEAD(cmd_q, cmd); +TAILQ_HEAD(cmd_q, cmd_ctx); + +enum menu_exec { + CWM_MENU_EXEC_EXEC, + CWM_MENU_EXEC_WM +}; +#define CWM_MENU_DUMMY 0x0001 +#define CWM_MENU_FILE 0x0002 +#define CWM_MENU_LIST 0x0004 struct menu { TAILQ_ENTRY(menu) entry; @@ -298,39 +296,37 @@ struct menu { TAILQ_HEAD(menu_q, menu); struct conf { - struct keybinding_q keybindingq; - struct mousebinding_q mousebindingq; - struct autogroupwin_q autogroupq; + struct keybind_q keybindq; + struct mousebind_q mousebindq; + struct autogroup_q autogroupq; struct ignore_q ignoreq; struct cmd_q cmdq; -#define CONF_STICKY_GROUPS 0x0001 - int flags; -#define CONF_BWIDTH 1 + int ngroups; + int stickygroups; + int nameqlen; int bwidth; -#define CONF_MAMOUNT 1 int mamount; -#define CONF_SNAPDIST 0 int snapdist; struct gap gap; char *color[CWM_COLOR_NITEMS]; char known_hosts[PATH_MAX]; -#define CONF_FONT "sans-serif:pixelsize=14:bold" char *font; + char *wmname; Cursor cursor[CF_NITEMS]; + int xrandr; + int xrandr_event_base; + char *wm_argv; }; /* MWM hints */ struct mwm_hints { - unsigned long flags; - unsigned long functions; - unsigned long decorations; -}; #define MWM_HINTS_ELEMENTS 3L +#define MWM_FLAGS_STATUS (1<<3) #define MWM_FLAGS_FUNCTIONS (1<<0) #define MWM_FLAGS_DECORATIONS (1<<1) #define MWM_FLAGS_INPUT_MODE (1<<2) -#define MWM_FLAGS_STATUS (1<<3) + unsigned long flags; #define MWM_FUNCS_ALL (1<<0) #define MWM_FUNCS_RESIZE (1<<1) @@ -338,6 +334,7 @@ struct mwm_hints { #define MWM_FUNCS_MINIMIZE (1<<3) #define MWM_FUNCS_MAXIMIZE (1<<4) #define MWM_FUNCS_CLOSE (1<<5) + unsigned long functions; #define MWM_DECOR_ALL (1<<0) #define MWM_DECOR_BORDER (1<<1) @@ -346,16 +343,10 @@ struct mwm_hints { #define MWM_DECOR_MENU (1<<4) #define MWM_DECOR_MINIMIZE (1<<5) #define MWM_DECOR_MAXIMIZE (1<<6) + unsigned long decorations; +}; -extern Display *X_Dpy; -extern Time Last_Event_Time; -extern struct screen_ctx_q Screenq; -extern struct conf Conf; -extern char *wm_argv; -extern const char *homedir; -extern int HasRandr, Randr_ev; - -enum { +enum cwmh { WM_STATE, WM_DELETE_WINDOW, WM_TAKE_FOCUS, @@ -365,7 +356,7 @@ enum { WM_CHANGE_STATE, CWMH_NITEMS }; -enum { +enum ewmh { _NET_SUPPORTED, _NET_SUPPORTING_WM_CHECK, _NET_ACTIVE_WINDOW, @@ -393,13 +384,19 @@ enum { _CWM_WM_STATE_FREEZE, EWMH_NITEMS }; -enum { +enum net_wm_state { _NET_WM_STATE_REMOVE, _NET_WM_STATE_ADD, _NET_WM_STATE_TOGGLE }; + +extern Display *X_Dpy; +extern Time Last_Event_Time; extern Atom cwmh[CWMH_NITEMS]; extern Atom ewmh[EWMH_NITEMS]; +extern struct screen_q Screenq; +extern struct conf Conf; +extern const char *homedir; void usage(void); @@ -419,6 +416,7 @@ void client_lower(struct client_ctx *); void client_map(struct client_ctx *); void client_msg(struct client_ctx *, Atom, Time); void client_move(struct client_ctx *); +int client_inbound(struct client_ctx *, int, int); struct client_ctx *client_init(Window, struct screen_ctx *, int); void client_ptrsave(struct client_ctx *); void client_ptrwarp(struct client_ctx *); @@ -440,7 +438,6 @@ void client_transient(struct client_ctx *); void client_unhide(struct client_ctx *); void client_urgency(struct client_ctx *); void client_vtile(struct client_ctx *); -void client_warp(struct client_ctx *); void client_wm_hints(struct client_ctx *); void group_alltoggle(struct screen_ctx *); @@ -477,62 +474,59 @@ void search_print_group(struct menu *, int); struct region_ctx *region_find(struct screen_ctx *, int, int); struct geom screen_apply_gap(struct screen_ctx *, struct geom); struct screen_ctx *screen_find(Window); -struct geom screen_area(struct screen_ctx *, int, int, int); +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 kbfunc_client_cycle(struct client_ctx *, union arg *); -void kbfunc_client_delete(struct client_ctx *, union arg *); -void kbfunc_client_grouptoggle(struct client_ctx *, - union arg *); -void kbfunc_client_hide(struct client_ctx *, union arg *); -void kbfunc_client_label(struct client_ctx *, union arg *); -void kbfunc_client_lower(struct client_ctx *, union arg *); -void kbfunc_client_move(struct client_ctx *, union arg *); -void kbfunc_client_movetogroup(struct client_ctx *, - union arg *); -void kbfunc_client_raise(struct client_ctx *, union arg *); -void kbfunc_client_rcycle(struct client_ctx *, union arg *); -void kbfunc_client_resize(struct client_ctx *, union arg *); -void kbfunc_client_tile(struct client_ctx *, union arg *); -void kbfunc_client_toggle_freeze(struct client_ctx *, - union arg *); -void kbfunc_client_toggle_fullscreen(struct client_ctx *, - union arg *); -void kbfunc_client_toggle_hmaximize(struct client_ctx *, - union arg *); -void kbfunc_client_toggle_maximize(struct client_ctx *, - union arg *); -void kbfunc_client_toggle_sticky(struct client_ctx *, - union arg *); -void kbfunc_client_toggle_vmaximize(struct client_ctx *, - union arg *); -void kbfunc_cwm_status(struct client_ctx *, union arg *); -void kbfunc_exec(struct client_ctx *, union arg *); -void kbfunc_exec_lock(struct client_ctx *, union arg *); -void kbfunc_exec_term(struct client_ctx *, union arg *); -void kbfunc_group_alltoggle(struct client_ctx *, - union arg *); -void kbfunc_group_cycle(struct client_ctx *, union arg *); -void kbfunc_group_only(struct client_ctx *, union arg *); -void kbfunc_group_toggle(struct client_ctx *, union arg *); -void kbfunc_menu_exec(struct client_ctx *, union arg *); -void kbfunc_menu_client(struct client_ctx *, union arg *); -void kbfunc_menu_cmd(struct client_ctx *, union arg *); -void kbfunc_menu_group(struct client_ctx *, union arg *); -void kbfunc_menu_ssh(struct client_ctx *, union arg *); -void kbfunc_ptrmove(struct client_ctx *, union arg *); +void kbfunc_cwm_status(void *, union arg *, enum xev); +void kbfunc_ptrmove(void *, union arg *, enum xev); +void kbfunc_client_move(void *, union arg *, enum xev); +void kbfunc_client_resize(void *, union arg *, enum xev); +void kbfunc_client_delete(void *, union arg *, enum xev); +void kbfunc_client_lower(void *, union arg *, enum xev); +void kbfunc_client_raise(void *, union arg *, enum xev); +void kbfunc_client_hide(void *, union arg *, enum xev); +void kbfunc_client_toggle_freeze(void *, + union arg *, enum xev); +void kbfunc_client_toggle_sticky(void *, + union arg *, enum xev); +void kbfunc_client_toggle_fullscreen(void *, + union arg *, enum xev); +void kbfunc_client_toggle_maximize(void *, + union arg *, enum xev); +void kbfunc_client_toggle_hmaximize(void *, + union arg *, enum xev); +void kbfunc_client_toggle_vmaximize(void *, + union arg *, enum xev); +void kbfunc_client_htile(void *, union arg *, enum xev); +void kbfunc_client_vtile(void *, union arg *, enum xev); +void kbfunc_client_cycle(void *, union arg *, enum xev); +void kbfunc_client_toggle_group(void *, + union arg *, enum xev); +void kbfunc_client_movetogroup(void *, + union arg *, enum xev); +void kbfunc_group_toggle(void *, union arg *, enum xev); +void kbfunc_group_only(void *, union arg *, enum xev); +void kbfunc_group_cycle(void *, union arg *, enum xev); +void kbfunc_group_alltoggle(void *, union arg *, enum xev); +void kbfunc_menu_client(void *, union arg *, enum xev); +void kbfunc_menu_cmd(void *, union arg *, enum xev); +void kbfunc_menu_group(void *, union arg *, enum xev); +void kbfunc_menu_exec(void *, union arg *, enum xev); +void kbfunc_menu_ssh(void *, union arg *, enum xev); +void kbfunc_menu_client_label(void *, union arg *, enum xev); +void kbfunc_exec_cmd(void *, union arg *, enum xev); +void kbfunc_exec_lock(void *, union arg *, enum xev); +void kbfunc_exec_term(void *, union arg *, enum xev); -void mousefunc_client_move(struct client_ctx *, - union arg *); -void mousefunc_client_resize(struct client_ctx *, - union arg *); -void mousefunc_menu_client(struct client_ctx *, - union arg *); -void mousefunc_menu_cmd(struct client_ctx *, union arg *); -void mousefunc_menu_group(struct client_ctx *, union arg *); +void mousefunc_client_move(void *, union arg *, enum xev); +void mousefunc_client_resize(void *, union arg *, enum xev); +void menu_windraw(struct screen_ctx *, Window, + const char *, ...); struct menu *menu_filter(struct screen_ctx *, struct menu_q *, const char *, const char *, int, void (*)(struct menu_q *, struct menu_q *, char *), @@ -562,20 +556,10 @@ void conf_screen(struct screen_ctx *); void xev_process(void); -void xu_btn_grab(Window, int, unsigned int); -void xu_btn_ungrab(Window); int xu_getprop(Window, Atom, Atom, long, unsigned char **); int xu_getstrprop(Window, Atom, char **); -void xu_key_grab(Window, unsigned int, KeySym); -void xu_key_ungrab(Window); void xu_ptr_getpos(Window, int *, int *); -int xu_ptr_grab(Window, unsigned int, Cursor); -int xu_ptr_regrab(unsigned int, Cursor); void xu_ptr_setpos(Window, int, int); -void xu_ptr_ungrab(void); -void xu_xft_draw(struct screen_ctx *, const char *, - int, int, int); -int xu_xft_width(XftFont *, const char *, int); void xu_xorcolor(XftColor, XftColor, XftColor *); void xu_ewmh_net_supported(struct screen_ctx *); diff --git a/client.c b/client.c index da4e8b9..7975bb9 100644 --- a/client.c +++ b/client.c @@ -34,13 +34,9 @@ static struct client_ctx *client_next(struct client_ctx *); static struct client_ctx *client_prev(struct client_ctx *); static void client_mtf(struct client_ctx *); -static void client_none(struct screen_ctx *); static void client_placecalc(struct client_ctx *); static void client_wm_protocols(struct client_ctx *); static void client_mwm_hints(struct client_ctx *); -static int client_inbound(struct client_ctx *, int, int); - -struct client_ctx *curcc = NULL; struct client_ctx * client_init(Window win, struct screen_ctx *sc, int active) @@ -79,8 +75,6 @@ client_init(Window win, struct screen_ctx *sc, int active) cc->stackingorder = 0; memset(&cc->hint, 0, sizeof(cc->hint)); memset(&cc->ch, 0, sizeof(cc->ch)); - cc->ptr.x = -1; - cc->ptr.y = -1; TAILQ_INIT(&cc->nameq); client_setname(cc); @@ -97,6 +91,9 @@ client_init(Window win, struct screen_ctx *sc, int active) cc->geom.y = wattr.y; cc->geom.w = wattr.width; cc->geom.h = wattr.height; + cc->ptr.x = cc->geom.w / 2; + cc->ptr.y = cc->geom.h / 2; + cc->colormap = wattr.colormap; if (wattr.map_state != IsViewable) { @@ -136,7 +133,7 @@ client_init(Window win, struct screen_ctx *sc, int active) goto out; if (group_autogroup(cc)) goto out; - if (Conf.flags & CONF_STICKY_GROUPS) + if (Conf.stickygroups) group_assign(sc->group_active, cc); else group_assign(NULL, cc); @@ -178,7 +175,7 @@ client_delete(struct client_ctx *cc) xu_ewmh_net_client_list_stacking(sc); if (cc->flags & CLIENT_ACTIVE) - client_none(sc); + xu_ewmh_net_active_window(sc, None); if (cc->gc != NULL) TAILQ_REMOVE(&cc->gc->clientq, cc, group_entry); @@ -227,7 +224,6 @@ client_setactive(struct client_ctx *cc) if (!sc->cycling) client_mtf(cc); - curcc = cc; cc->flags |= CLIENT_ACTIVE; cc->flags &= ~CLIENT_URGENCY; client_draw_border(cc); @@ -235,23 +231,19 @@ client_setactive(struct client_ctx *cc) xu_ewmh_net_active_window(sc, cc->win); } -/* - * set when there is no active client - */ -static void -client_none(struct screen_ctx *sc) -{ - Window none = None; - - xu_ewmh_net_active_window(sc, none); - - curcc = NULL; -} - struct client_ctx * client_current(void) { - return(curcc); + struct screen_ctx *sc; + struct client_ctx *cc; + + TAILQ_FOREACH(sc, &Screenq, entry) { + TAILQ_FOREACH(cc, &sc->clientq, entry) { + if (cc->flags & CLIENT_ACTIVE) + return(cc); + } + } + return(NULL); } void @@ -477,18 +469,7 @@ client_config(struct client_ctx *cc) void client_ptrwarp(struct client_ctx *cc) { - int x = cc->ptr.x, y = cc->ptr.y; - - if (x == -1 || y == -1) { - x = cc->geom.w / 2; - y = cc->geom.h / 2; - } - - if (cc->flags & CLIENT_HIDDEN) - client_unhide(cc); - else - client_raise(cc); - xu_ptr_setpos(cc->win, x, y); + xu_ptr_setpos(cc->win, cc->ptr.x, cc->ptr.y); } void @@ -501,8 +482,8 @@ client_ptrsave(struct client_ctx *cc) cc->ptr.x = x; cc->ptr.y = y; } else { - cc->ptr.x = -1; - cc->ptr.y = -1; + cc->ptr.x = cc->geom.w / 2; + cc->ptr.y = cc->geom.h / 2; } } @@ -512,7 +493,7 @@ client_hide(struct client_ctx *cc) XUnmapWindow(X_Dpy, cc->win); if (cc->flags & CLIENT_ACTIVE) - client_none(cc->sc); + xu_ewmh_net_active_window(cc->sc, None); cc->flags &= ~CLIENT_ACTIVE; cc->flags |= CLIENT_HIDDEN; @@ -624,6 +605,7 @@ client_setname(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)) @@ -640,19 +622,19 @@ client_setname(struct client_ctx *cc) wn = xmalloc(sizeof(*wn)); wn->name = newname; TAILQ_INSERT_TAIL(&cc->nameq, wn, entry); - cc->nameqlen++; match: cc->name = wn->name; - /* Now, do some garbage collection. */ - if (cc->nameqlen > CLIENT_MAXNAMEQLEN) { - if ((wn = TAILQ_FIRST(&cc->nameq)) == NULL) - errx(1, "client_setname: window name queue empty"); + /* Do some garbage collection. */ + TAILQ_FOREACH(wn, &cc->nameq, entry) + i++; + if (i > Conf.nameqlen) { + wn = TAILQ_FIRST(&cc->nameq); TAILQ_REMOVE(&cc->nameq, wn, entry); free(wn->name); free(wn); - cc->nameqlen--; + i--; } } @@ -671,20 +653,20 @@ client_cycle(struct screen_ctx *sc, int flags) oldcc = client_current(); if (oldcc == NULL) - oldcc = (flags & CWM_CLIENT_RCYCLE) ? - TAILQ_LAST(&sc->clientq, client_ctx_q) : + oldcc = (flags & CWM_CYCLE_REVERSE) ? + TAILQ_LAST(&sc->clientq, client_q) : TAILQ_FIRST(&sc->clientq); newcc = oldcc; while (again) { again = 0; - newcc = (flags & CWM_CLIENT_RCYCLE) ? client_prev(newcc) : + newcc = (flags & CWM_CYCLE_REVERSE) ? client_prev(newcc) : client_next(newcc); /* Only cycle visible and non-ignored windows. */ if ((newcc->flags & (CLIENT_HIDDEN | CLIENT_IGNORE)) - || ((flags & CWM_CLIENT_CYCLE_INGRP) && + || ((flags & CWM_CYCLE_INGROUP) && (newcc->gc != oldcc->gc))) again = 1; @@ -700,6 +682,11 @@ client_cycle(struct screen_ctx *sc, int flags) /* reset when cycling mod is released. XXX I hate this hack */ sc->cycling = 1; client_ptrsave(oldcc); + 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); } @@ -734,8 +721,8 @@ client_prev(struct client_ctx *cc) struct screen_ctx *sc = cc->sc; struct client_ctx *newcc; - return(((newcc = TAILQ_PREV(cc, client_ctx_q, entry)) != NULL) ? - newcc : TAILQ_LAST(&sc->clientq, client_ctx_q)); + return(((newcc = TAILQ_PREV(cc, client_q, entry)) != NULL) ? + newcc : TAILQ_LAST(&sc->clientq, client_q)); } static void @@ -925,7 +912,7 @@ client_transient(struct client_ctx *cc) } } -static int +int client_inbound(struct client_ctx *cc, int x, int y) { return(x < cc->geom.w && x >= 0 && diff --git a/conf.c b/conf.c index 24f1902..cebfc07 100644 --- a/conf.c +++ b/conf.c @@ -34,13 +34,13 @@ static const char *conf_bind_getmask(const char *, unsigned int *); static void conf_cmd_remove(struct conf *, const char *); -static void conf_unbind_kbd(struct conf *, struct binding *); -static void conf_unbind_mouse(struct conf *, struct binding *); +static void conf_unbind_kbd(struct conf *, struct bind_ctx *); +static void conf_unbind_mouse(struct conf *, struct bind_ctx *); int conf_cmd_add(struct conf *c, const char *name, const char *path) { - struct cmd *cmd; + struct cmd_ctx *cmd; cmd = xmalloc(sizeof(*cmd)); @@ -61,7 +61,7 @@ conf_cmd_add(struct conf *c, const char *name, const char *path) static void conf_cmd_remove(struct conf *c, const char *name) { - struct cmd *cmd = NULL, *cmdnxt; + struct cmd_ctx *cmd = NULL, *cmdnxt; TAILQ_FOREACH_SAFE(cmd, &c->cmdq, entry, cmdnxt) { if (strcmp(cmd->name, name) == 0) { @@ -74,31 +74,31 @@ conf_cmd_remove(struct conf *c, const char *name) void conf_autogroup(struct conf *c, int num, const char *name, const char *class) { - struct autogroupwin *aw; + struct autogroup *ag; char *p; - aw = xmalloc(sizeof(*aw)); + ag = xmalloc(sizeof(*ag)); if ((p = strchr(class, ',')) == NULL) { if (name == NULL) - aw->name = NULL; + ag->name = NULL; else - aw->name = xstrdup(name); + ag->name = xstrdup(name); - aw->class = xstrdup(class); + ag->class = xstrdup(class); } else { *(p++) = '\0'; if (name == NULL) - aw->name = xstrdup(class); + ag->name = xstrdup(class); else - aw->name = xstrdup(name); + ag->name = xstrdup(name); - aw->class = xstrdup(p); + ag->class = xstrdup(p); } - aw->num = num; + ag->num = num; - TAILQ_INSERT_TAIL(&c->autogroupq, aw, entry); + TAILQ_INSERT_TAIL(&c->autogroupq, ag, entry); } void @@ -138,7 +138,7 @@ conf_screen(struct screen_ctx *sc) if (sc->xftfont == NULL) { sc->xftfont = XftFontOpenName(X_Dpy, sc->which, Conf.font); if (sc->xftfont == NULL) - errx(1, "XftFontOpenName: %s", Conf.font); + errx(1, "%s: XftFontOpenName: %s", __func__, Conf.font); } for (i = 0; i < nitems(color_binds); i++) { @@ -162,14 +162,14 @@ conf_screen(struct screen_ctx *sc) } } - sc->menuwin = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0, 1, 1, + sc->menu.win = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0, 1, 1, Conf.bwidth, sc->xftcolor[CWM_COLOR_MENU_FG].pixel, sc->xftcolor[CWM_COLOR_MENU_BG].pixel); - sc->xftdraw = XftDrawCreate(X_Dpy, sc->menuwin, visual, colormap); - if (sc->xftdraw == NULL) - errx(1, "XftDrawCreate"); + sc->menu.xftdraw = XftDrawCreate(X_Dpy, sc->menu.win, visual, colormap); + if (sc->menu.xftdraw == NULL) + errx(1, "%s: XftDrawCreate", __func__); conf_grab_kbd(sc->rootwin); } @@ -192,6 +192,7 @@ static const struct { { "MS-Tab", "rcycle" }, { "CM-n", "label" }, { "CM-x", "delete" }, + { "CM-a", "nogroup" }, { "CM-0", "nogroup" }, { "CM-1", "group1" }, { "CM-2", "group2" }, @@ -254,15 +255,18 @@ conf_init(struct conf *c) { unsigned int i; - c->bwidth = CONF_BWIDTH; - c->mamount = CONF_MAMOUNT; - c->snapdist = CONF_SNAPDIST; + c->stickygroups = 0; + c->bwidth = 1; + c->mamount = 1; + c->snapdist = 0; + c->ngroups = 10; + c->nameqlen = 5; TAILQ_INIT(&c->ignoreq); TAILQ_INIT(&c->cmdq); - TAILQ_INIT(&c->keybindingq); + TAILQ_INIT(&c->keybindq); TAILQ_INIT(&c->autogroupq); - TAILQ_INIT(&c->mousebindingq); + TAILQ_INIT(&c->mousebindq); for (i = 0; i < nitems(kbd_binds); i++) conf_bind_kbd(c, kbd_binds[i].key, kbd_binds[i].func); @@ -279,16 +283,17 @@ conf_init(struct conf *c) (void)snprintf(c->known_hosts, sizeof(c->known_hosts), "%s/%s", homedir, ".ssh/known_hosts"); - c->font = xstrdup(CONF_FONT); + c->font = xstrdup("sans-serif:pixelsize=14:bold"); + c->wmname = xstrdup("CWM"); } void conf_clear(struct conf *c) { - struct autogroupwin *aw; - struct binding *kb, *mb; + struct autogroup *ag; + struct bind_ctx *kb, *mb; struct winname *wn; - struct cmd *cmd; + struct cmd_ctx *cmd; int i; while ((cmd = TAILQ_FIRST(&c->cmdq)) != NULL) { @@ -297,16 +302,16 @@ conf_clear(struct conf *c) free(cmd); } - while ((kb = TAILQ_FIRST(&c->keybindingq)) != NULL) { - TAILQ_REMOVE(&c->keybindingq, kb, entry); + while ((kb = TAILQ_FIRST(&c->keybindq)) != NULL) { + TAILQ_REMOVE(&c->keybindq, kb, entry); free(kb); } - while ((aw = TAILQ_FIRST(&c->autogroupq)) != NULL) { - TAILQ_REMOVE(&c->autogroupq, aw, entry); - free(aw->class); - free(aw->name); - free(aw); + while ((ag = TAILQ_FIRST(&c->autogroupq)) != NULL) { + TAILQ_REMOVE(&c->autogroupq, ag, entry); + free(ag->class); + free(ag->name); + free(ag); } while ((wn = TAILQ_FIRST(&c->ignoreq)) != NULL) { @@ -315,8 +320,8 @@ conf_clear(struct conf *c) free(wn); } - while ((mb = TAILQ_FIRST(&c->mousebindingq)) != NULL) { - TAILQ_REMOVE(&c->mousebindingq, mb, entry); + while ((mb = TAILQ_FIRST(&c->mousebindq)) != NULL) { + TAILQ_REMOVE(&c->mousebindq, mb, entry); free(mb); } @@ -324,6 +329,7 @@ conf_clear(struct conf *c) free(c->color[i]); free(c->font); + free(c->wmname); } void @@ -345,149 +351,133 @@ conf_client(struct client_ctx *cc) static const struct { const char *tag; - void (*handler)(struct client_ctx *, union arg *); + void (*handler)(void *, union arg *, enum xev); int context; union arg argument; } name_to_func[] = { - { "lower", kbfunc_client_lower, CWM_CONTEXT_CLIENT, {0} }, - { "raise", kbfunc_client_raise, CWM_CONTEXT_CLIENT, {0} }, - { "search", kbfunc_menu_client, CWM_CONTEXT_SCREEN, {0} }, - { "menusearch", kbfunc_menu_cmd, CWM_CONTEXT_SCREEN, {0} }, - { "groupsearch", kbfunc_menu_group, CWM_CONTEXT_SCREEN, {0} }, - { "hide", kbfunc_client_hide, CWM_CONTEXT_CLIENT, {0} }, - { "cycle", kbfunc_client_cycle, CWM_CONTEXT_SCREEN, - {.i = CWM_CLIENT_CYCLE} }, - { "rcycle", kbfunc_client_cycle, CWM_CONTEXT_SCREEN, - {.i = CWM_CLIENT_RCYCLE} }, - { "label", kbfunc_client_label, CWM_CONTEXT_CLIENT, {0} }, - { "delete", kbfunc_client_delete, CWM_CONTEXT_CLIENT, {0} }, - { "group1", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 1} }, - { "group2", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 2} }, - { "group3", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 3} }, - { "group4", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 4} }, - { "group5", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 5} }, - { "group6", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 6} }, - { "group7", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 7} }, - { "group8", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 8} }, - { "group9", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 9} }, - { "grouponly1", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 1} }, - { "grouponly2", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 2} }, - { "grouponly3", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 3} }, - { "grouponly4", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 4} }, - { "grouponly5", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 5} }, - { "grouponly6", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 6} }, - { "grouponly7", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 7} }, - { "grouponly8", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 8} }, - { "grouponly9", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 9} }, - { "movetogroup1", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT, - {.i = 1} }, - { "movetogroup2", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT, - {.i = 2} }, - { "movetogroup3", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT, - {.i = 3} }, - { "movetogroup4", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT, - {.i = 4} }, - { "movetogroup5", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT, - {.i = 5} }, - { "movetogroup6", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT, - {.i = 6} }, - { "movetogroup7", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT, - {.i = 7} }, - { "movetogroup8", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT, - {.i = 8} }, - { "movetogroup9", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT, - {.i = 9} }, - { "nogroup", kbfunc_group_alltoggle, CWM_CONTEXT_SCREEN, {0} }, - { "cyclegroup", kbfunc_group_cycle, CWM_CONTEXT_SCREEN, - {.i = CWM_CLIENT_CYCLE} }, - { "rcyclegroup", kbfunc_group_cycle, CWM_CONTEXT_SCREEN, - {.i = CWM_CLIENT_RCYCLE} }, - { "cycleingroup", kbfunc_client_cycle, CWM_CONTEXT_CLIENT, - {.i = (CWM_CLIENT_CYCLE | CWM_CLIENT_CYCLE_INGRP)} }, - { "rcycleingroup", kbfunc_client_cycle, CWM_CONTEXT_CLIENT, - {.i = (CWM_CLIENT_RCYCLE | CWM_CLIENT_CYCLE_INGRP)} }, - { "grouptoggle", kbfunc_client_grouptoggle, CWM_CONTEXT_CLIENT, - {.i = CWM_KBD}}, - { "stick", kbfunc_client_toggle_sticky, CWM_CONTEXT_CLIENT, {0} }, - { "fullscreen", kbfunc_client_toggle_fullscreen, CWM_CONTEXT_CLIENT, - {0} }, - { "maximize", kbfunc_client_toggle_maximize, CWM_CONTEXT_CLIENT, {0} }, - { "vmaximize", kbfunc_client_toggle_vmaximize, CWM_CONTEXT_CLIENT, - {0} }, - { "hmaximize", kbfunc_client_toggle_hmaximize, CWM_CONTEXT_CLIENT, - {0} }, - { "freeze", kbfunc_client_toggle_freeze, CWM_CONTEXT_CLIENT, {0} }, - { "restart", kbfunc_cwm_status, CWM_CONTEXT_SCREEN, - {.i = CWM_EXEC_WM} }, - { "quit", kbfunc_cwm_status, CWM_CONTEXT_SCREEN, {.i = CWM_QUIT} }, - { "exec", kbfunc_menu_exec, CWM_CONTEXT_SCREEN, {.i = CWM_MENU_EXEC} }, - { "exec_wm", kbfunc_menu_exec, CWM_CONTEXT_SCREEN, + { "lower", kbfunc_client_lower, CWM_CONTEXT_CC, {0} }, + { "raise", kbfunc_client_raise, CWM_CONTEXT_CC, {0} }, + { "search", kbfunc_menu_client, CWM_CONTEXT_SC, {0} }, + { "menusearch", kbfunc_menu_cmd, CWM_CONTEXT_SC, {0} }, + { "groupsearch", kbfunc_menu_group, CWM_CONTEXT_SC, {0} }, + { "hide", kbfunc_client_hide, CWM_CONTEXT_CC, {0} }, + { "cycle", kbfunc_client_cycle, CWM_CONTEXT_SC, + {.i = (CWM_CYCLE_FORWARD)} }, + { "rcycle", kbfunc_client_cycle, CWM_CONTEXT_SC, + {.i = (CWM_CYCLE_REVERSE)} }, + { "label", kbfunc_menu_client_label, CWM_CONTEXT_CC, {0} }, + { "delete", kbfunc_client_delete, CWM_CONTEXT_CC, {0} }, + { "group1", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 1} }, + { "group2", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 2} }, + { "group3", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 3} }, + { "group4", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 4} }, + { "group5", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 5} }, + { "group6", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 6} }, + { "group7", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 7} }, + { "group8", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 8} }, + { "group9", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 9} }, + { "grouponly1", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 1} }, + { "grouponly2", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 2} }, + { "grouponly3", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 3} }, + { "grouponly4", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 4} }, + { "grouponly5", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 5} }, + { "grouponly6", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 6} }, + { "grouponly7", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 7} }, + { "grouponly8", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 8} }, + { "grouponly9", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 9} }, + { "movetogroup1", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 1} }, + { "movetogroup2", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 2} }, + { "movetogroup3", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 3} }, + { "movetogroup4", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 4} }, + { "movetogroup5", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 5} }, + { "movetogroup6", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 6} }, + { "movetogroup7", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 7} }, + { "movetogroup8", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 8} }, + { "movetogroup9", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 9} }, + { "nogroup", kbfunc_group_alltoggle, CWM_CONTEXT_SC, {0} }, + { "cyclegroup", kbfunc_group_cycle, CWM_CONTEXT_SC, + {.i = (CWM_CYCLE_FORWARD)} }, + { "rcyclegroup", kbfunc_group_cycle, CWM_CONTEXT_SC, + {.i = (CWM_CYCLE_REVERSE)} }, + { "cycleingroup", kbfunc_client_cycle, CWM_CONTEXT_SC, + {.i = (CWM_CYCLE_FORWARD | CWM_CYCLE_INGROUP)} }, + { "rcycleingroup", kbfunc_client_cycle, CWM_CONTEXT_SC, + {.i = (CWM_CYCLE_REVERSE | CWM_CYCLE_INGROUP)} }, + { "grouptoggle", kbfunc_client_toggle_group, CWM_CONTEXT_CC, {0} }, + { "stick", kbfunc_client_toggle_sticky, CWM_CONTEXT_CC, {0} }, + { "fullscreen", kbfunc_client_toggle_fullscreen, CWM_CONTEXT_CC, {0} }, + { "maximize", kbfunc_client_toggle_maximize, CWM_CONTEXT_CC, {0} }, + { "vmaximize", kbfunc_client_toggle_vmaximize, CWM_CONTEXT_CC, {0} }, + { "hmaximize", kbfunc_client_toggle_hmaximize, CWM_CONTEXT_CC, {0} }, + { "freeze", kbfunc_client_toggle_freeze, CWM_CONTEXT_CC, {0} }, + { "restart", kbfunc_cwm_status, CWM_CONTEXT_SC, {.i = CWM_EXEC_WM} }, + { "quit", kbfunc_cwm_status, CWM_CONTEXT_SC, {.i = CWM_QUIT} }, + { "exec", kbfunc_menu_exec, CWM_CONTEXT_SC, + {.i = CWM_MENU_EXEC_EXEC} }, + { "exec_wm", kbfunc_menu_exec, CWM_CONTEXT_SC, {.i = CWM_MENU_EXEC_WM} }, - { "ssh", kbfunc_menu_ssh, CWM_CONTEXT_SCREEN, {0} }, - { "terminal", kbfunc_exec_term, CWM_CONTEXT_SCREEN, {0} }, - { "lock", kbfunc_exec_lock, CWM_CONTEXT_SCREEN, {0} }, - { "moveup", kbfunc_client_move, CWM_CONTEXT_CLIENT, + { "ssh", kbfunc_menu_ssh, CWM_CONTEXT_SC, {0} }, + { "terminal", kbfunc_exec_term, CWM_CONTEXT_SC, {0} }, + { "lock", kbfunc_exec_lock, CWM_CONTEXT_SC, {0} }, + { "moveup", kbfunc_client_move, CWM_CONTEXT_CC, {.i = (CWM_UP)} }, - { "movedown", kbfunc_client_move, CWM_CONTEXT_CLIENT, + { "movedown", kbfunc_client_move, CWM_CONTEXT_CC, {.i = (CWM_DOWN)} }, - { "moveright", kbfunc_client_move, CWM_CONTEXT_CLIENT, + { "moveright", kbfunc_client_move, CWM_CONTEXT_CC, {.i = (CWM_RIGHT)} }, - { "moveleft", kbfunc_client_move, CWM_CONTEXT_CLIENT, + { "moveleft", kbfunc_client_move, CWM_CONTEXT_CC, {.i = (CWM_LEFT)} }, - { "bigmoveup", kbfunc_client_move, CWM_CONTEXT_CLIENT, + { "bigmoveup", kbfunc_client_move, CWM_CONTEXT_CC, {.i = (CWM_UP | CWM_BIGAMOUNT)} }, - { "bigmovedown", kbfunc_client_move, CWM_CONTEXT_CLIENT, + { "bigmovedown", kbfunc_client_move, CWM_CONTEXT_CC, {.i = (CWM_DOWN | CWM_BIGAMOUNT)} }, - { "bigmoveright", kbfunc_client_move, CWM_CONTEXT_CLIENT, + { "bigmoveright", kbfunc_client_move, CWM_CONTEXT_CC, {.i = (CWM_RIGHT | CWM_BIGAMOUNT)} }, - { "bigmoveleft", kbfunc_client_move, CWM_CONTEXT_CLIENT, + { "bigmoveleft", kbfunc_client_move, CWM_CONTEXT_CC, {.i = (CWM_LEFT | CWM_BIGAMOUNT)} }, - { "resizeup", kbfunc_client_resize, CWM_CONTEXT_CLIENT, + { "resizeup", kbfunc_client_resize, CWM_CONTEXT_CC, {.i = (CWM_UP)} }, - { "resizedown", kbfunc_client_resize, CWM_CONTEXT_CLIENT, + { "resizedown", kbfunc_client_resize, CWM_CONTEXT_CC, {.i = (CWM_DOWN)} }, - { "resizeright", kbfunc_client_resize, CWM_CONTEXT_CLIENT, + { "resizeright", kbfunc_client_resize, CWM_CONTEXT_CC, {.i = (CWM_RIGHT)} }, - { "resizeleft", kbfunc_client_resize, CWM_CONTEXT_CLIENT, + { "resizeleft", kbfunc_client_resize, CWM_CONTEXT_CC, {.i = (CWM_LEFT)} }, - { "bigresizeup", kbfunc_client_resize, CWM_CONTEXT_CLIENT, + { "bigresizeup", kbfunc_client_resize, CWM_CONTEXT_CC, {.i = (CWM_UP | CWM_BIGAMOUNT)} }, - { "bigresizedown", kbfunc_client_resize, CWM_CONTEXT_CLIENT, + { "bigresizedown", kbfunc_client_resize, CWM_CONTEXT_CC, {.i = (CWM_DOWN | CWM_BIGAMOUNT)} }, - { "bigresizeright", kbfunc_client_resize, CWM_CONTEXT_CLIENT, + { "bigresizeright", kbfunc_client_resize, CWM_CONTEXT_CC, {.i = (CWM_RIGHT | CWM_BIGAMOUNT)} }, - { "bigresizeleft", kbfunc_client_resize, CWM_CONTEXT_CLIENT, + { "bigresizeleft", kbfunc_client_resize, CWM_CONTEXT_CC, {.i = (CWM_LEFT | CWM_BIGAMOUNT)} }, - { "ptrmoveup", kbfunc_ptrmove, CWM_CONTEXT_SCREEN, + { "ptrmoveup", kbfunc_ptrmove, CWM_CONTEXT_SC, {.i = (CWM_UP)} }, - { "ptrmovedown", kbfunc_ptrmove, CWM_CONTEXT_SCREEN, + { "ptrmovedown", kbfunc_ptrmove, CWM_CONTEXT_SC, {.i = (CWM_DOWN)} }, - { "ptrmoveleft", kbfunc_ptrmove, CWM_CONTEXT_SCREEN, + { "ptrmoveleft", kbfunc_ptrmove, CWM_CONTEXT_SC, {.i = (CWM_LEFT)} }, - { "ptrmoveright", kbfunc_ptrmove, CWM_CONTEXT_SCREEN, + { "ptrmoveright", kbfunc_ptrmove, CWM_CONTEXT_SC, {.i = (CWM_RIGHT)} }, - { "bigptrmoveup", kbfunc_ptrmove, CWM_CONTEXT_SCREEN, + { "bigptrmoveup", kbfunc_ptrmove, CWM_CONTEXT_SC, {.i = (CWM_UP | CWM_BIGAMOUNT)} }, - { "bigptrmovedown", kbfunc_ptrmove, CWM_CONTEXT_SCREEN, + { "bigptrmovedown", kbfunc_ptrmove, CWM_CONTEXT_SC, {.i = (CWM_DOWN | CWM_BIGAMOUNT)} }, - { "bigptrmoveleft", kbfunc_ptrmove, CWM_CONTEXT_SCREEN, + { "bigptrmoveleft", kbfunc_ptrmove, CWM_CONTEXT_SC, {.i = (CWM_LEFT | CWM_BIGAMOUNT)} }, - { "bigptrmoveright", kbfunc_ptrmove, CWM_CONTEXT_SCREEN, + { "bigptrmoveright", kbfunc_ptrmove, CWM_CONTEXT_SC, {.i = (CWM_RIGHT | CWM_BIGAMOUNT)} }, - { "htile", kbfunc_client_tile, CWM_CONTEXT_CLIENT, - {.i = CWM_CLIENT_TILE_HORIZ} }, - { "vtile", kbfunc_client_tile, CWM_CONTEXT_CLIENT, - {.i = CWM_CLIENT_TILE_VERT} }, - { "window_lower", kbfunc_client_lower, CWM_CONTEXT_CLIENT, {0} }, - { "window_raise", kbfunc_client_raise, CWM_CONTEXT_CLIENT, {0} }, - { "window_hide", kbfunc_client_hide, CWM_CONTEXT_CLIENT, {0} }, - { "window_move", mousefunc_client_move, CWM_CONTEXT_CLIENT, {0} }, - { "window_resize", mousefunc_client_resize, CWM_CONTEXT_CLIENT, {0} }, - { "window_grouptoggle", kbfunc_client_grouptoggle, CWM_CONTEXT_CLIENT, - {.i = CWM_MOUSE} }, - { "menu_group", mousefunc_menu_group, CWM_CONTEXT_SCREEN, {0} }, - { "menu_unhide", mousefunc_menu_client, CWM_CONTEXT_SCREEN, {0} }, - { "menu_cmd", mousefunc_menu_cmd, CWM_CONTEXT_SCREEN, {0} }, + { "htile", kbfunc_client_htile, CWM_CONTEXT_CC, {0} }, + { "vtile", kbfunc_client_vtile, CWM_CONTEXT_CC, {0} }, + { "window_lower", kbfunc_client_lower, CWM_CONTEXT_CC, {0} }, + { "window_raise", kbfunc_client_raise, CWM_CONTEXT_CC, {0} }, + { "window_hide", kbfunc_client_hide, CWM_CONTEXT_CC, {0} }, + { "window_move", mousefunc_client_move, CWM_CONTEXT_CC, {0} }, + { "window_resize", mousefunc_client_resize, CWM_CONTEXT_CC, {0} }, + { "window_grouptoggle", kbfunc_client_toggle_group, CWM_CONTEXT_CC, {0} }, + { "menu_group", kbfunc_menu_group, CWM_CONTEXT_SC, {0} }, + { "menu_unhide", kbfunc_menu_client, CWM_CONTEXT_SC, {0} }, + { "menu_cmd", kbfunc_menu_cmd, CWM_CONTEXT_SC, {0} }, }; static const struct { @@ -522,7 +512,7 @@ conf_bind_getmask(const char *name, unsigned int *mask) int conf_bind_kbd(struct conf *c, const char *bind, const char *cmd) { - struct binding *kb; + struct bind_ctx *kb; const char *key; unsigned int i; @@ -551,28 +541,28 @@ conf_bind_kbd(struct conf *c, const char *bind, const char *cmd) kb->callback = name_to_func[i].handler; kb->context = name_to_func[i].context; kb->argument = name_to_func[i].argument; - TAILQ_INSERT_TAIL(&c->keybindingq, kb, entry); + TAILQ_INSERT_TAIL(&c->keybindq, kb, entry); return(1); } - kb->callback = kbfunc_exec; + kb->callback = kbfunc_exec_cmd; kb->context = CWM_CONTEXT_NONE; kb->argument.c = xstrdup(cmd); - TAILQ_INSERT_TAIL(&c->keybindingq, kb, entry); + TAILQ_INSERT_TAIL(&c->keybindq, kb, entry); return(1); } static void -conf_unbind_kbd(struct conf *c, struct binding *unbind) +conf_unbind_kbd(struct conf *c, struct bind_ctx *unbind) { - struct binding *key = NULL, *keynxt; + struct bind_ctx *key = NULL, *keynxt; - TAILQ_FOREACH_SAFE(key, &c->keybindingq, entry, keynxt) { + TAILQ_FOREACH_SAFE(key, &c->keybindq, entry, keynxt) { if (key->modmask != unbind->modmask) continue; if (key->press.keysym == unbind->press.keysym) { - TAILQ_REMOVE(&c->keybindingq, key, entry); + TAILQ_REMOVE(&c->keybindq, key, entry); if (key->context == CWM_CONTEXT_NONE) free(key->argument.c); free(key); @@ -583,7 +573,7 @@ conf_unbind_kbd(struct conf *c, struct binding *unbind) int conf_bind_mouse(struct conf *c, const char *bind, const char *cmd) { - struct binding *mb; + struct bind_ctx *mb; const char *button, *errstr; unsigned int i; @@ -612,7 +602,7 @@ conf_bind_mouse(struct conf *c, const char *bind, const char *cmd) mb->callback = name_to_func[i].handler; mb->context = name_to_func[i].context; mb->argument = name_to_func[i].argument; - TAILQ_INSERT_TAIL(&c->mousebindingq, mb, entry); + TAILQ_INSERT_TAIL(&c->mousebindq, mb, entry); return(1); } @@ -620,27 +610,26 @@ conf_bind_mouse(struct conf *c, const char *bind, const char *cmd) } static void -conf_unbind_mouse(struct conf *c, struct binding *unbind) +conf_unbind_mouse(struct conf *c, struct bind_ctx *unbind) { - struct binding *mb = NULL, *mbnxt; + struct bind_ctx *mb = NULL, *mbnxt; - TAILQ_FOREACH_SAFE(mb, &c->mousebindingq, entry, mbnxt) { + TAILQ_FOREACH_SAFE(mb, &c->mousebindq, entry, mbnxt) { if (mb->modmask != unbind->modmask) continue; if (mb->press.button == unbind->press.button) { - TAILQ_REMOVE(&c->mousebindingq, mb, entry); + TAILQ_REMOVE(&c->mousebindq, mb, entry); free(mb); } } } static int cursor_binds[] = { - XC_X_cursor, /* CF_DEFAULT */ - XC_fleur, /* CF_MOVE */ XC_left_ptr, /* CF_NORMAL */ - XC_question_arrow, /* CF_QUESTION */ + XC_fleur, /* CF_MOVE */ XC_bottom_right_corner, /* CF_RESIZE */ + XC_question_arrow, /* CF_QUESTION */ }; void @@ -652,28 +641,48 @@ conf_cursor(struct conf *c) c->cursor[i] = XCreateFontCursor(X_Dpy, cursor_binds[i]); } +static unsigned int ign_mods[] = { 0, LockMask, Mod2Mask, Mod2Mask | LockMask }; + void conf_grab_mouse(Window win) { - struct binding *mb; + struct bind_ctx *mb; + unsigned int i; - xu_btn_ungrab(win); + XUngrabButton(X_Dpy, AnyButton, AnyModifier, win); - TAILQ_FOREACH(mb, &Conf.mousebindingq, entry) { - if (mb->context == CWM_CONTEXT_CLIENT) - xu_btn_grab(win, mb->modmask, mb->press.button); + TAILQ_FOREACH(mb, &Conf.mousebindq, entry) { + if (mb->context != CWM_CONTEXT_CC) + continue; + for (i = 0; i < nitems(ign_mods); i++) { + XGrabButton(X_Dpy, mb->press.button, + (mb->modmask | ign_mods[i]), win, False, + BUTTONMASK, GrabModeAsync, GrabModeSync, + None, None); + } } + } void conf_grab_kbd(Window win) { - struct binding *kb; + struct bind_ctx *kb; + KeyCode kc; + unsigned int i; - xu_key_ungrab(win); + XUngrabKey(X_Dpy, AnyKey, AnyModifier, win); - TAILQ_FOREACH(kb, &Conf.keybindingq, entry) - xu_key_grab(win, kb->modmask, kb->press.keysym); + TAILQ_FOREACH(kb, &Conf.keybindq, entry) { + kc = XKeysymToKeycode(X_Dpy, kb->press.keysym); + if ((XkbKeycodeToKeysym(X_Dpy, kc, 0, 0) != kb->press.keysym) && + (XkbKeycodeToKeysym(X_Dpy, kc, 0, 1) == kb->press.keysym)) + kb->modmask |= ShiftMask; + + for (i = 0; i < nitems(ign_mods); i++) + XGrabKey(X_Dpy, kc, (kb->modmask | ign_mods[i]), win, + True, GrabModeAsync, GrabModeAsync); + } } static char *cwmhints[] = { diff --git a/cwm.1 b/cwm.1 index 447b646..68434c3 100644 --- a/cwm.1 +++ b/cwm.1 @@ -96,9 +96,9 @@ Reverse cycle through currently visible windows. .It Ic CM-x Delete current window. .It Ic CM-[n] -Select group n, where n is 1-9. -.It Ic CM-0 -Select all groups. +Toggle visibility of group n, where n is 1-9. +.It Ic CM-a +Toggle visibility of all groups. .It Ic CM-g Toggle group membership of current window. .It Ic M-Right diff --git a/cwmrc.5 b/cwmrc.5 index 19a4152..93f7273 100644 --- a/cwmrc.5 +++ b/cwmrc.5 @@ -266,13 +266,13 @@ Launch .Dq ssh menu. .It group[n] -Select group n, where n is 1-9. +Toggle visibility of group n, where n is 1-9. .It grouponly[n] Like .Ar group[n] but also hides the other groups. .It nogroup -Select all groups. +Toggle visibility of all groups. .It grouptoggle Toggle group membership of current window. .It movetogroup[n] diff --git a/group.c b/group.c index 69d4b92..b585286 100644 --- a/group.c +++ b/group.c @@ -154,8 +154,8 @@ group_movetogroup(struct client_ctx *cc, int idx) struct screen_ctx *sc = cc->sc; struct group_ctx *gc; - if (idx < 0 || idx >= CALMWM_NGROUPS) - errx(1, "group_movetogroup: index out of range (%d)", idx); + if (idx < 0 || idx >= Conf.ngroups) + errx(1, "%s: index out of range (%d)", __func__, idx); TAILQ_FOREACH(gc, &sc->groupq, entry) { if (gc->num == idx) @@ -222,8 +222,8 @@ group_hidetoggle(struct screen_ctx *sc, int idx) { struct group_ctx *gc; - if (idx < 0 || idx >= CALMWM_NGROUPS) - errx(1, "group_hidetoggle: index out of range (%d)", idx); + if (idx < 0 || idx >= Conf.ngroups) + errx(1, "%s: index out of range (%d)", __func__, idx); TAILQ_FOREACH(gc, &sc->groupq, entry) { if (gc->num == idx) @@ -245,8 +245,8 @@ group_only(struct screen_ctx *sc, int idx) { struct group_ctx *gc; - if (idx < 0 || idx >= CALMWM_NGROUPS) - errx(1, "group_only: index out of range (%d)", idx); + if (idx < 0 || idx >= Conf.ngroups) + errx(1, "%s: index out of range (%d)", __func__, idx); TAILQ_FOREACH(gc, &sc->groupq, entry) { if (gc->num == idx) @@ -265,7 +265,7 @@ group_cycle(struct screen_ctx *sc, int flags) newgc = oldgc; for (;;) { - newgc = (flags & CWM_CLIENT_RCYCLE) ? group_prev(newgc) : + newgc = (flags & CWM_CYCLE_REVERSE) ? group_prev(newgc) : group_next(newgc); if (newgc == oldgc) @@ -304,8 +304,8 @@ group_prev(struct group_ctx *gc) struct screen_ctx *sc = gc->sc; struct group_ctx *newgc; - return(((newgc = TAILQ_PREV(gc, group_ctx_q, entry)) != NULL) ? - newgc : TAILQ_LAST(&sc->groupq, group_ctx_q)); + return(((newgc = TAILQ_PREV(gc, group_q, entry)) != NULL) ? + newgc : TAILQ_LAST(&sc->groupq, group_q)); } void @@ -335,7 +335,7 @@ group_restore(struct client_ctx *cc) return(0); num = (*grpnum == -1) ? 0 : *grpnum; - num = MIN(num, (CALMWM_NGROUPS - 1)); + num = MIN(num, (Conf.ngroups - 1)); XFree(grpnum); TAILQ_FOREACH(gc, &sc->groupq, entry) { @@ -351,21 +351,21 @@ int group_autogroup(struct client_ctx *cc) { struct screen_ctx *sc = cc->sc; - struct autogroupwin *aw; + struct autogroup *ag; struct group_ctx *gc; int num = -1, both_match = 0; if (cc->ch.res_class == NULL || cc->ch.res_name == NULL) return(0); - TAILQ_FOREACH(aw, &Conf.autogroupq, entry) { - if (strcmp(aw->class, cc->ch.res_class) == 0) { - if ((aw->name != NULL) && - (strcmp(aw->name, cc->ch.res_name) == 0)) { - num = aw->num; + TAILQ_FOREACH(ag, &Conf.autogroupq, entry) { + if (strcmp(ag->class, cc->ch.res_class) == 0) { + if ((ag->name != NULL) && + (strcmp(ag->name, cc->ch.res_name) == 0)) { + num = ag->num; both_match = 1; - } else if (aw->name == NULL && !both_match) - num = aw->num; + } else if (ag->name == NULL && !both_match) + num = ag->num; } } diff --git a/kbfunc.c b/kbfunc.c index 715c682..5f5a163 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -41,16 +41,9 @@ extern sig_atomic_t cwm_status; static void kbfunc_amount(int, int, unsigned int *, unsigned int *); void -kbfunc_client_lower(struct client_ctx *cc, union arg *arg) +kbfunc_cwm_status(void *ctx, union arg *arg, enum xev xev) { - client_ptrsave(cc); - client_lower(cc); -} - -void -kbfunc_client_raise(struct client_ctx *cc, union arg *arg) -{ - client_raise(cc); + cwm_status = arg->i; } static void @@ -78,9 +71,9 @@ kbfunc_amount(int flags, int amt, unsigned int *mx, unsigned int *my) } void -kbfunc_ptrmove(struct client_ctx *cc, union arg *arg) +kbfunc_ptrmove(void *ctx, union arg *arg, enum xev xev) { - struct screen_ctx *sc = cc->sc; + struct screen_ctx *sc = ctx; int x, y; unsigned int mx = 0, my = 0; @@ -91,16 +84,29 @@ kbfunc_ptrmove(struct client_ctx *cc, union arg *arg) } void -kbfunc_client_move(struct client_ctx *cc, union arg *arg) +kbfunc_client_move(void *ctx, union arg *arg, enum xev xev) { + struct client_ctx *cc = ctx; struct screen_ctx *sc = cc->sc; struct geom area; - int x, y; + int x, y, px, py; unsigned int mx = 0, my = 0; if (cc->flags & CLIENT_FREEZE) return; + xu_ptr_getpos(cc->win, &px, &py); + if (px < 0) + px = 0; + else if (px > cc->geom.w) + px = cc->geom.w; + if (py < 0) + py = 0; + else if (py > cc->geom.h) + py = cc->geom.h; + + xu_ptr_setpos(cc->win, px, py); + kbfunc_amount(arg->i, Conf.mamount, &mx, &my); cc->geom.x += mx; @@ -132,8 +138,9 @@ kbfunc_client_move(struct client_ctx *cc, union arg *arg) } void -kbfunc_client_resize(struct client_ctx *cc, union arg *arg) +kbfunc_client_resize(void *ctx, union arg *arg, enum xev xev) { + struct client_ctx *cc = ctx; unsigned int mx = 0, my = 0; int amt = 1; @@ -161,24 +168,157 @@ kbfunc_client_resize(struct client_ctx *cc, union arg *arg) } void -kbfunc_menu_client(struct client_ctx *cc, union arg *arg) +kbfunc_client_delete(void *ctx, union arg *arg, enum xev xev) { - struct screen_ctx *sc = cc->sc; - struct client_ctx *old_cc; + client_send_delete(ctx); +} + +void +kbfunc_client_lower(void *ctx, union arg *arg, enum xev xev) +{ + client_ptrsave(ctx); + client_lower(ctx); +} + +void +kbfunc_client_raise(void *ctx, union arg *arg, enum xev xev) +{ + client_raise(ctx); +} + +void +kbfunc_client_hide(void *ctx, union arg *arg, enum xev xev) +{ + client_hide(ctx); +} + +void +kbfunc_client_toggle_freeze(void *ctx, union arg *arg, enum xev xev) +{ + client_toggle_freeze(ctx); +} + +void +kbfunc_client_toggle_sticky(void *ctx, union arg *arg, enum xev xev) +{ + client_toggle_sticky(ctx); +} + +void +kbfunc_client_toggle_fullscreen(void *ctx, union arg *arg, enum xev xev) +{ + client_toggle_fullscreen(ctx); +} + +void +kbfunc_client_toggle_maximize(void *ctx, union arg *arg, enum xev xev) +{ + client_toggle_maximize(ctx); +} + +void +kbfunc_client_toggle_hmaximize(void *ctx, union arg *arg, enum xev xev) +{ + client_toggle_hmaximize(ctx); +} + +void +kbfunc_client_toggle_vmaximize(void *ctx, union arg *arg, enum xev xev) +{ + client_toggle_vmaximize(ctx); +} + +void +kbfunc_client_htile(void *ctx, union arg *arg, enum xev xev) +{ + client_htile(ctx); +} + +void +kbfunc_client_vtile(void *ctx, union arg *arg, enum xev xev) +{ + client_vtile(ctx); +} + +void +kbfunc_client_cycle(void *ctx, union arg *arg, enum xev xev) +{ + client_cycle(ctx, arg->i); +} + +void +kbfunc_client_toggle_group(void *ctx, union arg *arg, enum xev xev) +{ + struct client_ctx *cc = ctx; + + if (xev == CWM_XEV_KEY) { + /* For X apps that steal events. */ + XGrabKeyboard(X_Dpy, cc->win, True, + GrabModeAsync, GrabModeAsync, CurrentTime); + } + + group_toggle_membership_enter(cc); +} + +void +kbfunc_client_movetogroup(void *ctx, union arg *arg, enum xev xev) +{ + group_movetogroup(ctx, arg->i); +} + +void +kbfunc_group_toggle(void *ctx, union arg *arg, enum xev xev) +{ + group_hidetoggle(ctx, arg->i); +} + +void +kbfunc_group_only(void *ctx, union arg *arg, enum xev xev) +{ + group_only(ctx, arg->i); +} + +void +kbfunc_group_cycle(void *ctx, union arg *arg, enum xev xev) +{ + group_cycle(ctx, arg->i); +} + +void +kbfunc_group_alltoggle(void *ctx, union arg *arg, enum xev xev) +{ + group_alltoggle(ctx); +} + +void +kbfunc_menu_client(void *ctx, union arg *arg, enum xev xev) +{ + struct screen_ctx *sc = ctx; + struct client_ctx *cc, *old_cc; struct menu *mi; struct menu_q menuq; + int m = (xev == CWM_XEV_BTN); old_cc = client_current(); TAILQ_INIT(&menuq); - TAILQ_FOREACH(cc, &sc->clientq, entry) - menuq_add(&menuq, cc, NULL); + TAILQ_FOREACH(cc, &sc->clientq, entry) { + if (m) { + if (cc->flags & CLIENT_HIDDEN) + menuq_add(&menuq, cc, NULL); + } else + menuq_add(&menuq, cc, NULL); + } - if ((mi = menu_filter(sc, &menuq, "window", NULL, 0, + if ((mi = menu_filter(sc, &menuq, + (m) ? NULL : "window", NULL, + ((m) ? CWM_MENU_LIST : 0), search_match_client, search_print_client)) != NULL) { cc = (struct client_ctx *)mi->ctx; if (cc->flags & CLIENT_HIDDEN) client_unhide(cc); + else + client_raise(cc); if (old_cc) client_ptrsave(old_cc); client_ptrwarp(cc); @@ -188,12 +328,13 @@ kbfunc_menu_client(struct client_ctx *cc, union arg *arg) } void -kbfunc_menu_cmd(struct client_ctx *cc, union arg *arg) +kbfunc_menu_cmd(void *ctx, union arg *arg, enum xev xev) { - struct screen_ctx *sc = cc->sc; - struct cmd *cmd; + struct screen_ctx *sc = ctx; + struct cmd_ctx *cmd; struct menu *mi; struct menu_q menuq; + int m = (xev == CWM_XEV_BTN); TAILQ_INIT(&menuq); TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { @@ -204,20 +345,25 @@ kbfunc_menu_cmd(struct client_ctx *cc, union arg *arg) menuq_add(&menuq, cmd, "%s", cmd->name); } - if ((mi = menu_filter(sc, &menuq, "application", NULL, 0, - search_match_text, search_print_cmd)) != NULL) - u_spawn(((struct cmd *)mi->ctx)->path); + if ((mi = menu_filter(sc, &menuq, + (m) ? NULL : "application", NULL, + ((m) ? CWM_MENU_LIST : 0), + search_match_text, search_print_cmd)) != NULL) { + cmd = (struct cmd_ctx *)mi->ctx; + u_spawn(cmd->path); + } menuq_clear(&menuq); } void -kbfunc_menu_group(struct client_ctx *cc, union arg *arg) +kbfunc_menu_group(void *ctx, union arg *arg, enum xev xev) { - struct screen_ctx *sc = cc->sc; + struct screen_ctx *sc = ctx; struct group_ctx *gc; struct menu *mi; struct menu_q menuq; + int m = (xev == CWM_XEV_BTN); TAILQ_INIT(&menuq); TAILQ_FOREACH(gc, &sc->groupq, entry) { @@ -226,7 +372,8 @@ kbfunc_menu_group(struct client_ctx *cc, union arg *arg) menuq_add(&menuq, gc, "%d %s", gc->num, gc->name); } - if ((mi = menu_filter(sc, &menuq, "group", NULL, CWM_MENU_LIST, + if ((mi = menu_filter(sc, &menuq, + (m) ? NULL : "group", NULL, (CWM_MENU_LIST), search_match_text, search_print_group)) != NULL) { gc = (struct group_ctx *)mi->ctx; (group_holds_only_hidden(gc)) ? @@ -237,50 +384,10 @@ kbfunc_menu_group(struct client_ctx *cc, union arg *arg) } void -kbfunc_client_cycle(struct client_ctx *cc, union arg *arg) -{ - client_cycle(cc->sc, arg->i); -} - -void -kbfunc_client_hide(struct client_ctx *cc, union arg *arg) -{ - client_hide(cc); -} - -void -kbfunc_exec(struct client_ctx *cc, union arg *arg) -{ - u_spawn(arg->c); -} - -void -kbfunc_exec_term(struct client_ctx *cc, union arg *arg) -{ - struct cmd *cmd; - - TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { - if (strcmp(cmd->name, "term") == 0) - u_spawn(cmd->path); - } -} - -void -kbfunc_exec_lock(struct client_ctx *cc, union arg *arg) -{ - struct cmd *cmd; - - TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { - if (strcmp(cmd->name, "lock") == 0) - u_spawn(cmd->path); - } -} - -void -kbfunc_menu_exec(struct client_ctx *cc, union arg *arg) +kbfunc_menu_exec(void *ctx, union arg *arg, enum xev xev) { #define NPATHS 256 - struct screen_ctx *sc = cc->sc; + struct screen_ctx *sc = ctx; char **ap, *paths[NPATHS], *path, *pathcpy; char tpath[PATH_MAX]; const char *label; @@ -292,15 +399,15 @@ kbfunc_menu_exec(struct client_ctx *cc, union arg *arg) struct stat sb; switch (cmd) { - case CWM_MENU_EXEC: + case CWM_MENU_EXEC_EXEC: label = "exec"; break; case CWM_MENU_EXEC_WM: label = "wm"; break; default: - errx(1, "kbfunc_menu_exec: invalid cmd %d", cmd); - /*NOTREACHED*/ + errx(1, "%s: invalid cmd %d", __func__, cmd); + /* NOTREACHED */ } TAILQ_INIT(&menuq); @@ -341,22 +448,22 @@ kbfunc_menu_exec(struct client_ctx *cc, union arg *arg) free(path); if ((mi = menu_filter(sc, &menuq, label, NULL, - CWM_MENU_DUMMY | CWM_MENU_FILE, + (CWM_MENU_DUMMY | CWM_MENU_FILE), search_match_exec_path, NULL)) != NULL) { if (mi->text[0] == '\0') goto out; switch (cmd) { - case CWM_MENU_EXEC: + case CWM_MENU_EXEC_EXEC: u_spawn(mi->text); break; case CWM_MENU_EXEC_WM: cwm_status = CWM_EXEC_WM; - free(wm_argv); - wm_argv = xstrdup(mi->text); + free(Conf.wm_argv); + Conf.wm_argv = xstrdup(mi->text); break; default: - errx(1, "kb_func: egad, cmd changed value!"); - break; + errx(1, "%s: egad, cmd changed value!", __func__); + /* NOTREACHED */ } } out: @@ -366,10 +473,10 @@ out: } void -kbfunc_menu_ssh(struct client_ctx *cc, union arg *arg) +kbfunc_menu_ssh(void *ctx, union arg *arg, enum xev xev) { - struct screen_ctx *sc = cc->sc; - struct cmd *cmd; + struct screen_ctx *sc = ctx; + struct cmd_ctx *cmd; struct menu *mi; struct menu_q menuq; FILE *fp; @@ -386,7 +493,7 @@ kbfunc_menu_ssh(struct client_ctx *cc, union arg *arg) TAILQ_INIT(&menuq); if ((fp = fopen(Conf.known_hosts, "r")) == NULL) { - warn("kbfunc_menu_ssh: %s", Conf.known_hosts); + warn("%s: %s", __func__, Conf.known_hosts); goto menu; } @@ -416,7 +523,7 @@ kbfunc_menu_ssh(struct client_ctx *cc, union arg *arg) free(lbuf); (void)fclose(fp); menu: - if ((mi = menu_filter(sc, &menuq, "ssh", NULL, CWM_MENU_DUMMY, + if ((mi = menu_filter(sc, &menuq, "ssh", NULL, (CWM_MENU_DUMMY), search_match_exec, NULL)) != NULL) { if (mi->text[0] == '\0') goto out; @@ -433,15 +540,16 @@ out: } void -kbfunc_client_label(struct client_ctx *cc, union arg *arg) +kbfunc_menu_client_label(void *ctx, union arg *arg, enum xev xev) { - struct menu *mi; - struct menu_q menuq; + struct client_ctx *cc = ctx; + struct menu *mi; + struct menu_q menuq; TAILQ_INIT(&menuq); /* dummy is set, so this will always return */ - mi = menu_filter(cc->sc, &menuq, "label", cc->label, CWM_MENU_DUMMY, + mi = menu_filter(cc->sc, &menuq, "label", cc->label, (CWM_MENU_DUMMY), search_match_text, NULL); if (!mi->abort) { @@ -452,104 +560,29 @@ kbfunc_client_label(struct client_ctx *cc, union arg *arg) } void -kbfunc_client_delete(struct client_ctx *cc, union arg *arg) +kbfunc_exec_cmd(void *ctx, union arg *arg, enum xev xev) { - client_send_delete(cc); + u_spawn(arg->c); } void -kbfunc_group_toggle(struct client_ctx *cc, union arg *arg) +kbfunc_exec_term(void *ctx, union arg *arg, enum xev xev) { - group_hidetoggle(cc->sc, arg->i); -} + struct cmd_ctx *cmd; -void -kbfunc_group_only(struct client_ctx *cc, union arg *arg) -{ - group_only(cc->sc, arg->i); -} - -void -kbfunc_group_cycle(struct client_ctx *cc, union arg *arg) -{ - group_cycle(cc->sc, arg->i); -} - -void -kbfunc_group_alltoggle(struct client_ctx *cc, union arg *arg) -{ - group_alltoggle(cc->sc); -} - -void -kbfunc_client_grouptoggle(struct client_ctx *cc, union arg *arg) -{ - if (arg->i == CWM_KBD) { - /* For X apps that steal events. */ - XGrabKeyboard(X_Dpy, cc->win, True, - GrabModeAsync, GrabModeAsync, CurrentTime); - } - - group_toggle_membership_enter(cc); -} - -void -kbfunc_client_movetogroup(struct client_ctx *cc, union arg *arg) -{ - group_movetogroup(cc, arg->i); -} - -void -kbfunc_client_toggle_sticky(struct client_ctx *cc, union arg *arg) -{ - client_toggle_sticky(cc); -} - -void -kbfunc_client_toggle_fullscreen(struct client_ctx *cc, union arg *arg) -{ - client_toggle_fullscreen(cc); -} - -void -kbfunc_client_toggle_maximize(struct client_ctx *cc, union arg *arg) -{ - client_toggle_maximize(cc); -} - -void -kbfunc_client_toggle_vmaximize(struct client_ctx *cc, union arg *arg) -{ - client_toggle_vmaximize(cc); -} - -void -kbfunc_client_toggle_hmaximize(struct client_ctx *cc, union arg *arg) -{ - client_toggle_hmaximize(cc); -} - -void -kbfunc_client_toggle_freeze(struct client_ctx *cc, union arg *arg) -{ - client_toggle_freeze(cc); -} - -void -kbfunc_cwm_status(struct client_ctx *cc, union arg *arg) -{ - cwm_status = arg->i; -} - -void -kbfunc_client_tile(struct client_ctx *cc, union arg *arg) -{ - switch (arg->i) { - case CWM_CLIENT_TILE_HORIZ: - client_htile(cc); - break; - case CWM_CLIENT_TILE_VERT: - client_vtile(cc); - break; + TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { + if (strcmp(cmd->name, "term") == 0) + u_spawn(cmd->path); + } +} + +void +kbfunc_exec_lock(void *ctx, union arg *arg, enum xev xev) +{ + struct cmd_ctx *cmd; + + TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { + if (strcmp(cmd->name, "lock") == 0) + u_spawn(cmd->path); } } diff --git a/menu.c b/menu.c index f85d96d..44f76da 100644 --- a/menu.c +++ b/menu.c @@ -63,10 +63,10 @@ struct menu_ctx { }; static struct menu *menu_handle_key(XEvent *, struct menu_ctx *, struct menu_q *, struct menu_q *); -static void menu_handle_move(XEvent *, struct menu_ctx *, - struct menu_q *); -static struct menu *menu_handle_release(XEvent *, struct menu_ctx *, - struct menu_q *); +static void menu_handle_move(struct menu_ctx *, + struct menu_q *, int, int); +static struct menu *menu_handle_release(struct menu_ctx *, + struct menu_q *, int, int); static void menu_draw(struct menu_ctx *, struct menu_q *, struct menu_q *); static void menu_draw_entry(struct menu_ctx *, struct menu_q *, @@ -118,26 +118,28 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt, mc.hasprompt = 1; } - XSelectInput(X_Dpy, sc->menuwin, evmask); - XMapRaised(X_Dpy, sc->menuwin); + XSelectInput(X_Dpy, sc->menu.win, evmask); + XMapRaised(X_Dpy, sc->menu.win); - if (xu_ptr_grab(sc->menuwin, MENUGRABMASK, - Conf.cursor[CF_QUESTION]) < 0) { - XUnmapWindow(X_Dpy, sc->menuwin); + if (XGrabPointer(X_Dpy, sc->menu.win, False, MENUGRABMASK, + GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_QUESTION], + CurrentTime) != GrabSuccess) { + XUnmapWindow(X_Dpy, sc->menu.win); return(NULL); + } XGetInputFocus(X_Dpy, &focuswin, &focusrevert); - XSetInputFocus(X_Dpy, sc->menuwin, RevertToPointerRoot, CurrentTime); + XSetInputFocus(X_Dpy, sc->menu.win, RevertToPointerRoot, CurrentTime); /* make sure keybindings don't remove keys from the menu stream */ - XGrabKeyboard(X_Dpy, sc->menuwin, True, + XGrabKeyboard(X_Dpy, sc->menu.win, True, GrabModeAsync, GrabModeAsync, CurrentTime); for (;;) { mc.changed = 0; - XWindowEvent(X_Dpy, sc->menuwin, evmask, &e); + XWindowEvent(X_Dpy, sc->menu.win, evmask, &e); switch (e.type) { case KeyPress: @@ -149,11 +151,12 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt, menu_draw(&mc, menuq, &resultq); break; case MotionNotify: - menu_handle_move(&e, &mc, &resultq); + menu_handle_move(&mc, &resultq, + e.xbutton.x, e.xbutton.y); break; case ButtonRelease: - if ((mi = menu_handle_release(&e, &mc, &resultq)) - != NULL) + if ((mi = menu_handle_release(&mc, &resultq, + e.xbutton.x, e.xbutton.y)) != NULL) goto out; break; default: @@ -172,10 +175,10 @@ out: xu_ptr_getpos(sc->rootwin, &xcur, &ycur); if (xcur == mc.geom.x && ycur == mc.geom.y) xu_ptr_setpos(sc->rootwin, xsave, ysave); - xu_ptr_ungrab(); + XUngrabPointer(X_Dpy, CurrentTime); - XMoveResizeWindow(X_Dpy, sc->menuwin, 0, 0, 1, 1); - XUnmapWindow(X_Dpy, sc->menuwin); + XMoveResizeWindow(X_Dpy, sc->menu.win, 0, 0, 1, 1); + XUnmapWindow(X_Dpy, sc->menu.win); XUngrabKeyboard(X_Dpy, CurrentTime); return(mi); @@ -193,7 +196,7 @@ menu_complete_path(struct menu_ctx *mc) TAILQ_INIT(&menuq); if ((mi = menu_filter(sc, &menuq, mc->searchstr, NULL, - CWM_MENU_DUMMY, search_match_path_any, NULL)) != NULL) { + (CWM_MENU_DUMMY), search_match_path_any, NULL)) != NULL) { mr->abort = mi->abort; mr->dummy = mi->dummy; if (mi->text[0] != '\0') @@ -334,6 +337,7 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq) struct menu *mi; struct geom area; int n, xsave, ysave; + XGlyphInfo extents; if (mc->list) { if (TAILQ_EMPTY(resultq)) { @@ -352,8 +356,11 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq) if (mc->hasprompt) { (void)snprintf(mc->dispstr, sizeof(mc->dispstr), "%s%s%s%s", mc->promptstr, PROMPT_SCHAR, mc->searchstr, PROMPT_ECHAR); - mc->geom.w = xu_xft_width(sc->xftfont, mc->dispstr, - strlen(mc->dispstr)); + + XftTextExtentsUtf8(X_Dpy, sc->xftfont, + (const FcChar8*)mc->dispstr, strlen(mc->dispstr), &extents); + + mc->geom.w = extents.xOff; mc->geom.h = sc->xftfont->height + 1; mc->num = 1; } @@ -365,8 +372,11 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq) (void)snprintf(mi->print, sizeof(mi->print), "%s", mi->text); - mc->geom.w = MAX(mc->geom.w, xu_xft_width(sc->xftfont, - mi->print, MIN(strlen(mi->print), MENU_MAXENTRY))); + XftTextExtentsUtf8(X_Dpy, sc->xftfont, + (const FcChar8*)mi->print, + MIN(strlen(mi->print), MENU_MAXENTRY), &extents); + + mc->geom.w = MAX(mc->geom.w, extents.xOff); mc->geom.h += sc->xftfont->height + 1; mc->num++; } @@ -395,16 +405,18 @@ 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); - XClearWindow(X_Dpy, sc->menuwin); - XMoveResizeWindow(X_Dpy, sc->menuwin, mc->geom.x, mc->geom.y, + XClearWindow(X_Dpy, sc->menu.win); + XMoveResizeWindow(X_Dpy, sc->menu.win, mc->geom.x, mc->geom.y, mc->geom.w, mc->geom.h); + n = 0; if (mc->hasprompt) { - xu_xft_draw(sc, mc->dispstr, CWM_COLOR_MENU_FONT, - 0, sc->xftfont->ascent); - n = 1; - } else - n = 0; + XftDrawStringUtf8(sc->menu.xftdraw, + &sc->xftcolor[CWM_COLOR_MENU_FONT], sc->xftfont, + 0, sc->xftfont->ascent, + (const FcChar8*)mc->dispstr, strlen(mc->dispstr)); + n++; + } TAILQ_FOREACH(mi, resultq, resultentry) { int y = n * (sc->xftfont->height + 1) + sc->xftfont->ascent + 1; @@ -413,7 +425,10 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq) if (mc->geom.y + y > area.h) break; - xu_xft_draw(sc, mi->print, CWM_COLOR_MENU_FONT, 0, y); + XftDrawStringUtf8(sc->menu.xftdraw, + &sc->xftcolor[CWM_COLOR_MENU_FONT], sc->xftfont, + 0, y, + (const FcChar8*)mi->print, strlen(mi->print)); n++; } if (mc->hasprompt && n > 1) @@ -438,19 +453,21 @@ menu_draw_entry(struct menu_ctx *mc, struct menu_q *resultq, return; color = (active) ? CWM_COLOR_MENU_FG : CWM_COLOR_MENU_BG; - XftDrawRect(sc->xftdraw, &sc->xftcolor[color], 0, + XftDrawRect(sc->menu.xftdraw, &sc->xftcolor[color], 0, (sc->xftfont->height + 1) * entry, mc->geom.w, (sc->xftfont->height + 1) + sc->xftfont->descent); color = (active) ? CWM_COLOR_MENU_FONT_SEL : CWM_COLOR_MENU_FONT; - xu_xft_draw(sc, mi->print, color, - 0, (sc->xftfont->height + 1) * entry + sc->xftfont->ascent + 1); + XftDrawStringUtf8(sc->menu.xftdraw, + &sc->xftcolor[color], sc->xftfont, + 0, (sc->xftfont->height + 1) * entry + sc->xftfont->ascent + 1, + (const FcChar8*)mi->print, strlen(mi->print)); } static void -menu_handle_move(XEvent *e, struct menu_ctx *mc, struct menu_q *resultq) +menu_handle_move(struct menu_ctx *mc, struct menu_q *resultq, int x, int y) { mc->prev = mc->entry; - mc->entry = menu_calc_entry(mc, e->xbutton.x, e->xbutton.y); + mc->entry = menu_calc_entry(mc, x, y); if (mc->prev == mc->entry) return; @@ -458,19 +475,19 @@ menu_handle_move(XEvent *e, struct menu_ctx *mc, struct menu_q *resultq) if (mc->prev != -1) menu_draw_entry(mc, resultq, mc->prev, 0); if (mc->entry != -1) { - (void)xu_ptr_regrab(MENUGRABMASK, Conf.cursor[CF_NORMAL]); + XChangeActivePointerGrab(X_Dpy, MENUGRABMASK, + Conf.cursor[CF_NORMAL], CurrentTime); menu_draw_entry(mc, resultq, mc->entry, 1); - } else - (void)xu_ptr_regrab(MENUGRABMASK, Conf.cursor[CF_DEFAULT]); + } } static struct menu * -menu_handle_release(XEvent *e, struct menu_ctx *mc, struct menu_q *resultq) +menu_handle_release(struct menu_ctx *mc, struct menu_q *resultq, int x, int y) { struct menu *mi; int entry, i = 0; - entry = menu_calc_entry(mc, e->xbutton.x, e->xbutton.y); + entry = menu_calc_entry(mc, x, y); if (mc->hasprompt) i = 1; @@ -510,13 +527,12 @@ static int menu_keycode(XKeyEvent *ev, enum ctltype *ctl, char *chr) { KeySym ks; - unsigned int state = ev->state; *ctl = CTL_NONE; chr[0] = '\0'; ks = XkbKeycodeToKeysym(X_Dpy, ev->keycode, 0, - (state & ShiftMask) ? 1 : 0); + (ev->state & ShiftMask) ? 1 : 0); /* Look for control characters. */ switch (ks) { @@ -541,7 +557,7 @@ menu_keycode(XKeyEvent *ev, enum ctltype *ctl, char *chr) break; } - if (*ctl == CTL_NONE && (state & ControlMask)) { + if (*ctl == CTL_NONE && (ev->state & ControlMask)) { switch (ks) { case XK_s: case XK_S: @@ -565,10 +581,13 @@ menu_keycode(XKeyEvent *ev, enum ctltype *ctl, char *chr) case XK_A: *ctl = CTL_ALL; break; + case XK_bracketleft: + *ctl = CTL_ABORT; + break; } } - if (*ctl == CTL_NONE && (state & Mod1Mask)) { + if (*ctl == CTL_NONE && (ev->state & Mod1Mask)) { switch (ks) { case XK_j: case XK_J: @@ -621,3 +640,35 @@ menuq_clear(struct menu_q *mq) free(mi); } } + +void +menu_windraw(struct screen_ctx *sc, Window win, const char *fmt, ...) +{ + va_list ap; + int i; + char *text; + XGlyphInfo extents; + + va_start(ap, fmt); + i = vasprintf(&text, fmt, ap); + va_end(ap); + + if (i < 0 || text == NULL) + err(1, "vasprintf"); + + XftTextExtentsUtf8(X_Dpy, sc->xftfont, (const FcChar8*)text, + strlen(text), &extents); + + XReparentWindow(X_Dpy, sc->menu.win, win, 0, 0); + XMoveResizeWindow(X_Dpy, sc->menu.win, 0, 0, + extents.xOff, sc->xftfont->height); + XMapWindow(X_Dpy, sc->menu.win); + XClearWindow(X_Dpy, sc->menu.win); + + XftDrawStringUtf8(sc->menu.xftdraw, &sc->xftcolor[CWM_COLOR_MENU_FONT], + sc->xftfont, 0, sc->xftfont->ascent + 1, + (const FcChar8*)text, strlen(text)); + + free(text); +} + diff --git a/mousefunc.c b/mousefunc.c index f55ebff..dbec420 100644 --- a/mousefunc.c +++ b/mousefunc.c @@ -32,28 +32,10 @@ #include "calmwm.h" -static void mousefunc_sweep_draw(struct client_ctx *); - -static void -mousefunc_sweep_draw(struct client_ctx *cc) -{ - struct screen_ctx *sc = cc->sc; - char s[14]; /* fits " nnnn x nnnn \0" */ - - (void)snprintf(s, sizeof(s), " %4d x %-4d ", cc->dim.w, cc->dim.h); - - XReparentWindow(X_Dpy, sc->menuwin, cc->win, 0, 0); - XMoveResizeWindow(X_Dpy, sc->menuwin, 0, 0, - xu_xft_width(sc->xftfont, s, strlen(s)), sc->xftfont->height); - XMapWindow(X_Dpy, sc->menuwin); - XClearWindow(X_Dpy, sc->menuwin); - - xu_xft_draw(sc, s, CWM_COLOR_MENU_FONT, 0, sc->xftfont->ascent + 1); -} - void -mousefunc_client_resize(struct client_ctx *cc, union arg *arg) +mousefunc_client_resize(void *ctx, union arg *arg, enum xev xev) { + struct client_ctx *cc = ctx; XEvent ev; Time ltime = 0; struct screen_ctx *sc = cc->sc; @@ -64,14 +46,15 @@ mousefunc_client_resize(struct client_ctx *cc, union arg *arg) client_raise(cc); client_ptrsave(cc); - if (xu_ptr_grab(cc->win, MOUSEMASK, Conf.cursor[CF_RESIZE]) < 0) + xu_ptr_setpos(cc->win, cc->geom.w, cc->geom.h); + + if (XGrabPointer(X_Dpy, cc->win, False, MOUSEMASK, + GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_RESIZE], + CurrentTime) != GrabSuccess) return; - xu_ptr_setpos(cc->win, cc->geom.w, cc->geom.h); - mousefunc_sweep_draw(cc); - for (;;) { - XMaskEvent(X_Dpy, MOUSEMASK, &ev); + XWindowEvent(X_Dpy, cc->win, MOUSEMASK, &ev); switch (ev.type) { case MotionNotify: @@ -84,13 +67,14 @@ mousefunc_client_resize(struct client_ctx *cc, union arg *arg) cc->geom.h = ev.xmotion.y; client_applysizehints(cc); client_resize(cc, 1); - mousefunc_sweep_draw(cc); + menu_windraw(sc, cc->win, + "%4d x %-4d", cc->dim.w, cc->dim.h); break; case ButtonRelease: client_resize(cc, 1); - XUnmapWindow(X_Dpy, sc->menuwin); - XReparentWindow(X_Dpy, sc->menuwin, sc->rootwin, 0, 0); - xu_ptr_ungrab(); + XUnmapWindow(X_Dpy, sc->menu.win); + XReparentWindow(X_Dpy, sc->menu.win, sc->rootwin, 0, 0); + XUngrabPointer(X_Dpy, CurrentTime); /* Make sure the pointer stays within the window. */ if (cc->ptr.x > cc->geom.w) @@ -105,8 +89,9 @@ mousefunc_client_resize(struct client_ctx *cc, union arg *arg) } void -mousefunc_client_move(struct client_ctx *cc, union arg *arg) +mousefunc_client_move(void *ctx, union arg *arg, enum xev xev) { + struct client_ctx *cc = ctx; XEvent ev; Time ltime = 0; struct screen_ctx *sc = cc->sc; @@ -118,13 +103,25 @@ mousefunc_client_move(struct client_ctx *cc, union arg *arg) if (cc->flags & CLIENT_FREEZE) return; - if (xu_ptr_grab(cc->win, MOUSEMASK, Conf.cursor[CF_MOVE]) < 0) + xu_ptr_getpos(cc->win, &px, &py); + if (px < 0) + px = 0; + else if (px > cc->geom.w) + px = cc->geom.w; + if (py < 0) + py = 0; + else if (py > cc->geom.h) + py = cc->geom.h; + + xu_ptr_setpos(cc->win, px, py); + + if (XGrabPointer(X_Dpy, cc->win, False, MOUSEMASK, + GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_MOVE], + CurrentTime) != GrabSuccess) return; - xu_ptr_getpos(cc->win, &px, &py); - for (;;) { - XMaskEvent(X_Dpy, MOUSEMASK, &ev); + XWindowEvent(X_Dpy, cc->win, MOUSEMASK, &ev); switch (ev.type) { case MotionNotify: @@ -146,89 +143,16 @@ mousefunc_client_move(struct client_ctx *cc, union arg *arg) cc->geom.y + cc->geom.h + (cc->bwidth * 2), area.y, area.y + area.h, sc->snapdist); client_move(cc); + menu_windraw(sc, cc->win, + "%4d, %-4d", cc->geom.x, cc->geom.y); break; case ButtonRelease: client_move(cc); - xu_ptr_ungrab(); + XUnmapWindow(X_Dpy, sc->menu.win); + XReparentWindow(X_Dpy, sc->menu.win, sc->rootwin, 0, 0); + XUngrabPointer(X_Dpy, CurrentTime); return; } } /* NOTREACHED */ } - -void -mousefunc_menu_group(struct client_ctx *cc, union arg *arg) -{ - struct screen_ctx *sc = cc->sc; - struct group_ctx *gc; - struct menu *mi; - struct menu_q menuq; - - TAILQ_INIT(&menuq); - TAILQ_FOREACH(gc, &sc->groupq, entry) { - if (group_holds_only_sticky(gc)) - continue; - menuq_add(&menuq, gc, "%d %s", gc->num, gc->name); - } - - if ((mi = menu_filter(sc, &menuq, NULL, NULL, CWM_MENU_LIST, - NULL, search_print_group)) != NULL) { - gc = (struct group_ctx *)mi->ctx; - (group_holds_only_hidden(gc)) ? - group_show(gc) : group_hide(gc); - } - - menuq_clear(&menuq); -} - -void -mousefunc_menu_client(struct client_ctx *cc, union arg *arg) -{ - struct screen_ctx *sc = cc->sc; - struct client_ctx *old_cc; - struct menu *mi; - struct menu_q menuq; - - old_cc = client_current(); - - TAILQ_INIT(&menuq); - TAILQ_FOREACH(cc, &sc->clientq, entry) { - if (cc->flags & CLIENT_HIDDEN) { - menuq_add(&menuq, cc, NULL); - } - } - - if ((mi = menu_filter(sc, &menuq, NULL, NULL, CWM_MENU_LIST, - NULL, search_print_client)) != NULL) { - cc = (struct client_ctx *)mi->ctx; - client_unhide(cc); - if (old_cc != NULL) - client_ptrsave(old_cc); - client_ptrwarp(cc); - } - - menuq_clear(&menuq); -} - -void -mousefunc_menu_cmd(struct client_ctx *cc, union arg *arg) -{ - struct screen_ctx *sc = cc->sc; - struct cmd *cmd; - struct menu *mi; - struct menu_q menuq; - - TAILQ_INIT(&menuq); - TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { - if ((strcmp(cmd->name, "lock") == 0) || - (strcmp(cmd->name, "term") == 0)) - continue; - menuq_add(&menuq, cmd, NULL); - } - - if ((mi = menu_filter(sc, &menuq, NULL, NULL, CWM_MENU_LIST, - NULL, search_print_cmd)) != NULL) - u_spawn(((struct cmd *)mi->ctx)->path); - - menuq_clear(&menuq); -} diff --git a/parse.y b/parse.y index 1c04e2a..abd3224 100644 --- a/parse.y +++ b/parse.y @@ -114,10 +114,7 @@ main : FONTNAME STRING { conf->font = $2; } | STICKY yesno { - if ($2 == 0) - conf->flags &= ~CONF_STICKY_GROUPS; - else - conf->flags |= CONF_STICKY_GROUPS; + conf->stickygroups = $2; } | BORDERWIDTH NUMBER { if ($2 < 0 || $2 > UINT_MAX) { diff --git a/screen.c b/screen.c index 5d724a8..4e2767b 100644 --- a/screen.c +++ b/screen.c @@ -57,7 +57,7 @@ screen_init(int which) screen_update_geometry(sc); - for (i = 0; i < CALMWM_NGROUPS; i++) + for (i = 0; i < Conf.ngroups; i++) group_init(sc, i); xu_ewmh_net_desktop_names(sc); @@ -84,7 +84,7 @@ screen_init(int which) } screen_updatestackingorder(sc); - if (HasRandr) + if (Conf.xrandr) XRRSelectInput(X_Dpy, sc->rootwin, RRScreenChangeNotifyMask); TAILQ_INSERT_TAIL(&Screenq, sc, entry); @@ -101,7 +101,7 @@ screen_find(Window win) if (sc->rootwin == win) return(sc); } - warnx("screen_find failure win 0x%lu\n", win); + warnx("%s: failure win 0x%lu\n", __func__, win); return(NULL); } @@ -140,7 +140,7 @@ region_find(struct screen_ctx *sc, int x, int y) } struct geom -screen_area(struct screen_ctx *sc, int x, int y, int flags) +screen_area(struct screen_ctx *sc, int x, int y, enum apply_gap apply_gap) { struct region_ctx *rc; struct geom area = sc->work; @@ -152,7 +152,7 @@ screen_area(struct screen_ctx *sc, int x, int y, int flags) break; } } - if (flags & CWM_GAP) + if (apply_gap) area = screen_apply_gap(sc, area); return(area); } @@ -173,7 +173,7 @@ screen_update_geometry(struct screen_ctx *sc) free(rc); } - if (HasRandr) { + if (Conf.xrandr) { XRRScreenResources *sr; XRRCrtcInfo *ci; int i; @@ -229,3 +229,26 @@ screen_apply_gap(struct screen_ctx *sc, struct geom geom) return(geom); } + +/* Bring back clients which are beyond the screen. */ +void +screen_assert_clients_within(struct screen_ctx *sc) +{ + struct client_ctx *cc; + int top, left, right, bottom; + + TAILQ_FOREACH(cc, &sc->clientq, entry) { + if (cc->sc != sc) + continue; + top = cc->geom.y; + left = cc->geom.x; + right = cc->geom.x + cc->geom.w + (cc->bwidth * 2) - 1; + bottom = cc->geom.y + cc->geom.h + (cc->bwidth * 2) - 1; + if ((top > sc->view.h || left > sc->view.w) || + (bottom < 0 || right < 0)) { + cc->geom.x = sc->gap.left; + cc->geom.y = sc->gap.top; + client_move(cc); + } + } +} diff --git a/search.c b/search.c index 6f826af..c1b3e3d 100644 --- a/search.c +++ b/search.c @@ -52,57 +52,40 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search) (void)memset(tierp, 0, sizeof(tierp)); - /* - * In order of rank: - * - * 1. Look through labels. - * 2. Look at title history, from present to past. - * 3. Look at window class name. - */ - TAILQ_FOREACH(mi, menuq, entry) { int tier = -1, t; struct client_ctx *cc = (struct client_ctx *)mi->ctx; - /* First, try to match on labels. */ - if (cc->label != NULL && strsubmatch(search, cc->label, 0)) { - cc->matchname = cc->label; + /* Match on label. */ + if (strsubmatch(search, cc->label, 0)) tier = 0; - } - /* Then, on window names. */ + /* Match on window name history, from present to past. */ if (tier < 0) { - TAILQ_FOREACH_REVERSE(wn, &cc->nameq, winname_q, entry) + TAILQ_FOREACH_REVERSE(wn, &cc->nameq, name_q, entry) if (strsubmatch(search, wn->name, 0)) { - cc->matchname = wn->name; tier = 2; break; } } - /* Then if there is a match on the window class name. */ - if (tier < 0 && strsubmatch(search, cc->ch.res_class, 0)) { - cc->matchname = cc->ch.res_class; + /* Match on window resource class. */ + if ((tier < 0) && strsubmatch(search, cc->ch.res_class, 0)) tier = 3; - } if (tier < 0) continue; - /* - * De-rank a client one tier if it's the current - * window. Furthermore, this is denoted by a "!" when - * printing the window name in the search menu. - */ - if ((cc->flags & CLIENT_ACTIVE) && (tier < nitems(tierp) - 1)) + /* Current window is ranked down. */ + if ((tier < nitems(tierp) - 1) && (cc->flags & CLIENT_ACTIVE)) tier++; - /* Clients that are hidden get ranked one up. */ - if ((cc->flags & CLIENT_HIDDEN) && (tier > 0)) + /* Hidden window is ranked up. */ + if ((tier > 0) && (cc->flags & CLIENT_HIDDEN)) tier--; if (tier >= nitems(tierp)) - errx(1, "search_match_client: invalid tier"); + errx(1, "%s: invalid tier", __func__); /* * If you have a tierp, insert after it, and make it @@ -126,7 +109,7 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search) void search_print_cmd(struct menu *mi, int i) { - struct cmd *cmd = (struct cmd *)mi->ctx; + struct cmd_ctx *cmd = (struct cmd_ctx *)mi->ctx; (void)snprintf(mi->print, sizeof(mi->print), "%s", cmd->name); } @@ -152,12 +135,9 @@ search_print_client(struct menu *mi, int list) else if (cc->flags & CLIENT_HIDDEN) flag = '&'; - if ((list) || (cc->matchname == cc->label)) - cc->matchname = cc->name; - (void)snprintf(mi->print, sizeof(mi->print), "(%d) %c[%s] %s", (cc->gc) ? cc->gc->num : 0, flag, - (cc->label) ? cc->label : "", cc->matchname); + (cc->label) ? cc->label : "", cc->name); } static void diff --git a/xevents.c b/xevents.c index 4435016..2cfd12d 100644 --- a/xevents.c +++ b/xevents.c @@ -220,31 +220,37 @@ static void xev_handle_buttonpress(XEvent *ee) { XButtonEvent *e = &ee->xbutton; - struct client_ctx *cc, fakecc; - struct binding *mb; + struct client_ctx *cc; + struct screen_ctx *sc; + struct bind_ctx *mb; e->state &= ~IGNOREMODMASK; - TAILQ_FOREACH(mb, &Conf.mousebindingq, entry) { + TAILQ_FOREACH(mb, &Conf.mousebindq, entry) { if (e->button == mb->press.button && e->state == mb->modmask) break; } if (mb == NULL) return; - if (mb->context == CWM_CONTEXT_CLIENT) { + switch (mb->context) { + case CWM_CONTEXT_CC: if (((cc = client_find(e->window)) == NULL) && (cc = client_current()) == NULL) return; - } else { + (*mb->callback)(cc, &mb->argument, CWM_XEV_BTN); + break; + case CWM_CONTEXT_SC: if (e->window != e->root) return; - cc = &fakecc; - if ((cc->sc = screen_find(e->window)) == NULL) + if ((sc = screen_find(e->window)) == NULL) return; + (*mb->callback)(sc, &mb->argument, CWM_XEV_BTN); + break; + case CWM_CONTEXT_NONE: + (*mb->callback)(NULL, &mb->argument, CWM_XEV_BTN); + break; } - - (*mb->callback)(cc, &mb->argument); } static void @@ -263,8 +269,9 @@ static void xev_handle_keypress(XEvent *ee) { XKeyEvent *e = &ee->xkey; - struct client_ctx *cc = NULL, fakecc; - struct binding *kb; + struct client_ctx *cc; + struct screen_ctx *sc; + struct bind_ctx *kb; KeySym keysym, skeysym; unsigned int modshift; @@ -273,7 +280,7 @@ xev_handle_keypress(XEvent *ee) e->state &= ~IGNOREMODMASK; - TAILQ_FOREACH(kb, &Conf.keybindingq, entry) { + TAILQ_FOREACH(kb, &Conf.keybindq, entry) { if (keysym != kb->press.keysym && skeysym == kb->press.keysym) modshift = ShiftMask; else @@ -288,17 +295,22 @@ xev_handle_keypress(XEvent *ee) if (kb == NULL) return; - if (kb->context == CWM_CONTEXT_CLIENT) { + switch (kb->context) { + case CWM_CONTEXT_CC: if (((cc = client_find(e->window)) == NULL) && (cc = client_current()) == NULL) return; - } else { - cc = &fakecc; - if ((cc->sc = screen_find(e->window)) == NULL) + (*kb->callback)(cc, &kb->argument, CWM_XEV_KEY); + break; + case CWM_CONTEXT_SC: + if ((sc = screen_find(e->window)) == NULL) return; + (*kb->callback)(sc, &kb->argument, CWM_XEV_KEY); + break; + case CWM_CONTEXT_NONE: + (*kb->callback)(NULL, &kb->argument, CWM_XEV_KEY); + break; } - - (*kb->callback)(cc, &kb->argument); } /* @@ -344,6 +356,10 @@ xev_handle_clientmessage(XEvent *ee) if ((cc = client_find(e->window)) != NULL) { if ((old_cc = client_current()) != NULL) client_ptrsave(old_cc); + if (cc->flags & CLIENT_HIDDEN) + client_unhide(cc); + else + client_raise(cc); client_ptrwarp(cc); } } else if (e->message_type == ewmh[_NET_WM_DESKTOP]) { @@ -382,6 +398,7 @@ xev_handle_randr(XEvent *ee) if (sc->which == i) { XRRUpdateConfiguration(ee); screen_update_geometry(sc); + screen_assert_clients_within(sc); } } } @@ -419,7 +436,7 @@ xev_process(void) XEvent e; XNextEvent(X_Dpy, &e); - if (e.type - Randr_ev == RRScreenChangeNotify) + if (e.type - Conf.xrandr_event_base == RRScreenChangeNotify) xev_handle_randr(&e); else if (e.type < LASTEvent && xev_handlers[e.type] != NULL) (*xev_handlers[e.type])(&e); diff --git a/xutil.c b/xutil.c index 3393179..2a851df 100644 --- a/xutil.c +++ b/xutil.c @@ -31,68 +31,6 @@ #include "calmwm.h" -static unsigned int ign_mods[] = { 0, LockMask, Mod2Mask, Mod2Mask | LockMask }; - -void -xu_btn_grab(Window win, int mask, unsigned int btn) -{ - unsigned int i; - - for (i = 0; i < nitems(ign_mods); i++) - XGrabButton(X_Dpy, btn, (mask | ign_mods[i]), win, - False, BUTTONMASK, GrabModeAsync, - GrabModeSync, None, None); -} - -void -xu_btn_ungrab(Window win) -{ - XUngrabButton(X_Dpy, AnyButton, AnyModifier, win); -} - -void -xu_key_grab(Window win, unsigned int mask, KeySym keysym) -{ - KeyCode code; - unsigned int i; - - code = XKeysymToKeycode(X_Dpy, keysym); - if ((XkbKeycodeToKeysym(X_Dpy, code, 0, 0) != keysym) && - (XkbKeycodeToKeysym(X_Dpy, code, 0, 1) == keysym)) - mask |= ShiftMask; - - for (i = 0; i < nitems(ign_mods); i++) - XGrabKey(X_Dpy, code, (mask | ign_mods[i]), win, - True, GrabModeAsync, GrabModeAsync); -} - -void -xu_key_ungrab(Window win) -{ - XUngrabKey(X_Dpy, AnyKey, AnyModifier, win); -} - -int -xu_ptr_grab(Window win, unsigned int mask, Cursor curs) -{ - return(XGrabPointer(X_Dpy, win, False, mask, - GrabModeAsync, GrabModeAsync, - None, curs, CurrentTime) == GrabSuccess ? 0 : -1); -} - -int -xu_ptr_regrab(unsigned int mask, Cursor curs) -{ - return(XChangeActivePointerGrab(X_Dpy, mask, - curs, CurrentTime) == GrabSuccess ? 0 : -1); -} - -void -xu_ptr_ungrab(void) -{ - XUngrabPointer(X_Dpy, CurrentTime); -} - void xu_ptr_getpos(Window win, int *x, int *y) { @@ -177,8 +115,8 @@ xu_ewmh_net_supported_wm_check(struct screen_ctx *sc) XChangeProperty(X_Dpy, w, ewmh[_NET_SUPPORTING_WM_CHECK], XA_WINDOW, 32, PropModeReplace, (unsigned char *)&w, 1); XChangeProperty(X_Dpy, w, ewmh[_NET_WM_NAME], - cwmh[UTF8_STRING], 8, PropModeReplace, (unsigned char *)WMNAME, - strlen(WMNAME)); + cwmh[UTF8_STRING], 8, PropModeReplace, + (unsigned char *)Conf.wmname, strlen(Conf.wmname)); } void @@ -193,19 +131,20 @@ xu_ewmh_net_desktop_geometry(struct screen_ctx *sc) void xu_ewmh_net_workarea(struct screen_ctx *sc) { - long workareas[CALMWM_NGROUPS][4]; - int i; + unsigned long *workarea; + int i, ngroups = Conf.ngroups; - for (i = 0; i < CALMWM_NGROUPS; i++) { - workareas[i][0] = sc->work.x; - workareas[i][1] = sc->work.y; - workareas[i][2] = sc->work.w; - workareas[i][3] = sc->work.h; + workarea = xreallocarray(NULL, ngroups * 4, sizeof(unsigned long)); + for (i = 0; i < ngroups; i++) { + workarea[4 * i + 0] = sc->work.x; + workarea[4 * i + 1] = sc->work.y; + workarea[4 * i + 2] = sc->work.w; + workarea[4 * i + 3] = sc->work.h; } - XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_WORKAREA], - XA_CARDINAL, 32, PropModeReplace, (unsigned char *)workareas, - CALMWM_NGROUPS * 4); + XA_CARDINAL, 32, PropModeReplace, (unsigned char *)workarea, + ngroups * 4); + free(workarea); } void @@ -285,7 +224,7 @@ xu_ewmh_net_wm_desktop_viewport(struct screen_ctx *sc) void xu_ewmh_net_wm_number_of_desktops(struct screen_ctx *sc) { - long ndesks = CALMWM_NGROUPS; + long ndesks = Conf.ngroups; XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_NUMBER_OF_DESKTOPS], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&ndesks, 1); @@ -531,21 +470,3 @@ xu_xorcolor(XftColor a, XftColor b, XftColor *r) r->color.blue = a.color.blue ^ b.color.blue; r->color.alpha = 0xffff; } - -int -xu_xft_width(XftFont *xftfont, const char *text, int len) -{ - XGlyphInfo extents; - - XftTextExtentsUtf8(X_Dpy, xftfont, (const FcChar8*)text, - len, &extents); - - return(extents.xOff); -} - -void -xu_xft_draw(struct screen_ctx *sc, const char *text, int color, int x, int y) -{ - XftDrawStringUtf8(sc->xftdraw, &sc->xftcolor[color], sc->xftfont, - x, y, (const FcChar8*)text, strlen(text)); -}