void mousefunc_client_move(struct client_ctx *cc, union arg *arg) { XEvent ev; Time ltime = 0; struct screen_ctx *sc = cc->sc; struct geom xine; int px, py; client_raise(cc); if (cc->flags & CLIENT_FREEZE) return; if (xu_ptr_grab(cc->win, MOUSEMASK, Conf.cursor[CF_MOVE]) < 0) return; xu_ptr_getpos(cc->win, &px, &py); for (;;) { XMaskEvent(X_Dpy, MOUSEMASK, &ev); switch (ev.type) { case MotionNotify: cc->geom.x = ev.xmotion.x_root - px - cc->bwidth; cc->geom.y = ev.xmotion.y_root - py - cc->bwidth; xine = screen_find_xinerama(sc, cc->geom.x + cc->geom.w / 2, cc->geom.y + cc->geom.h / 2, CWM_GAP); cc->geom.x += client_snapcalc(cc->geom.x, cc->geom.x + cc->geom.w + (cc->bwidth * 2), xine.x, xine.x + xine.w, sc->snapdist); cc->geom.y += client_snapcalc(cc->geom.y, cc->geom.y + cc->geom.h + (cc->bwidth * 2), xine.y, xine.y + xine.h, sc->snapdist); /* don't move more than 60 times / second */ if ((ev.xmotion.time - ltime) > (1000 / 60)) { ltime = ev.xmotion.time; client_move(cc); } break; case ButtonRelease: if (ltime) client_move(cc); xu_ptr_ungrab(); return; } } /* NOTREACHED */ }
void 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; struct geom area; int px, py; client_raise(cc); 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); if (XGrabPointer(X_Dpy, cc->win, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_MOVE], CurrentTime) != GrabSuccess) return; menu_windraw(sc, cc->win, "%4d, %-4d", cc->geom.x, cc->geom.y); for (;;) { XWindowEvent(X_Dpy, cc->win, MOUSEMASK, &ev); switch (ev.type) { case MotionNotify: /* not more than 60 times / second */ if ((ev.xmotion.time - ltime) <= (1000 / 60)) continue; ltime = ev.xmotion.time; cc->geom.x = ev.xmotion.x_root - px - cc->bwidth; cc->geom.y = ev.xmotion.y_root - py - cc->bwidth; area = screen_area(sc, cc->geom.x + cc->geom.w / 2, cc->geom.y + cc->geom.h / 2, CWM_GAP); cc->geom.x += client_snapcalc(cc->geom.x, cc->geom.x + cc->geom.w + (cc->bwidth * 2), area.x, area.x + area.w, sc->snapdist); cc->geom.y += client_snapcalc(cc->geom.y, 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); XUnmapWindow(X_Dpy, sc->menu.win); XReparentWindow(X_Dpy, sc->menu.win, sc->rootwin, 0, 0); XUngrabPointer(X_Dpy, CurrentTime); return; } } /* NOTREACHED */ }
struct menu * menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt, const char *initial, int flags, void (*match)(struct menu_q *, struct menu_q *, char *), void (*print)(struct menu *, int)) { struct menu_ctx mc; struct menu_q resultq; struct menu *mi = NULL; XEvent e; Window focuswin; int focusrevert, xsave, ysave, xcur, ycur; TAILQ_INIT(&resultq); xu_ptr_getpos(sc->rootwin, &xsave, &ysave); (void)memset(&mc, 0, sizeof(mc)); mc.sc = sc; mc.flags = flags; mc.match = match; mc.print = print; mc.entry = mc.prev = -1; mc.geom.x = xsave; mc.geom.y = ysave; if (mc.flags & CWM_MENU_LIST) mc.list = 1; (void)strlcpy(mc.promptstr, prompt, sizeof(mc.promptstr)); if (initial != NULL) (void)strlcpy(mc.searchstr, initial, sizeof(mc.searchstr)); else mc.searchstr[0] = '\0'; mc.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); mc.xftdraw = XftDrawCreate(X_Dpy, mc.win, sc->visual, sc->colormap); XSelectInput(X_Dpy, mc.win, MENUMASK); XMapRaised(X_Dpy, mc.win); if (XGrabPointer(X_Dpy, mc.win, False, MENUGRABMASK, GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_QUESTION], CurrentTime) != GrabSuccess) { XftDrawDestroy(mc.xftdraw); XDestroyWindow(X_Dpy, mc.win); } XGetInputFocus(X_Dpy, &focuswin, &focusrevert); XSetInputFocus(X_Dpy, mc.win, RevertToPointerRoot, CurrentTime); /* make sure keybindings don't remove keys from the menu stream */ XGrabKeyboard(X_Dpy, mc.win, True, GrabModeAsync, GrabModeAsync, CurrentTime); for (;;) { mc.changed = 0; XWindowEvent(X_Dpy, mc.win, MENUMASK, &e); switch (e.type) { case KeyPress: if ((mi = menu_handle_key(&e, &mc, menuq, &resultq)) != NULL) goto out; /* FALLTHROUGH */ case Expose: menu_draw(&mc, menuq, &resultq); break; case MotionNotify: menu_handle_move(&mc, &resultq, e.xbutton.x, e.xbutton.y); break; case ButtonRelease: if ((mi = menu_handle_release(&mc, &resultq, e.xbutton.x, e.xbutton.y)) != NULL) goto out; break; default: break; } } out: if ((mc.flags & CWM_MENU_DUMMY) == 0 && mi->dummy) { /* no mouse based match */ free(mi); mi = NULL; } XftDrawDestroy(mc.xftdraw); XDestroyWindow(X_Dpy, mc.win); XSetInputFocus(X_Dpy, focuswin, focusrevert, CurrentTime); /* restore if user didn't move */ xu_ptr_getpos(sc->rootwin, &xcur, &ycur); if (xcur == mc.geom.x && ycur == mc.geom.y) xu_ptr_setpos(sc->rootwin, xsave, ysave); XUngrabPointer(X_Dpy, CurrentTime); XUngrabKeyboard(X_Dpy, CurrentTime); return(mi); }
struct menu * menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt, char *initial, int dummy, void (*match)(struct menu_q *, struct menu_q *, char *), void (*print)(struct menu *, int)) { struct menu_ctx mc; struct menu_q resultq; struct menu *mi = NULL; XEvent e; Window focuswin; int evmask, focusrevert; int xsave, ysave, xcur, ycur; TAILQ_INIT(&resultq); bzero(&mc, sizeof(mc)); xu_ptr_getpos(sc->rootwin, &mc.x, &mc.y); xsave = mc.x; ysave = mc.y; if (prompt == NULL) { evmask = MENUMASK; mc.promptstr[0] = '\0'; mc.list = 1; } else { evmask = MENUMASK | KEYMASK; /* only accept keys if prompt */ (void)snprintf(mc.promptstr, sizeof(mc.promptstr), "%s%s", prompt, PROMPT_SCHAR); (void)snprintf(mc.dispstr, sizeof(mc.dispstr), "%s%s%s", mc.promptstr, mc.searchstr, PROMPT_ECHAR); mc.width = font_width(sc, mc.dispstr, strlen(mc.dispstr)); mc.hasprompt = 1; } if (initial != NULL) (void)strlcpy(mc.searchstr, initial, sizeof(mc.searchstr)); else mc.searchstr[0] = '\0'; mc.match = match; mc.print = print; mc.entry = mc.prev = -1; XMoveResizeWindow(X_Dpy, sc->menuwin, mc.x, mc.y, mc.width, font_height(sc)); XSelectInput(X_Dpy, sc->menuwin, evmask); XMapRaised(X_Dpy, sc->menuwin); if (xu_ptr_grab(sc->menuwin, MENUGRABMASK, Cursor_question) < 0) { XUnmapWindow(X_Dpy, sc->menuwin); return (NULL); } XGetInputFocus(X_Dpy, &focuswin, &focusrevert); XSetInputFocus(X_Dpy, sc->menuwin, RevertToPointerRoot, CurrentTime); /* make sure keybindings don't remove keys from the menu stream */ XGrabKeyboard(X_Dpy, sc->menuwin, True, GrabModeAsync, GrabModeAsync, CurrentTime); menu_draw(sc, &mc, menuq, &resultq); for (;;) { mc.changed = 0; XWindowEvent(X_Dpy, sc->menuwin, evmask, &e); switch (e.type) { case KeyPress: if ((mi = menu_handle_key(&e, &mc, menuq, &resultq)) != NULL) goto out; /* FALLTHROUGH */ case Expose: menu_draw(sc, &mc, menuq, &resultq); break; case MotionNotify: menu_handle_move(&e, &mc, &resultq, sc); break; case ButtonRelease: if ((mi = menu_handle_release(&e, &mc, sc, &resultq)) != NULL) goto out; break; default: break; } } out: if (dummy == 0 && mi->dummy) { /* no mouse based match */ xfree(mi); mi = NULL; } XSetInputFocus(X_Dpy, focuswin, focusrevert, CurrentTime); /* restore if user didn't move */ xu_ptr_getpos(sc->rootwin, &xcur, &ycur); if (xcur == mc.x && ycur == mc.y) xu_ptr_setpos(sc->rootwin, xsave, ysave); xu_ptr_ungrab(); XUnmapWindow(X_Dpy, sc->menuwin); XUngrabKeyboard(X_Dpy, CurrentTime); return (mi); }