diff --git a/calmwm.h b/calmwm.h index 6ccaf83..0f5b4b8 100644 --- a/calmwm.h +++ b/calmwm.h @@ -378,6 +378,7 @@ int grab_drag(struct client_ctx *); void grab_menuinit(struct screen_ctx *); void *grab_menu(XButtonEvent *, struct menu_q *); void grab_label(struct client_ctx *); +void grab_exec(void); void xfree(void *); void *xmalloc(size_t); @@ -425,6 +426,7 @@ void kbfunc_client_nogroup(struct client_ctx *, void *); void kbfunc_client_maximize(struct client_ctx *, void *); void kbfunc_client_vmaximize(struct client_ctx *, void *); void kbfunc_menu_search(struct client_ctx *, void *); +void kbfunc_exec(struct client_ctx *, void *); void kbfunc_term(struct client_ctx *cc, void *arg); void kbfunc_lock(struct client_ctx *cc, void *arg); diff --git a/conf.c b/conf.c index c4a1217..153e894 100644 --- a/conf.c +++ b/conf.c @@ -185,6 +185,7 @@ conf_setup(struct conf *c) XK_Return, ControlMask|Mod1Mask, 0, NULL); conf_bindkey(c, kbfunc_lock, XK_Delete, ControlMask|Mod1Mask, 0, NULL); + conf_bindkey(c, kbfunc_exec, XK_question, Mod1Mask, 0, NULL); conf_bindkey(c, kbfunc_client_hide, XK_Return, Mod1Mask, KBFLAG_NEEDCLIENT, 0); conf_bindkey(c, kbfunc_client_lower, diff --git a/cwm.1 b/cwm.1 index 6adcaf8..9cb9290 100644 --- a/cwm.1 +++ b/cwm.1 @@ -81,6 +81,8 @@ Switch to next group. Switch to previous group. .It Fa C-M-= Toggle vertical maximization of window. +.It Fa M-? +Spawn \&"Exec program\&" dialog. .El The mouse bindings are also important, they are: diff --git a/grab.c b/grab.c index 72b4523..3148272 100644 --- a/grab.c +++ b/grab.c @@ -430,6 +430,85 @@ grab_label(struct client_ctx *cc) XUnmapWindow(G_dpy, sc->searchwin); } +#define ExecMask (KeyPressMask|ExposureMask) + +void +grab_exec(void) +{ + int x, y, dx, dy, fontheight, focusrevert, len; + char cmdstr[MAXPATHLEN]; + char dispstr[MAXPATHLEN + sizeof("exec>") - 1]; + char chr, str[2]; + enum ctltype ctl; + struct fontdesc *font = DefaultFont; + struct screen_ctx *sc = screen_current(); + XEvent e; + Window focuswin; + + cmdstr[0] = '\0'; + + xu_ptr_getpos(sc->rootwin, &x, &y); + + dy = fontheight = font_ascent(font) + font_descent(font) + 1; + dx = font_width(font, "exec>", 5); + + XMoveResizeWindow(G_dpy, sc->searchwin, x, y, dx, dy); + XSelectInput(G_dpy, sc->searchwin, ExecMask); + XMapRaised(G_dpy, sc->searchwin); + + XGetInputFocus(G_dpy, &focuswin, &focusrevert); + XSetInputFocus(G_dpy, sc->searchwin, + RevertToPointerRoot, CurrentTime); + + for (;;) { + XMaskEvent(G_dpy, ExecMask, &e); + + switch (e.type) { + case KeyPress: + if (input_keycodetrans(e.xkey.keycode, e.xkey.state, + &ctl, &chr, 0) < 0) + continue; + + switch (ctl) { + case CTL_ERASEONE: + if ((len = strlen(cmdstr)) > 0) + cmdstr[len - 1] = '\0'; + break; + case CTL_RETURN: + if (strlen(cmdstr) > 0) + u_spawn(cmdstr); + goto out; + break; + case CTL_ABORT: + goto out; + default: + break; + } + + if (chr != '\0') { + str[0] = chr; + str[1] = '\0'; + strlcat(cmdstr, str, sizeof(cmdstr)); + } + case Expose: + snprintf(dispstr, sizeof(dispstr), "exec>%s", cmdstr); + + dx = font_width(font, dispstr, strlen(dispstr)); + dy = fontheight; + + XClearWindow(G_dpy, sc->searchwin); + XResizeWindow(G_dpy, sc->searchwin, dx, dy); + + font_draw(font, dispstr, strlen(dispstr), + sc->searchwin, 0, font_ascent(font) + 1); + break; + } + } + out: + XSetInputFocus(G_dpy, focuswin, focusrevert, CurrentTime); + XUnmapWindow(G_dpy, sc->searchwin); +} + int _sweepcalc(struct client_ctx *cc, int x0, int y0, int motionx, int motiony) { diff --git a/kbfunc.c b/kbfunc.c index 4071734..f8c463b 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -122,6 +122,12 @@ kbfunc_lock(struct client_ctx *cc, void *arg) u_spawn(G_conf.lockpath); } +void +kbfunc_exec(struct client_ctx *scratch, void *arg) +{ + grab_exec(); +} + void kbfunc_client_label(struct client_ctx *cc, void *arg) {