diff --git a/calmwm.h b/calmwm.h index faac8bb..eb64dd7 100644 --- a/calmwm.h +++ b/calmwm.h @@ -282,6 +282,8 @@ enum menu_exec { #define CWM_MENU_DUMMY 0x0001 #define CWM_MENU_FILE 0x0002 #define CWM_MENU_LIST 0x0004 +#define CWM_MENU_WINDOW_ALL 0x0008 +#define CWM_MENU_WINDOW_HIDDEN 0x0010 struct menu { TAILQ_ENTRY(menu) entry; @@ -461,15 +463,14 @@ void search_match_client(struct menu_q *, struct menu_q *, char *); void search_match_exec(struct menu_q *, struct menu_q *, char *); -void search_match_exec_path(struct menu_q *, - struct menu_q *, char *); -void search_match_path_any(struct menu_q *, struct menu_q *, +void search_match_path(struct menu_q *, struct menu_q *, char *); void search_match_text(struct menu_q *, struct menu_q *, char *); void search_print_client(struct menu *, int); void search_print_cmd(struct menu *, int); void search_print_group(struct menu *, int); +void search_print_text(struct menu *, int); struct region_ctx *region_find(struct screen_ctx *, int, int); struct geom screen_apply_gap(struct screen_ctx *, struct geom); @@ -539,7 +540,7 @@ int parse_config(const char *, struct conf *); void conf_atoms(void); void conf_autogroup(struct conf *, int, const char *, const char *); -int conf_bind_kbd(struct conf *, const char *, +int conf_bind_key(struct conf *, const char *, const char *); int conf_bind_mouse(struct conf *, const char *, const char *); diff --git a/client.c b/client.c index 7975bb9..377abdb 100644 --- a/client.c +++ b/client.c @@ -91,6 +91,8 @@ 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->dim.w = (cc->geom.w - cc->hint.basew) / cc->hint.incw; + cc->dim.h = (cc->geom.h - cc->hint.baseh) / cc->hint.inch; cc->ptr.x = cc->geom.w / 2; cc->ptr.y = cc->geom.h / 2; @@ -424,6 +426,8 @@ client_resize(struct client_ctx *cc, int reset) XMoveResizeWindow(X_Dpy, cc->win, cc->geom.x, cc->geom.y, cc->geom.w, cc->geom.h); + cc->dim.w = (cc->geom.w - cc->hint.basew) / cc->hint.incw; + cc->dim.h = (cc->geom.h - cc->hint.baseh) / cc->hint.inch; client_config(cc); } @@ -877,9 +881,6 @@ client_applysizehints(struct client_ctx *cc) cc->geom.w = MIN(cc->geom.w, cc->hint.maxw); if (cc->hint.maxh) cc->geom.h = MIN(cc->geom.h, cc->hint.maxh); - - cc->dim.w = (cc->geom.w - cc->hint.basew) / cc->hint.incw; - cc->dim.h = (cc->geom.h - cc->hint.baseh) / cc->hint.inch; } static void @@ -1085,4 +1086,3 @@ client_set_wm_state(struct client_ctx *cc, long state) 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 cebfc07..15d3217 100644 --- a/conf.c +++ b/conf.c @@ -34,27 +34,330 @@ 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 bind_ctx *); +static void conf_unbind_key(struct conf *, struct bind_ctx *); static void conf_unbind_mouse(struct conf *, struct bind_ctx *); +static int cursor_binds[] = { + XC_left_ptr, /* CF_NORMAL */ + XC_fleur, /* CF_MOVE */ + XC_bottom_right_corner, /* CF_RESIZE */ + XC_question_arrow, /* CF_QUESTION */ +}; +static const char *color_binds[] = { + "#CCCCCC", /* CWM_COLOR_BORDER_ACTIVE */ + "#666666", /* CWM_COLOR_BORDER_INACTIVE */ + "#FC8814", /* CWM_COLOR_BORDER_URGENCY */ + "blue", /* CWM_COLOR_BORDER_GROUP */ + "red", /* CWM_COLOR_BORDER_UNGROUP */ + "black", /* CWM_COLOR_MENU_FG */ + "white", /* CWM_COLOR_MENU_BG */ + "black", /* CWM_COLOR_MENU_FONT */ + "", /* CWM_COLOR_MENU_FONT_SEL */ +}; +static const struct { + const char *tag; + void (*handler)(void *, union arg *, enum xev); + enum context context; + union arg argument; +} name_to_func[] = { + { "window-menu-label", kbfunc_menu_client_label, 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-delete", kbfunc_client_delete, CWM_CONTEXT_CC, {0} }, + { "window-htile", kbfunc_client_htile, CWM_CONTEXT_CC, {0} }, + { "window-vtile", kbfunc_client_vtile, CWM_CONTEXT_CC, {0} }, + { "window-stick", kbfunc_client_toggle_sticky, CWM_CONTEXT_CC, {0} }, + { "window-fullscreen", kbfunc_client_toggle_fullscreen, CWM_CONTEXT_CC, {0} }, + { "window-maximize", kbfunc_client_toggle_maximize, CWM_CONTEXT_CC, {0} }, + { "window-vmaximize", kbfunc_client_toggle_vmaximize, CWM_CONTEXT_CC, {0} }, + { "window-hmaximize", kbfunc_client_toggle_hmaximize, CWM_CONTEXT_CC, {0} }, + { "window-freeze", kbfunc_client_toggle_freeze, CWM_CONTEXT_CC, {0} }, + { "window-cycle", kbfunc_client_cycle, CWM_CONTEXT_SC, + {.i = (CWM_CYCLE_FORWARD)} }, + { "window-rcycle", kbfunc_client_cycle, CWM_CONTEXT_SC, + {.i = (CWM_CYCLE_REVERSE)} }, + { "window-cycle-ingroup", kbfunc_client_cycle, CWM_CONTEXT_SC, + {.i = (CWM_CYCLE_FORWARD | CWM_CYCLE_INGROUP)} }, + { "window-rcycle-ingroup", kbfunc_client_cycle, CWM_CONTEXT_SC, + {.i = (CWM_CYCLE_REVERSE | CWM_CYCLE_INGROUP)} }, + { "window-group", kbfunc_client_toggle_group, CWM_CONTEXT_CC, {0} }, + { "window-movetogroup-1", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 1} }, + { "window-movetogroup-2", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 2} }, + { "window-movetogroup-3", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 3} }, + { "window-movetogroup-4", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 4} }, + { "window-movetogroup-5", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 5} }, + { "window-movetogroup-6", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 6} }, + { "window-movetogroup-7", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 7} }, + { "window-movetogroup-8", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 8} }, + { "window-movetogroup-9", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 9} }, + + { "window-move", mousefunc_client_move, CWM_CONTEXT_CC, {0} }, + { "window-move-up", kbfunc_client_move, CWM_CONTEXT_CC, + {.i = (CWM_UP)} }, + { "window-move-down", kbfunc_client_move, CWM_CONTEXT_CC, + {.i = (CWM_DOWN)} }, + { "window-move-right", kbfunc_client_move, CWM_CONTEXT_CC, + {.i = (CWM_RIGHT)} }, + { "window-move-left", kbfunc_client_move, CWM_CONTEXT_CC, + {.i = (CWM_LEFT)} }, + { "window-move-up-big", kbfunc_client_move, CWM_CONTEXT_CC, + {.i = (CWM_UP | CWM_BIGAMOUNT)} }, + { "window-move-down-big", kbfunc_client_move, CWM_CONTEXT_CC, + {.i = (CWM_DOWN | CWM_BIGAMOUNT)} }, + { "window-move-right-big", kbfunc_client_move, CWM_CONTEXT_CC, + {.i = (CWM_RIGHT | CWM_BIGAMOUNT)} }, + { "window-move-left-big", kbfunc_client_move, CWM_CONTEXT_CC, + {.i = (CWM_LEFT | CWM_BIGAMOUNT)} }, + { "window-resize", mousefunc_client_resize, CWM_CONTEXT_CC, {0} }, + { "window-resize-up", kbfunc_client_resize, CWM_CONTEXT_CC, + {.i = (CWM_UP)} }, + { "window-resize-down", kbfunc_client_resize, CWM_CONTEXT_CC, + {.i = (CWM_DOWN)} }, + { "window-resize-right", kbfunc_client_resize, CWM_CONTEXT_CC, + {.i = (CWM_RIGHT)} }, + { "window-resize-left", kbfunc_client_resize, CWM_CONTEXT_CC, + {.i = (CWM_LEFT)} }, + { "window-resize-up-big", kbfunc_client_resize, CWM_CONTEXT_CC, + {.i = (CWM_UP | CWM_BIGAMOUNT)} }, + { "window-resize-down-big", kbfunc_client_resize, CWM_CONTEXT_CC, + {.i = (CWM_DOWN | CWM_BIGAMOUNT)} }, + { "window-resize-right-big", kbfunc_client_resize, CWM_CONTEXT_CC, + {.i = (CWM_RIGHT | CWM_BIGAMOUNT)} }, + { "window-resize-left-big", kbfunc_client_resize, CWM_CONTEXT_CC, + {.i = (CWM_LEFT | CWM_BIGAMOUNT)} }, + + { "group-cycle", kbfunc_group_cycle, CWM_CONTEXT_SC, + {.i = (CWM_CYCLE_FORWARD)} }, + { "group-rcycle", kbfunc_group_cycle, CWM_CONTEXT_SC, + {.i = (CWM_CYCLE_REVERSE)} }, + { "group-toggle-all", kbfunc_group_alltoggle, CWM_CONTEXT_SC, {0} }, + { "group-toggle-1", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 1} }, + { "group-toggle-2", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 2} }, + { "group-toggle-3", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 3} }, + { "group-toggle-4", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 4} }, + { "group-toggle-5", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 5} }, + { "group-toggle-6", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 6} }, + { "group-toggle-7", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 7} }, + { "group-toggle-8", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 8} }, + { "group-toggle-9", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 9} }, + { "group-only-1", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 1} }, + { "group-only-2", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 2} }, + { "group-only-3", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 3} }, + { "group-only-4", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 4} }, + { "group-only-5", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 5} }, + { "group-only-6", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 6} }, + { "group-only-7", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 7} }, + { "group-only-8", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 8} }, + { "group-only-9", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 9} }, + + { "pointer-move-up", kbfunc_ptrmove, CWM_CONTEXT_SC, + {.i = (CWM_UP)} }, + { "pointer-move-down", kbfunc_ptrmove, CWM_CONTEXT_SC, + {.i = (CWM_DOWN)} }, + { "pointer-move-left", kbfunc_ptrmove, CWM_CONTEXT_SC, + {.i = (CWM_LEFT)} }, + { "pointer-move-right", kbfunc_ptrmove, CWM_CONTEXT_SC, + {.i = (CWM_RIGHT)} }, + { "pointer-move-up-big", kbfunc_ptrmove, CWM_CONTEXT_SC, + {.i = (CWM_UP | CWM_BIGAMOUNT)} }, + { "pointer-move-down-big", kbfunc_ptrmove, CWM_CONTEXT_SC, + {.i = (CWM_DOWN | CWM_BIGAMOUNT)} }, + { "pointer-move-left-big", kbfunc_ptrmove, CWM_CONTEXT_SC, + {.i = (CWM_LEFT | CWM_BIGAMOUNT)} }, + { "pointer-move-right-big", kbfunc_ptrmove, CWM_CONTEXT_SC, + {.i = (CWM_RIGHT | CWM_BIGAMOUNT)} }, + + { "menu-cmd", kbfunc_menu_cmd, CWM_CONTEXT_SC, {0} }, + { "menu-group", kbfunc_menu_group, CWM_CONTEXT_SC, {0} }, + { "menu-ssh", kbfunc_menu_ssh, CWM_CONTEXT_SC, {0} }, + { "menu-window", kbfunc_menu_client, CWM_CONTEXT_SC, + {.i = CWM_MENU_WINDOW_ALL} }, + { "menu-window-hidden", kbfunc_menu_client, CWM_CONTEXT_SC, + {.i = CWM_MENU_WINDOW_HIDDEN} }, + { "menu-exec", kbfunc_menu_exec, CWM_CONTEXT_SC, + {.i = CWM_MENU_EXEC_EXEC} }, + { "menu-exec-wm", kbfunc_menu_exec, CWM_CONTEXT_SC, + {.i = CWM_MENU_EXEC_WM} }, + + { "terminal", kbfunc_exec_term, CWM_CONTEXT_SC, {0} }, + { "lock", kbfunc_exec_lock, CWM_CONTEXT_SC, {0} }, + { "restart", kbfunc_cwm_status, CWM_CONTEXT_SC, {.i = CWM_EXEC_WM} }, + { "quit", kbfunc_cwm_status, CWM_CONTEXT_SC, {.i = CWM_QUIT} }, + +}; +static unsigned int ignore_mods[] = { + 0, LockMask, Mod2Mask, Mod2Mask | LockMask +}; +static const struct { + const char ch; + int mask; +} bind_mods[] = { + { 'C', ControlMask }, + { 'M', Mod1Mask }, + { '4', Mod4Mask }, + { 'S', ShiftMask }, +}; +static const struct { + const char *key; + const char *func; +} key_binds[] = { + { "CM-Return", "terminal" }, + { "CM-Delete", "lock" }, + { "M-question", "menu-exec" }, + { "CM-w", "menu-exec-wm" }, + { "M-period", "menu-ssh" }, + { "M-Return", "window-hide" }, + { "M-Down", "window-lower" }, + { "M-Up", "window-raise" }, + { "M-slash", "menu-window" }, + { "C-slash", "menu-cmd" }, + { "M-Tab", "window-cycle" }, + { "MS-Tab", "window-rcycle" }, + { "CM-n", "window-menu-label" }, + { "CM-x", "window-delete" }, + { "CM-a", "group-toggle-all" }, + { "CM-0", "group-toggle-all" }, + { "CM-1", "group-toggle-1" }, + { "CM-2", "group-toggle-2" }, + { "CM-3", "group-toggle-3" }, + { "CM-4", "group-toggle-4" }, + { "CM-5", "group-toggle-5" }, + { "CM-6", "group-toggle-6" }, + { "CM-7", "group-toggle-7" }, + { "CM-8", "group-toggle-8" }, + { "CM-9", "group-toggle-9" }, + { "M-Right", "group-cycle" }, + { "M-Left", "group-rcycle" }, + { "CM-g", "window-group" }, + { "CM-f", "window-fullscreen" }, + { "CM-m", "window-maximize" }, + { "CM-s", "window-stick" }, + { "CM-equal", "window-vmaximize" }, + { "CMS-equal", "window-hmaximize" }, + { "CMS-f", "window-freeze" }, + { "CMS-r", "restart" }, + { "CMS-q", "quit" }, + { "M-h", "window-move-left" }, + { "M-j", "window-move-down" }, + { "M-k", "window-move-up" }, + { "M-l", "window-move-right" }, + { "MS-h", "window-move-left-big" }, + { "MS-j", "window-move-down-big" }, + { "MS-k", "window-move-up-big" }, + { "MS-l", "window-move-right-big" }, + { "CM-h", "window-resize-left" }, + { "CM-j", "window-resize-down" }, + { "CM-k", "window-resize-up" }, + { "CM-l", "window-resize-right" }, + { "CMS-h", "window-resize-left-big" }, + { "CMS-j", "window-resize-down-big" }, + { "CMS-k", "window-resize-up-big" }, + { "CMS-l", "window-resize-right-big" }, +}, +mouse_binds[] = { + { "1", "menu-window" }, + { "2", "menu-group" }, + { "3", "menu-cmd" }, + { "M-1", "window-move" }, + { "CM-1", "window-group" }, + { "M-2", "window-resize" }, + { "M-3", "window-lower" }, + { "CMS-3", "window-hide" }, +}; + +void +conf_init(struct conf *c) +{ + unsigned int i; + + 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->keybindq); + TAILQ_INIT(&c->autogroupq); + TAILQ_INIT(&c->mousebindq); + + for (i = 0; i < nitems(key_binds); i++) + conf_bind_key(c, key_binds[i].key, key_binds[i].func); + + for (i = 0; i < nitems(mouse_binds); i++) + conf_bind_mouse(c, mouse_binds[i].key, mouse_binds[i].func); + + for (i = 0; i < nitems(color_binds); i++) + c->color[i] = xstrdup(color_binds[i]); + + conf_cmd_add(c, "lock", "xlock"); + conf_cmd_add(c, "term", "xterm"); + + (void)snprintf(c->known_hosts, sizeof(c->known_hosts), "%s/%s", + homedir, ".ssh/known_hosts"); + + c->font = xstrdup("sans-serif:pixelsize=14:bold"); + c->wmname = xstrdup("CWM"); +} + +void +conf_clear(struct conf *c) +{ + struct autogroup *ag; + struct bind_ctx *kb, *mb; + struct winname *wn; + struct cmd_ctx *cmd; + int i; + + while ((cmd = TAILQ_FIRST(&c->cmdq)) != NULL) { + TAILQ_REMOVE(&c->cmdq, cmd, entry); + free(cmd->name); + free(cmd); + } + while ((kb = TAILQ_FIRST(&c->keybindq)) != NULL) { + TAILQ_REMOVE(&c->keybindq, kb, entry); + free(kb); + } + 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) { + TAILQ_REMOVE(&c->ignoreq, wn, entry); + free(wn->name); + free(wn); + } + while ((mb = TAILQ_FIRST(&c->mousebindq)) != NULL) { + TAILQ_REMOVE(&c->mousebindq, mb, entry); + free(mb); + } + for (i = 0; i < CWM_COLOR_NITEMS; i++) + free(c->color[i]); + + free(c->font); + free(c->wmname); +} + int conf_cmd_add(struct conf *c, const char *name, const char *path) { struct cmd_ctx *cmd; cmd = xmalloc(sizeof(*cmd)); - cmd->name = xstrdup(name); if (strlcpy(cmd->path, path, sizeof(cmd->path)) >= sizeof(cmd->path)) { free(cmd->name); free(cmd); return(0); } - conf_cmd_remove(c, name); TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry); - return(1); } @@ -71,6 +374,7 @@ conf_cmd_remove(struct conf *c, const char *name) } } } + void conf_autogroup(struct conf *c, int num, const char *name, const char *class) { @@ -78,7 +382,6 @@ conf_autogroup(struct conf *c, int num, const char *name, const char *class) char *p; ag = xmalloc(sizeof(*ag)); - if ((p = strchr(class, ',')) == NULL) { if (name == NULL) ag->name = NULL; @@ -88,7 +391,6 @@ conf_autogroup(struct conf *c, int num, const char *name, const char *class) ag->class = xstrdup(class); } else { *(p++) = '\0'; - if (name == NULL) ag->name = xstrdup(class); else @@ -97,7 +399,6 @@ conf_autogroup(struct conf *c, int num, const char *name, const char *class) ag->class = xstrdup(p); } ag->num = num; - TAILQ_INSERT_TAIL(&c->autogroupq, ag, entry); } @@ -111,17 +412,30 @@ conf_ignore(struct conf *c, const char *name) TAILQ_INSERT_TAIL(&c->ignoreq, wn, entry); } -static const char *color_binds[] = { - "#CCCCCC", /* CWM_COLOR_BORDER_ACTIVE */ - "#666666", /* CWM_COLOR_BORDER_INACTIVE */ - "#FC8814", /* CWM_COLOR_BORDER_URGENCY */ - "blue", /* CWM_COLOR_BORDER_GROUP */ - "red", /* CWM_COLOR_BORDER_UNGROUP */ - "black", /* CWM_COLOR_MENU_FG */ - "white", /* CWM_COLOR_MENU_BG */ - "black", /* CWM_COLOR_MENU_FONT */ - "", /* CWM_COLOR_MENU_FONT_SEL */ -}; +void +conf_cursor(struct conf *c) +{ + unsigned int i; + + for (i = 0; i < nitems(cursor_binds); i++) + c->cursor[i] = XCreateFontCursor(X_Dpy, cursor_binds[i]); +} + +void +conf_client(struct client_ctx *cc) +{ + struct winname *wn; + int ignore = 0; + + TAILQ_FOREACH(wn, &Conf.ignoreq, entry) { + if (strncasecmp(wn->name, cc->name, strlen(wn->name)) == 0) { + ignore = 1; + break; + } + } + cc->bwidth = (ignore) ? 0 : Conf.bwidth; + cc->flags |= (ignore) ? CLIENT_IGNORE : 0; +} void conf_screen(struct screen_ctx *sc) @@ -174,322 +488,6 @@ conf_screen(struct screen_ctx *sc) conf_grab_kbd(sc->rootwin); } -static const struct { - const char *key; - const char *func; -} kbd_binds[] = { - { "CM-Return", "terminal" }, - { "CM-Delete", "lock" }, - { "M-question", "exec" }, - { "CM-w", "exec_wm" }, - { "M-period", "ssh" }, - { "M-Return", "hide" }, - { "M-Down", "lower" }, - { "M-Up", "raise" }, - { "M-slash", "search" }, - { "C-slash", "menusearch" }, - { "M-Tab", "cycle" }, - { "MS-Tab", "rcycle" }, - { "CM-n", "label" }, - { "CM-x", "delete" }, - { "CM-a", "nogroup" }, - { "CM-0", "nogroup" }, - { "CM-1", "group1" }, - { "CM-2", "group2" }, - { "CM-3", "group3" }, - { "CM-4", "group4" }, - { "CM-5", "group5" }, - { "CM-6", "group6" }, - { "CM-7", "group7" }, - { "CM-8", "group8" }, - { "CM-9", "group9" }, - { "M-Right", "cyclegroup" }, - { "M-Left", "rcyclegroup" }, - { "CM-g", "grouptoggle" }, - { "CM-f", "fullscreen" }, - { "CM-m", "maximize" }, - { "CM-s", "stick" }, - { "CM-equal", "vmaximize" }, - { "CMS-equal", "hmaximize" }, - { "CMS-f", "freeze" }, - { "CMS-r", "restart" }, - { "CMS-q", "quit" }, - { "M-h", "moveleft" }, - { "M-j", "movedown" }, - { "M-k", "moveup" }, - { "M-l", "moveright" }, - { "MS-h", "bigmoveleft" }, - { "MS-j", "bigmovedown" }, - { "MS-k", "bigmoveup" }, - { "MS-l", "bigmoveright" }, - { "CM-h", "resizeleft" }, - { "CM-j", "resizedown" }, - { "CM-k", "resizeup" }, - { "CM-l", "resizeright" }, - { "CMS-h", "bigresizeleft" }, - { "CMS-j", "bigresizedown" }, - { "CMS-k", "bigresizeup" }, - { "CMS-l", "bigresizeright" }, - { "C-Left", "ptrmoveleft" }, - { "C-Down", "ptrmovedown" }, - { "C-Up", "ptrmoveup" }, - { "C-Right", "ptrmoveright" }, - { "CS-Left", "bigptrmoveleft" }, - { "CS-Down", "bigptrmovedown" }, - { "CS-Up", "bigptrmoveup" }, - { "CS-Right", "bigptrmoveright" }, -}, -mouse_binds[] = { - { "1", "menu_unhide" }, - { "2", "menu_group" }, - { "3", "menu_cmd" }, - { "M-1", "window_move" }, - { "CM-1", "window_grouptoggle" }, - { "M-2", "window_resize" }, - { "M-3", "window_lower" }, - { "CMS-3", "window_hide" }, -}; - -void -conf_init(struct conf *c) -{ - unsigned int i; - - 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->keybindq); - TAILQ_INIT(&c->autogroupq); - TAILQ_INIT(&c->mousebindq); - - for (i = 0; i < nitems(kbd_binds); i++) - conf_bind_kbd(c, kbd_binds[i].key, kbd_binds[i].func); - - for (i = 0; i < nitems(mouse_binds); i++) - conf_bind_mouse(c, mouse_binds[i].key, mouse_binds[i].func); - - for (i = 0; i < nitems(color_binds); i++) - c->color[i] = xstrdup(color_binds[i]); - - conf_cmd_add(c, "lock", "xlock"); - conf_cmd_add(c, "term", "xterm"); - - (void)snprintf(c->known_hosts, sizeof(c->known_hosts), "%s/%s", - homedir, ".ssh/known_hosts"); - - c->font = xstrdup("sans-serif:pixelsize=14:bold"); - c->wmname = xstrdup("CWM"); -} - -void -conf_clear(struct conf *c) -{ - struct autogroup *ag; - struct bind_ctx *kb, *mb; - struct winname *wn; - struct cmd_ctx *cmd; - int i; - - while ((cmd = TAILQ_FIRST(&c->cmdq)) != NULL) { - TAILQ_REMOVE(&c->cmdq, cmd, entry); - free(cmd->name); - free(cmd); - } - - while ((kb = TAILQ_FIRST(&c->keybindq)) != NULL) { - TAILQ_REMOVE(&c->keybindq, kb, entry); - free(kb); - } - - 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) { - TAILQ_REMOVE(&c->ignoreq, wn, entry); - free(wn->name); - free(wn); - } - - while ((mb = TAILQ_FIRST(&c->mousebindq)) != NULL) { - TAILQ_REMOVE(&c->mousebindq, mb, entry); - free(mb); - } - - for (i = 0; i < CWM_COLOR_NITEMS; i++) - free(c->color[i]); - - free(c->font); - free(c->wmname); -} - -void -conf_client(struct client_ctx *cc) -{ - struct winname *wn; - int ignore = 0; - - TAILQ_FOREACH(wn, &Conf.ignoreq, entry) { - if (strncasecmp(wn->name, cc->name, strlen(wn->name)) == 0) { - ignore = 1; - break; - } - } - - cc->bwidth = (ignore) ? 0 : Conf.bwidth; - cc->flags |= (ignore) ? CLIENT_IGNORE : 0; -} - -static const struct { - const char *tag; - void (*handler)(void *, union arg *, enum xev); - int context; - union arg argument; -} name_to_func[] = { - { "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_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_CC, - {.i = (CWM_DOWN)} }, - { "moveright", kbfunc_client_move, CWM_CONTEXT_CC, - {.i = (CWM_RIGHT)} }, - { "moveleft", kbfunc_client_move, CWM_CONTEXT_CC, - {.i = (CWM_LEFT)} }, - { "bigmoveup", kbfunc_client_move, CWM_CONTEXT_CC, - {.i = (CWM_UP | CWM_BIGAMOUNT)} }, - { "bigmovedown", kbfunc_client_move, CWM_CONTEXT_CC, - {.i = (CWM_DOWN | CWM_BIGAMOUNT)} }, - { "bigmoveright", kbfunc_client_move, CWM_CONTEXT_CC, - {.i = (CWM_RIGHT | CWM_BIGAMOUNT)} }, - { "bigmoveleft", kbfunc_client_move, CWM_CONTEXT_CC, - {.i = (CWM_LEFT | CWM_BIGAMOUNT)} }, - { "resizeup", kbfunc_client_resize, CWM_CONTEXT_CC, - {.i = (CWM_UP)} }, - { "resizedown", kbfunc_client_resize, CWM_CONTEXT_CC, - {.i = (CWM_DOWN)} }, - { "resizeright", kbfunc_client_resize, CWM_CONTEXT_CC, - {.i = (CWM_RIGHT)} }, - { "resizeleft", kbfunc_client_resize, CWM_CONTEXT_CC, - {.i = (CWM_LEFT)} }, - { "bigresizeup", kbfunc_client_resize, CWM_CONTEXT_CC, - {.i = (CWM_UP | CWM_BIGAMOUNT)} }, - { "bigresizedown", kbfunc_client_resize, CWM_CONTEXT_CC, - {.i = (CWM_DOWN | CWM_BIGAMOUNT)} }, - { "bigresizeright", kbfunc_client_resize, CWM_CONTEXT_CC, - {.i = (CWM_RIGHT | CWM_BIGAMOUNT)} }, - { "bigresizeleft", kbfunc_client_resize, CWM_CONTEXT_CC, - {.i = (CWM_LEFT | CWM_BIGAMOUNT)} }, - { "ptrmoveup", kbfunc_ptrmove, CWM_CONTEXT_SC, - {.i = (CWM_UP)} }, - { "ptrmovedown", kbfunc_ptrmove, CWM_CONTEXT_SC, - {.i = (CWM_DOWN)} }, - { "ptrmoveleft", kbfunc_ptrmove, CWM_CONTEXT_SC, - {.i = (CWM_LEFT)} }, - { "ptrmoveright", kbfunc_ptrmove, CWM_CONTEXT_SC, - {.i = (CWM_RIGHT)} }, - { "bigptrmoveup", kbfunc_ptrmove, CWM_CONTEXT_SC, - {.i = (CWM_UP | CWM_BIGAMOUNT)} }, - { "bigptrmovedown", kbfunc_ptrmove, CWM_CONTEXT_SC, - {.i = (CWM_DOWN | CWM_BIGAMOUNT)} }, - { "bigptrmoveleft", kbfunc_ptrmove, CWM_CONTEXT_SC, - {.i = (CWM_LEFT | CWM_BIGAMOUNT)} }, - { "bigptrmoveright", kbfunc_ptrmove, CWM_CONTEXT_SC, - {.i = (CWM_RIGHT | CWM_BIGAMOUNT)} }, - { "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 { - const char ch; - int mask; -} bind_mods[] = { - { 'C', ControlMask }, - { 'M', Mod1Mask }, - { '4', Mod4Mask }, - { 'S', ShiftMask }, -}; - static const char * conf_bind_getmask(const char *name, unsigned int *mask) { @@ -504,64 +502,60 @@ conf_bind_getmask(const char *name, unsigned int *mask) if ((ch = strchr(name, bind_mods[i].ch)) != NULL && ch < dash) *mask |= bind_mods[i].mask; } - /* Skip past modifiers. */ return(dash + 1); } int -conf_bind_kbd(struct conf *c, const char *bind, const char *cmd) +conf_bind_key(struct conf *c, const char *bind, const char *cmd) { struct bind_ctx *kb; const char *key; unsigned int i; + if ((strcmp(bind, "all") == 0) && (cmd == NULL)) { + conf_unbind_key(c, NULL); + goto out; + } kb = xmalloc(sizeof(*kb)); key = conf_bind_getmask(bind, &kb->modmask); - kb->press.keysym = XStringToKeysym(key); if (kb->press.keysym == NoSymbol) { warnx("unknown symbol: %s", key); free(kb); return(0); } - - /* We now have the correct binding, remove duplicates. */ - conf_unbind_kbd(c, kb); - - if (strcmp("unmap", cmd) == 0) { + conf_unbind_key(c, kb); + if (cmd == NULL) { free(kb); - return(1); + goto out; } - for (i = 0; i < nitems(name_to_func); i++) { if (strcmp(name_to_func[i].tag, cmd) != 0) continue; - 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->keybindq, kb, entry); - return(1); + goto out; } - kb->callback = kbfunc_exec_cmd; kb->context = CWM_CONTEXT_NONE; kb->argument.c = xstrdup(cmd); TAILQ_INSERT_TAIL(&c->keybindq, kb, entry); +out: return(1); } static void -conf_unbind_kbd(struct conf *c, struct bind_ctx *unbind) +conf_unbind_key(struct conf *c, struct bind_ctx *unbind) { struct bind_ctx *key = NULL, *keynxt; TAILQ_FOREACH_SAFE(key, &c->keybindq, entry, keynxt) { - if (key->modmask != unbind->modmask) - continue; - - if (key->press.keysym == unbind->press.keysym) { + if ((unbind == NULL) || + ((key->modmask == unbind->modmask) && + (key->press.keysym == unbind->press.keysym))) { TAILQ_REMOVE(&c->keybindq, key, entry); if (key->context == CWM_CONTEXT_NONE) free(key->argument.c); @@ -577,36 +571,38 @@ conf_bind_mouse(struct conf *c, const char *bind, const char *cmd) const char *button, *errstr; unsigned int i; + if ((strcmp(bind, "all") == 0) && (cmd == NULL)) { + conf_unbind_mouse(c, NULL); + goto out; + } mb = xmalloc(sizeof(*mb)); button = conf_bind_getmask(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); } - - /* We now have the correct binding, remove duplicates. */ conf_unbind_mouse(c, mb); - - if (strcmp("unmap", cmd) == 0) { + if (cmd == NULL) { free(mb); - return(1); + goto out; } - for (i = 0; i < nitems(name_to_func); i++) { if (strcmp(name_to_func[i].tag, cmd) != 0) continue; - 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->mousebindq, mb, entry); - return(1); + goto out; } - - return(0); + mb->callback = kbfunc_exec_cmd; + mb->context = CWM_CONTEXT_NONE; + mb->argument.c = xstrdup(cmd); + TAILQ_INSERT_TAIL(&c->mousebindq, mb, entry); +out: + return(1); } static void @@ -615,55 +611,17 @@ conf_unbind_mouse(struct conf *c, struct bind_ctx *unbind) struct bind_ctx *mb = NULL, *mbnxt; TAILQ_FOREACH_SAFE(mb, &c->mousebindq, entry, mbnxt) { - if (mb->modmask != unbind->modmask) - continue; - - if (mb->press.button == unbind->press.button) { + if ((unbind == NULL) || + ((mb->modmask == unbind->modmask) && + (mb->press.button == unbind->press.button))) { TAILQ_REMOVE(&c->mousebindq, mb, entry); + if (mb->context == CWM_CONTEXT_NONE) + free(mb->argument.c); free(mb); } } } -static int cursor_binds[] = { - XC_left_ptr, /* CF_NORMAL */ - XC_fleur, /* CF_MOVE */ - XC_bottom_right_corner, /* CF_RESIZE */ - XC_question_arrow, /* CF_QUESTION */ -}; - -void -conf_cursor(struct conf *c) -{ - unsigned int i; - - for (i = 0; i < nitems(cursor_binds); i++) - 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 bind_ctx *mb; - unsigned int i; - - XUngrabButton(X_Dpy, AnyButton, AnyModifier, win); - - 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) { @@ -679,12 +637,32 @@ conf_grab_kbd(Window win) (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, + for (i = 0; i < nitems(ignore_mods); i++) + XGrabKey(X_Dpy, kc, (kb->modmask | ignore_mods[i]), win, True, GrabModeAsync, GrabModeAsync); } } +void +conf_grab_mouse(Window win) +{ + struct bind_ctx *mb; + unsigned int i; + + XUngrabButton(X_Dpy, AnyButton, AnyModifier, win); + + TAILQ_FOREACH(mb, &Conf.mousebindq, entry) { + if (mb->context != CWM_CONTEXT_CC) + continue; + for (i = 0; i < nitems(ignore_mods); i++) { + XGrabButton(X_Dpy, mb->press.button, + (mb->modmask | ignore_mods[i]), win, False, + BUTTONMASK, GrabModeAsync, GrabModeSync, + None, None); + } + } +} + static char *cwmhints[] = { "WM_STATE", "WM_DELETE_WINDOW", diff --git a/cwm.1 b/cwm.1 index 68434c3..2898a52 100644 --- a/cwm.1 +++ b/cwm.1 @@ -117,11 +117,6 @@ Toggle maximization of current window. Toggle vertical maximization of current window. .It Ic CMS-= Toggle horizontal maximization of current window. -.It Ic C-[Up | Down | Left | Right] -Move pointer by a small amount. -.It Ic CS-[Up | Down | Left | Right] -Move pointer by a large amount; see -.Xr cwmrc 5 . .It Ic M-[hjkl] Move window by a small amount. .It Ic MS-[hjkl] @@ -224,8 +219,8 @@ Menus are recalled by clicking the mouse on the root window: .Pp .Bl -tag -width Ds -offset indent -compact .It Ic M1 -Show list of currently hidden windows. -Selecting an item will unhide that window. +Show list of currently defined windows. +Selecting an item will warp to that window, unhiding it if necessary. .It Ic M2 Show list of currently defined groups. Selecting an item will hide/unhide that group. diff --git a/cwmrc.5 b/cwmrc.5 index 93f7273..6419abd 100644 --- a/cwmrc.5 +++ b/cwmrc.5 @@ -63,11 +63,15 @@ 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 Ar keys command -Cause the creation of a key binding, or replacement of a default -key binding. +.It Ic bind-key Ar key function +Bind or rebind key +.Ar key +to +.Ar function . The modifier keys come first, followed by a -.Sq - . +.Sq - , +then a keysym name, taken from +.Pa /usr/X11R6/include/X11/keysymdef.h . .Pp The following modifiers are recognised: .Pp @@ -83,22 +87,53 @@ Mod4 (windows) key. .El .Pp The -.Sq - -should be followed by a keysym name, taken from -.Pa /usr/X11R6/include/X11/keysymdef.h . -The -.Ar command +.Ar function may either be one from the -.Sx BIND COMMAND LIST +.Sx BIND FUNCTION LIST (see below) or the command line that is to be executed. .Pp -A special -.Ar command -keyword -.Dq unmap -can be used to remove the named key binding. -This can be used to remove a binding which conflicts with an -application. +.It Ic bind-mouse Ar button function +Bind or rebind button +.Ar button +to +.Ar function . +The modifier keys come first, followed by a +.Sq - , +then the button number. +.Pp +The following modifiers are recognised: +.Pp +.Bl -tag -width Ds -offset indent -compact +.It Ic C +Control key. +.It Ic M +Meta key. +.It Ic S +Shift key. +.It Ic 4 +Mod4 (windows) key. +.El +.Pp +The following buttons are recognised: +.Pp +.Bl -tag -width Ds -offset indent -compact +.It Ic 1 +Left mouse button. +.It Ic 2 +Middle mouse button. +.It Ic 3 +Right mouse button. +.It Ic 4 +Scroll up mouse button. +.It Ic 5 +Scroll down mouse button. +.El +.Pp +The +.Ar function +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 @@ -177,48 +212,6 @@ Ignore, and do not warp to, windows with the name .Ar windowname when drawing borders and cycling through windows. .Pp -.It Ic mousebind Ar buttons command -Cause the creation of a mouse binding, or replacement of a default -mouse binding. -The modifier keys come first, followed by a -.Sq - . -.Pp -The following modifiers are recognised: -.Pp -.Bl -tag -width Ds -offset indent -compact -.It Ic C -Control key. -.It Ic M -Meta key. -.It Ic S -Shift key. -.It Ic 4 -Mod4 (windows) key. -.El -.Pp -The -.Sq - -should be followed by number: -.Pp -.Bl -tag -width Ds -offset indent -compact -.It Ic 1 -Left mouse button. -.It Ic 2 -Middle mouse button. -.It Ic 3 -Right mouse button. -.It Ic 4 -Scroll up mouse button. -.It Ic 5 -Scroll down mouse button. -.El -.Pp -The -.Ar command -may be taken from the -.Sx MOUSEBIND COMMAND LIST -(see below). -.Pp .It Ic moveamount Ar pixels Set a default size for the keyboard movement bindings, in pixels. @@ -234,9 +227,28 @@ 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 . +A special +.Ar key +keyword +.Dq all +can be used to unbind all keys. +.Pp +.It Ic unbind-mouse Ar button +Unbind function bound to +.Ar button . +A special +.Ar button +keyword +.Dq all +can be used to unbind all buttons. +.Pp .El -.Sh BIND COMMAND LIST -.Bl -tag -width 18n -compact +.Sh BIND FUNCTION LIST +.Bl -tag -width 23n -compact .It restart Restart the running .Xr cwm 1 . @@ -247,197 +259,176 @@ Quit Spawn a new terminal. .It lock Lock the screen. -.It search +.It menu-window Launch window search menu. -.It menusearch +.It menu-window-hidden +Launch hidden window search menu. +.It menu-cmd Launch application search menu. -.It groupsearch +.It menu-group Launch group search menu. -.It exec +.It menu-exec Launch .Dq exec program menu. -.It exec_wm +.It menu-exec-wm Launch .Dq exec WindowManager menu. -.It ssh +.It menu-ssh Launch .Dq ssh menu. -.It group[n] +.It group-toggle-[n] 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 +.It group-only-[n] +Show only group n, where n is 1-9, hiding other groups. +.It window-toggle-all Toggle visibility of all groups. -.It grouptoggle +.It window-group Toggle group membership of current window. -.It movetogroup[n] +.It window-movetogroup-[n] Hide current window from display and move to group n, where n is 1-9. -.It cyclegroup +.It group-cycle Forward cycle through groups. -.It rcyclegroup +.It group-rcycle Reverse cycle through groups. -.It cycle +.It window-cycle Forward cycle through windows. -.It rcycle +.It window-rcycle Reverse cycle through windows. -.It cycleingroup +.It window-cycle-ingroup Forward cycle through windows in current group. -.It rcycleingroup +.It window-rcycle-ingroup Reverse cycle through windows in current group. -.It delete +.It window-delete Delete current window. -.It hide +.It window-hide Hide current window. -.It lower +.It window-lower Lower current window. -.It raise +.It window-raise Raise current window. -.It label +.It window-menu-label Label current window. -.It freeze +.It window-freeze Freeze current window geometry. -.It stick +.It window-stick Stick current window to all groups (same as assigning to nogroup). -.It fullscreen +.It window-fullscreen Full-screen current window (gap + border removed). -.It maximize +.It window-maximize Maximize current window (gap + border honored). -.It vmaximize +.It window-vmaximize Vertically maximize current window (gap + border honored). -.It hmaximize +.It window-hmaximize Horizontally maximize current window (gap + border honored). -.It moveup -Move window -.Ar moveamount -pixels up. -.It movedown -Move window -.Ar moveamount -pixels down. -.It moveright -Move window -.Ar moveamount -pixels right. -.It moveleft -Move window -.Ar moveamount -pixels left. -.It bigmoveup -Move window 10 times -.Ar moveamount -pixels up. -.It bigmovedown -Move window 10 times -.Ar moveamount -pixels down. -.It bigmoveright -Move window 10 times -.Ar moveamount -pixels right. -.It bigmoveleft -Move window 10 times -.Ar moveamount -pixels left. -.It resizeup -Resize window -.Ar moveamount -pixels up. -.It resizedown -Resize window -.Ar moveamount -pixels down. -.It resizeright -Resize window -.Ar moveamount -pixels right. -.It resizeleft -Resize window -.Ar moveamount -pixels left. -.It bigresizeup -Resize window 10 times -.Ar moveamount -pixels up. -.It bigresizedown -Resize window 10 times -.Ar moveamount -pixels down. -.It bigresizeright -Resize window 10 times -.Ar moveamount -pixels right. -.It bigresizeleft -Resize window 10 times -.Ar moveamount -pixels left. -.It ptrmoveup -Move pointer -.Ar moveamount -pixels up. -.It ptrmovedown -Move pointer -.Ar moveamount -pixels down. -.It ptrmoveright -Move pointer -.Ar moveamount -pixels right. -.It ptrmoveleft -Move pointer -.Ar moveamount -pixels left. -.It bigptrmoveup -Move pointer 10 times -.Ar moveamount -pixels up. -.It bigptrmovedown -Move pointer 10 times -.Ar moveamount -pixels down. -.It bigptrmoveright -Move pointer 10 times -.Ar moveamount -pixels right. -.It bigptrmoveleft -Move pointer 10 times -.Ar moveamount -pixels left. -.It htile +.It window-htile Current window is placed at the top of the screen and maximized horizontally, other windows in its group share remaining screen space. -.It vtile +.It window-vtile Current window is placed on the left of the screen and maximized vertically, other windows in its group share remaining screen space. -.El -.Sh MOUSEBIND COMMAND LIST -.Bl -tag -width 18n -compact -.It window_move +.It window-move Move current window. -.It window_resize +.It window-resize Resize current window. -.It window_lower -Lower current window. -.It window_raise -Raise current window. -.It window_hide -Hide current window. -.It window_grouptoggle -Toggle group membership of current window. -.It cyclegroup -Forward cycle through groups. -.It rcyclegroup -Reverse cycle through groups. -.It menu_group -Launch group list. -.It menu_unhide -Launch hidden window list. -.It menu_cmd -Launch command list. +.It window-move-up +Move window +.Ar moveamount +pixels up. +.It window-move-down +Move window +.Ar moveamount +pixels down. +.It window-move-right +Move window +.Ar moveamount +pixels right. +.It window-move-left +Move window +.Ar moveamount +pixels left. +.It window-move-up-big +Move window 10 times +.Ar moveamount +pixels up. +.It window-move-down-big +Move window 10 times +.Ar moveamount +pixels down. +.It window-move-right-big +Move window 10 times +.Ar moveamount +pixels right. +.It window-move-left-big +Move window 10 times +.Ar moveamount +pixels left. +.It window-resize-up +Resize window +.Ar moveamount +pixels up. +.It window-resize-down +Resize window +.Ar moveamount +pixels down. +.It window-resize-right +Resize window +.Ar moveamount +pixels right. +.It window-resize-left +Resize window +.Ar moveamount +pixels left. +.It window-resize-up-big +Resize window 10 times +.Ar moveamount +pixels up. +.It window-resize-down-big +Resize window 10 times +.Ar moveamount +pixels down. +.It window-resize-right-big +Resize window 10 times +.Ar moveamount +pixels right. +.It window-resize-left-big +Resize window 10 times +.Ar moveamount +pixels left. +.It pointer-move-up +Move pointer +.Ar moveamount +pixels up. +.It pointer-move-down +Move pointer +.Ar moveamount +pixels down. +.It pointer-move-right +Move pointer +.Ar moveamount +pixels right. +.It pointer-move-left +Move pointer +.Ar moveamount +pixels left. +.It pointer-move-up-big +Move pointer 10 times +.Ar moveamount +pixels up. +.It pointer-move-down-big +Move pointer 10 times +.Ar moveamount +pixels down. +.It pointer-move-right-big +Move pointer 10 times +.Ar moveamount +pixels right. +.It pointer-move-left-big +Move pointer 10 times +.Ar moveamount +pixels left. .El .Sh FILES .Bl -tag -width "~/.cwmrcXXX" -compact @@ -470,23 +461,23 @@ ignore xapm ignore xclock # Key bindings -bind CM-r label -bind CS-Return "xterm -e top" -bind 4-o unmap -bind CM-equal unmap -bind CMS-equal unmap -bind C4-equal vmaximize -bind C4S-equal hmaximize -bind M-1 grouponly1 -bind M-2 grouponly2 -bind M-3 grouponly3 -bind MS-1 movetogroup1 -bind MS-2 movetogroup2 -bind MS-3 movetogroup3 +bind-key CM-r window-menu-label +bind-key CS-Return "xterm -e top" +bind-key C4-equal window-vmaximize +bind-key C4S-equal window-hmaximize +bind-key M-1 group-only-1 +bind-key M-2 group-only-2 +bind-key M-3 group-only-3 +bind-key MS-1 window-movetogroup-1 +bind-key MS-2 window-movetogroup-2 +bind-key MS-3 window-movetogroup-3 +unbind-key 4-o +unbind-key CM-equal +unbind-key CMS-equal # Mouse bindings -mousebind M-2 window_lower -mousebind M-3 window_resize +bind-mouse M-2 window-lower +bind-mouse M-3 window-resize .Ed .Sh SEE ALSO .Xr cwm 1 diff --git a/kbfunc.c b/kbfunc.c index 5f5a163..5edb59d 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -298,12 +298,13 @@ kbfunc_menu_client(void *ctx, union arg *arg, enum xev xev) struct menu *mi; struct menu_q menuq; int m = (xev == CWM_XEV_BTN); + int all = (arg->i & CWM_MENU_WINDOW_ALL); old_cc = client_current(); TAILQ_INIT(&menuq); TAILQ_FOREACH(cc, &sc->clientq, entry) { - if (m) { + if (!all) { if (cc->flags & CLIENT_HIDDEN) menuq_add(&menuq, cc, NULL); } else @@ -390,6 +391,7 @@ kbfunc_menu_exec(void *ctx, union arg *arg, enum xev xev) struct screen_ctx *sc = ctx; char **ap, *paths[NPATHS], *path, *pathcpy; char tpath[PATH_MAX]; + struct stat sb; const char *label; DIR *dirp; struct dirent *dp; @@ -432,12 +434,13 @@ kbfunc_menu_exec(void *ctx, union arg *arg, enum xev xev) dp->d_name); if (l == -1 || l >= sizeof(tpath)) continue; - /* skip everything but regular files and symlinks */ + /* Skip everything but regular files and symlinks. */ if (dp->d_type != DT_REG && dp->d_type != DT_LNK) { - /* use an additional stat-based check in case d_type isn't supported */ - if (lstat(tpath, &sb) < 0) + /* lstat(2) in case d_type isn't supported. */ + if (lstat(tpath, &sb) == -1) continue; - if (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode)) + if (!S_ISREG(sb.st_mode) && + !S_ISLNK(sb.st_mode)) continue; } if (access(tpath, X_OK) == 0) @@ -449,7 +452,7 @@ kbfunc_menu_exec(void *ctx, union arg *arg, enum xev xev) if ((mi = menu_filter(sc, &menuq, label, NULL, (CWM_MENU_DUMMY | CWM_MENU_FILE), - search_match_exec_path, NULL)) != NULL) { + search_match_exec, search_print_text)) != NULL) { if (mi->text[0] == '\0') goto out; switch (cmd) { @@ -518,13 +521,13 @@ kbfunc_menu_ssh(void *ctx, union arg *arg, enum xev xev) if (p - buf + 1 > sizeof(hostbuf)) continue; (void)strlcpy(hostbuf, buf, p - buf + 1); - menuq_add(&menuq, NULL, hostbuf); + menuq_add(&menuq, NULL, "%s", hostbuf); } free(lbuf); (void)fclose(fp); menu: if ((mi = menu_filter(sc, &menuq, "ssh", NULL, (CWM_MENU_DUMMY), - search_match_exec, NULL)) != NULL) { + search_match_text, search_print_text)) != NULL) { if (mi->text[0] == '\0') goto out; l = snprintf(path, sizeof(path), "%s -T '[ssh] %s' -e ssh %s", @@ -550,7 +553,7 @@ kbfunc_menu_client_label(void *ctx, union arg *arg, enum xev xev) /* dummy is set, so this will always return */ mi = menu_filter(cc->sc, &menuq, "label", cc->label, (CWM_MENU_DUMMY), - search_match_text, NULL); + search_match_text, search_print_text); if (!mi->abort) { free(cc->label); diff --git a/menu.c b/menu.c index 44f76da..af13cbf 100644 --- a/menu.c +++ b/menu.c @@ -126,7 +126,6 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt, CurrentTime) != GrabSuccess) { XUnmapWindow(X_Dpy, sc->menu.win); return(NULL); - } XGetInputFocus(X_Dpy, &focuswin, &focusrevert); @@ -196,7 +195,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, search_print_text)) != NULL) { mr->abort = mi->abort; mr->dummy = mi->dummy; if (mi->text[0] != '\0') @@ -366,11 +365,7 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq) } TAILQ_FOREACH(mi, resultq, resultentry) { - if (mc->print != NULL) - (*mc->print)(mi, mc->listing); - else - (void)snprintf(mi->print, sizeof(mi->print), - "%s", mi->text); + (*mc->print)(mi, mc->listing); XftTextExtentsUtf8(X_Dpy, sc->xftfont, (const FcChar8*)mi->print, @@ -671,4 +666,3 @@ menu_windraw(struct screen_ctx *sc, Window win, const char *fmt, ...) free(text); } - diff --git a/mousefunc.c b/mousefunc.c index dbec420..0926506 100644 --- a/mousefunc.c +++ b/mousefunc.c @@ -53,6 +53,8 @@ mousefunc_client_resize(void *ctx, union arg *arg, enum xev xev) CurrentTime) != GrabSuccess) return; + menu_windraw(sc, cc->win, "%4d x %-4d", cc->dim.w, cc->dim.h); + for (;;) { XWindowEvent(X_Dpy, cc->win, MOUSEMASK, &ev); @@ -120,6 +122,8 @@ mousefunc_client_move(void *ctx, union arg *arg, enum xev xev) CurrentTime) != GrabSuccess) return; + menu_windraw(sc, cc->win, "%4d, %-4d", cc->geom.x, cc->geom.y); + for (;;) { XWindowEvent(X_Dpy, cc->win, MOUSEMASK, &ev); diff --git a/parse.y b/parse.y index abd3224..c8942d9 100644 --- a/parse.y +++ b/parse.y @@ -70,8 +70,9 @@ typedef struct { %} -%token FONTNAME STICKY GAP MOUSEBIND -%token AUTOGROUP BIND COMMAND IGNORE +%token BINDKEY UNBINDKEY BINDMOUSE UNBINDMOUSE +%token FONTNAME STICKY GAP +%token AUTOGROUP COMMAND IGNORE %token YES NO BORDERWIDTH MOVEAMOUNT %token COLOR SNAPDIST %token ACTIVEBORDER INACTIVEBORDER URGENCYBORDER @@ -171,16 +172,6 @@ main : FONTNAME STRING { conf_ignore(conf, $2); free($2); } - | BIND STRING string { - if (!conf_bind_kbd(conf, $2, $3)) { - yyerror("invalid bind: %s %s", $2, $3); - free($2); - free($3); - YYERROR; - } - free($2); - free($3); - } | GAP NUMBER NUMBER NUMBER NUMBER { if ($2 < 0 || $2 > INT_MAX || $3 < 0 || $3 > INT_MAX || @@ -194,9 +185,9 @@ main : FONTNAME STRING { conf->gap.left = $4; conf->gap.right = $5; } - | MOUSEBIND STRING string { - if (!conf_bind_mouse(conf, $2, $3)) { - yyerror("invalid mousebind: %s %s", $2, $3); + | BINDKEY STRING string { + if (!conf_bind_key(conf, $2, $3)) { + yyerror("invalid bind-key: %s %s", $2, $3); free($2); free($3); YYERROR; @@ -204,6 +195,32 @@ main : FONTNAME STRING { free($2); free($3); } + | UNBINDKEY STRING { + if (!conf_bind_key(conf, $2, NULL)) { + yyerror("invalid unbind-key: %s", $2); + free($2); + YYERROR; + } + free($2); + } + | BINDMOUSE STRING string { + if (!conf_bind_mouse(conf, $2, $3)) { + yyerror("invalid bind-mouse: %s %s", $2, $3); + free($2); + free($3); + YYERROR; + } + free($2); + free($3); + } + | UNBINDMOUSE STRING { + if (!conf_bind_mouse(conf, $2, NULL)) { + yyerror("invalid unbind-mouse: %s", $2); + free($2); + YYERROR; + } + free($2); + } ; color : COLOR colors @@ -280,7 +297,8 @@ lookup(char *s) static const struct keywords keywords[] = { { "activeborder", ACTIVEBORDER}, { "autogroup", AUTOGROUP}, - { "bind", BIND}, + { "bind-key", BINDKEY}, + { "bind-mouse", BINDMOUSE}, { "borderwidth", BORDERWIDTH}, { "color", COLOR}, { "command", COMMAND}, @@ -292,12 +310,13 @@ lookup(char *s) { "inactiveborder", INACTIVEBORDER}, { "menubg", MENUBG}, { "menufg", MENUFG}, - { "mousebind", MOUSEBIND}, { "moveamount", MOVEAMOUNT}, { "no", NO}, { "selfont", FONTSELCOLOR}, { "snapdist", SNAPDIST}, { "sticky", STICKY}, + { "unbind-key", UNBINDKEY}, + { "unbind-mouse", UNBINDMOUSE}, { "ungroupborder", UNGROUPBORDER}, { "urgencyborder", URGENCYBORDER}, { "yes", YES} diff --git a/search.c b/search.c index c1b3e3d..e50884a 100644 --- a/search.c +++ b/search.c @@ -36,10 +36,8 @@ #define PATH_ANY 0x0001 #define PATH_EXEC 0x0002 -static void search_match_path(struct menu_q *, struct menu_q *, +static void search_match_path_type(struct menu_q *, struct menu_q *, char *, int); -static void search_match_path_exec(struct menu_q *, struct menu_q *, - char *); static int strsubmatch(char *, char *, int); void @@ -107,7 +105,13 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search) } void -search_print_cmd(struct menu *mi, int i) +search_print_text(struct menu *mi, int listing) +{ + (void)snprintf(mi->print, sizeof(mi->print), "%s", mi->text); +} + +void +search_print_cmd(struct menu *mi, int listing) { struct cmd_ctx *cmd = (struct cmd_ctx *)mi->ctx; @@ -115,7 +119,7 @@ search_print_cmd(struct menu *mi, int i) } void -search_print_group(struct menu *mi, int i) +search_print_group(struct menu *mi, int listing) { struct group_ctx *gc = (struct group_ctx *)mi->ctx; @@ -125,7 +129,7 @@ search_print_group(struct menu *mi, int i) } void -search_print_client(struct menu *mi, int list) +search_print_client(struct menu *mi, int listing) { struct client_ctx *cc = (struct client_ctx *)mi->ctx; char flag = ' '; @@ -141,7 +145,8 @@ search_print_client(struct menu *mi, int list) } static void -search_match_path(struct menu_q *menuq, struct menu_q *resultq, char *search, int flag) +search_match_path_type(struct menu_q *menuq, struct menu_q *resultq, + char *search, int flag) { char pattern[PATH_MAX]; glob_t g; @@ -162,16 +167,10 @@ search_match_path(struct menu_q *menuq, struct menu_q *resultq, char *search, in globfree(&g); } -static void -search_match_path_exec(struct menu_q *menuq, struct menu_q *resultq, char *search) -{ - return(search_match_path(menuq, resultq, search, PATH_EXEC)); -} - void -search_match_path_any(struct menu_q *menuq, struct menu_q *resultq, char *search) +search_match_path(struct menu_q *menuq, struct menu_q *resultq, char *search) { - return(search_match_path(menuq, resultq, search, PATH_ANY)); + return(search_match_path_type(menuq, resultq, search, PATH_ANY)); } void @@ -208,14 +207,9 @@ search_match_exec(struct menu_q *menuq, struct menu_q *resultq, char *search) if (mj == NULL) TAILQ_INSERT_TAIL(resultq, mi, resultentry); } -} -void -search_match_exec_path(struct menu_q *menuq, struct menu_q *resultq, char *search) -{ - search_match_exec(menuq, resultq, search); if (TAILQ_EMPTY(resultq)) - search_match_path_exec(menuq, resultq, search); + search_match_path_type(menuq, resultq, search, PATH_EXEC); } static int