diff options
Diffstat (limited to 'menu.c')
-rw-r--r-- | menu.c | 141 |
1 files changed, 96 insertions, 45 deletions
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); +} + |