diff --git a/Makefile b/Makefile index cf49c4a..c3efedb 100644 --- a/Makefile +++ b/Makefile @@ -7,11 +7,11 @@ PROG= cwm BINDIR= /usr/bin SRCS= calmwm.c screen.c xmalloc.c client.c menu.c \ - search.c util.c xutil.c conf.c input.c xevents.c group.c \ + search.c util.c xutil.c conf.c xevents.c group.c \ kbfunc.c mousefunc.c font.c parse.y OBJS= calmwm.o screen.o xmalloc.o client.o menu.o \ - search.o util.o xutil.o conf.o input.o xevents.o group.o \ + search.o util.o xutil.o conf.o xevents.o group.o \ kbfunc.o mousefunc.o font.o strlcpy.o strlcat.o y.tab.o \ strtonum.o fgetln.o @@ -21,7 +21,7 @@ CPPFLAGS+= -I${X11BASE}/include -I${X11BASE}/include/freetype2 -I. CFLAGS+= -Wall -O2 -g -LDADD+= -L${X11BASE}/lib -lXft -lXrender -lX11 ${LIBXCB} -lXau -lXdmcp \ +LDADD+= -L${X11BASE}/lib -lXft -lXrender -lX11 -lxcb -lXau -lXdmcp \ -lfontconfig -lexpat -lfreetype -lz -lXinerama -lXrandr -lXext MANDIR= ${X11BASE}/man/cat diff --git a/calmwm.h b/calmwm.h index 433119a..2b8f531 100644 --- a/calmwm.h +++ b/calmwm.h @@ -59,6 +59,10 @@ size_t strlcat(char *, const char *, size_t); PointerMotionMask) #define SearchMask (KeyPressMask|ExposureMask) +#ifndef nitems +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#endif + enum cwmcolor { CWM_COLOR_BORDOR_ACTIVE, CWM_COLOR_BORDER_INACTIVE, @@ -197,7 +201,6 @@ struct client_ctx { char *app_class; char *app_name; - char *app_cliarg; }; extern const char *shortcut_to_name[]; @@ -333,12 +336,6 @@ struct menu { TAILQ_HEAD(menu_q, menu); -enum ctltype { - CTL_NONE = -1, - CTL_ERASEONE = 0, CTL_WIPE, CTL_UP, CTL_DOWN, CTL_RETURN, - CTL_ABORT, CTL_ALL -}; - /* MWM hints */ struct mwm_hints { @@ -354,9 +351,6 @@ struct mwm_hints { #define MWM_DECOR_ALL (1 << 0) #define MWM_DECOR_BORDER (1 << 1) -int input_keycodetrans(KeyCode, u_int, enum ctltype *, - char *); - __dead void usage(void); struct client_ctx *client_find(Window); @@ -392,9 +386,6 @@ struct menu *menu_filter(struct screen_ctx *, struct menu_q *, void (*)(struct menu *, int)); void menu_init(struct screen_ctx *); -/* XXX should be xu_ */ -void xev_reconfig(struct client_ctx *); - void xev_loop(void); void xu_getatoms(void); @@ -407,6 +398,7 @@ void xu_ptr_setpos(Window, int, int); void xu_ptr_getpos(Window, int *, int *); void xu_key_grab(Window, int, int); void xu_key_ungrab(Window, int, int); +void xu_configure(struct client_ctx *); void xu_sendmsg(Window, Atom, long); int xu_getprop(Window, Atom, Atom, long, u_char **); int xu_getstrprop(Window, Atom, char **); diff --git a/client.c b/client.c index 8971b35..237c0ce 100644 --- a/client.c +++ b/client.c @@ -114,7 +114,7 @@ client_new(Window win, struct screen_ctx *sc, int mapped) XAddToSaveSet(X_Dpy, cc->win); /* Notify client of its configuration. */ - xev_reconfig(cc); + xu_configure(cc); (state == IconicState) ? client_hide(cc) : client_unhide(cc); xu_setstate(cc, cc->state); @@ -390,14 +390,19 @@ client_resize(struct client_ctx *cc) XMoveResizeWindow(X_Dpy, cc->win, cc->geom.x, cc->geom.y, cc->geom.width, cc->geom.height); - xev_reconfig(cc); + xu_configure(cc); } void client_move(struct client_ctx *cc) { + if (cc->flags & CLIENT_VMAXIMIZED) + cc->savegeom.x = cc->geom.x; + if (cc->flags & CLIENT_HMAXIMIZED) + cc->savegeom.y = cc->geom.y; + XMoveWindow(X_Dpy, cc->win, cc->geom.x, cc->geom.y); - xev_reconfig(cc); + xu_configure(cc); } void @@ -807,8 +812,6 @@ static void client_gethints(struct client_ctx *cc) { XClassHint xch; - int argc; - char **argv; struct mwm_hints *mwmh; if (XGetClassHint(X_Dpy, cc->win, &xch)) { @@ -824,29 +827,6 @@ client_gethints(struct client_ctx *cc) !(mwmh->decorations & MWM_DECOR_ALL) && !(mwmh->decorations & MWM_DECOR_BORDER)) cc->bwidth = 0; - if (XGetCommand(X_Dpy, cc->win, &argv, &argc)) { -#define MAX_ARGLEN 512 -#define ARG_SEP_ " " - int i, o, len = MAX_ARGLEN; - char *buf; - - buf = xmalloc(len); - buf[0] = '\0'; - - for (o = 0, i = 0; o < len && i < argc; i++) { - if (argv[i] == NULL) - break; - strlcat(buf, argv[i], len); - o += strlen(buf); - strlcat(buf, ARG_SEP_, len); - o += strlen(ARG_SEP_); - } - - if (strlen(buf) > 0) - cc->app_cliarg = buf; - - XFreeStringList(argv); - } } static void @@ -856,7 +836,6 @@ client_freehints(struct client_ctx *cc) XFree(cc->app_name); if (cc->app_class != NULL) XFree(cc->app_class); - xfree(cc->app_cliarg); } static int diff --git a/conf.c b/conf.c index 10135a6..b453405 100644 --- a/conf.c +++ b/conf.c @@ -191,10 +191,10 @@ conf_init(struct conf *c) TAILQ_INIT(&c->autogroupq); TAILQ_INIT(&c->mousebindingq); - for (i = 0; i < sizeof(kb_binds) / sizeof(kb_binds[0]); i++) + for (i = 0; i < nitems(kb_binds); i++) conf_bindname(c, kb_binds[i].key, kb_binds[i].func); - for (i = 0; i < sizeof(m_binds) / sizeof(m_binds[0]); i++) + for (i = 0; i < nitems(m_binds); i++) conf_mousebind(c, m_binds[i].key, m_binds[i].func); /* Default term/lock */ @@ -467,8 +467,7 @@ conf_bindname(struct conf *c, char *name, char *binding) current_binding = xcalloc(1, sizeof(*current_binding)); if ((substring = strchr(name, '-')) != NULL) { - for (iter = 0; iter < (sizeof(bind_mods) / - sizeof(bind_mods[0])); iter++) { + for (iter = 0; iter < nitems(bind_mods); iter++) { if ((tmp = strchr(name, bind_mods[iter].chr)) != NULL && tmp < substring) { current_binding->modmask |= @@ -573,8 +572,7 @@ conf_mousebind(struct conf *c, char *name, char *binding) current_binding = xcalloc(1, sizeof(*current_binding)); if ((substring = strchr(name, '-')) != NULL) { - for (iter = 0; iter < (sizeof(bind_mods) / - sizeof(bind_mods[0])); iter++) { + for (iter = 0; iter < nitems(bind_mods); iter++) { if ((tmp = strchr(name, bind_mods[iter].chr)) != NULL && tmp < substring) { current_binding->modmask |= diff --git a/input.c b/input.c deleted file mode 100644 index 35931b6..0000000 --- a/input.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * calmwm - the calm window manager - * - * Copyright (c) 2004 Marius Aamodt Eriksen - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id$ - */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "calmwm.h" - -int -input_keycodetrans(KeyCode kc, u_int state, enum ctltype *ctl, char *chr) -{ - int ks; - - *ctl = CTL_NONE; - *chr = '\0'; - - ks = XKeycodeToKeysym(X_Dpy, kc, (state & ShiftMask) ? 1 : 0); - - /* Look for control characters. */ - switch (ks) { - case XK_BackSpace: - *ctl = CTL_ERASEONE; - break; - case XK_Return: - *ctl = CTL_RETURN; - break; - case XK_Up: - *ctl = CTL_UP; - break; - case XK_Down: - *ctl = CTL_DOWN; - break; - case XK_Escape: - *ctl = CTL_ABORT; - break; - } - - if (*ctl == CTL_NONE && (state & ControlMask)) { - switch (ks) { - case XK_s: - case XK_S: - /* Emacs "next" */ - *ctl = CTL_DOWN; - break; - case XK_r: - case XK_R: - /* Emacs "previous" */ - *ctl = CTL_UP; - break; - case XK_u: - case XK_U: - *ctl = CTL_WIPE; - break; - case XK_h: - case XK_H: - *ctl = CTL_ERASEONE; - break; - case XK_a: - case XK_A: - *ctl = CTL_ALL; - break; - } - } - - if (*ctl == CTL_NONE && (state & Mod1Mask)) { - switch (ks) { - case XK_j: - case XK_J: - /* Vi "down" */ - *ctl = CTL_DOWN; - break; - case XK_k: - case XK_K: - /* Vi "up" */ - *ctl = CTL_UP; - break; - } - } - - if (*ctl != CTL_NONE) - return (0); - - /* - * For regular characters, only (part of, actually) Latin 1 - * for now. - */ - if (ks < 0x20 || ks > 0x07e) - return (-1); - - *chr = (char)ks; - - return (0); -} diff --git a/menu.c b/menu.c index 6b462be..e757665 100644 --- a/menu.c +++ b/menu.c @@ -30,6 +30,12 @@ #define PROMPT_SCHAR '»' #define PROMPT_ECHAR '«' +enum ctltype { + CTL_NONE = -1, + CTL_ERASEONE = 0, CTL_WIPE, CTL_UP, CTL_DOWN, CTL_RETURN, + CTL_ABORT, CTL_ALL +}; + struct menu_ctx { char searchstr[MENU_MAXENTRY + 1]; char dispstr[MENU_MAXENTRY*2 + 1]; @@ -58,6 +64,8 @@ static void menu_draw(struct screen_ctx *, struct menu_ctx *, struct menu_q *, struct menu_q *); static int menu_calc_entry(struct screen_ctx *, struct menu_ctx *, int, int); +static int menu_keycode(KeyCode, u_int, enum ctltype *, + char *); void menu_init(struct screen_ctx *sc) @@ -89,6 +97,7 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt, XEvent e; Window focuswin; int evmask, focusrevert; + int xsave, ysave, xcur, ycur; TAILQ_INIT(&resultq); @@ -96,6 +105,9 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt, xu_ptr_getpos(sc->rootwin, &mc.x, &mc.y); + xsave = mc.x; + ysave = mc.y; + if (prompt == NULL) { evmask = MenuMask; mc.promptstr[0] = '\0'; @@ -142,8 +154,6 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt, XWindowEvent(X_Dpy, sc->menuwin, evmask, &e); switch (e.type) { - default: - break; case KeyPress: if ((mi = menu_handle_key(&e, &mc, menuq, &resultq)) != NULL) @@ -160,16 +170,23 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt, != NULL) goto out; break; + default: + break; } } out: - if (dummy == 0 && mi->dummy) { /* no match */ - xfree (mi); + if (dummy == 0 && mi->dummy) { /* no mouse based match */ + xfree(mi); mi = NULL; - xu_ptr_ungrab(); - XSetInputFocus(X_Dpy, focuswin, focusrevert, CurrentTime); } + 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); @@ -185,8 +202,7 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq, char chr; size_t len; - if (input_keycodetrans(e->xkey.keycode, e->xkey.state, - &ctl, &chr) < 0) + if (menu_keycode(e->xkey.keycode, e->xkey.state, &ctl, &chr) < 0) return (NULL); switch (ctl) { @@ -349,7 +365,7 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq, n++; } - if (mc->hasprompt && n > 1) + if (mc->hasprompt && n > 1 && (mc->searchstr[0] != '\0')) XFillRectangle(X_Dpy, sc->menuwin, sc->gc, 0, font_height(sc), mc->width, font_height(sc)); @@ -383,7 +399,6 @@ menu_handle_release(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc, int entry, i = 0; entry = menu_calc_entry(sc, mc, e->xbutton.x, e->xbutton.y); - xu_ptr_ungrab(); if (mc->hasprompt) i = 1; @@ -416,3 +431,89 @@ menu_calc_entry(struct screen_ctx *sc, struct menu_ctx *mc, int x, int y) return (entry); } + +static int +menu_keycode(KeyCode kc, u_int state, enum ctltype *ctl, char *chr) +{ + int ks; + + *ctl = CTL_NONE; + *chr = '\0'; + + ks = XKeycodeToKeysym(X_Dpy, kc, (state & ShiftMask) ? 1 : 0); + + /* Look for control characters. */ + switch (ks) { + case XK_BackSpace: + *ctl = CTL_ERASEONE; + break; + case XK_Return: + *ctl = CTL_RETURN; + break; + case XK_Up: + *ctl = CTL_UP; + break; + case XK_Down: + *ctl = CTL_DOWN; + break; + case XK_Escape: + *ctl = CTL_ABORT; + break; + } + + if (*ctl == CTL_NONE && (state & ControlMask)) { + switch (ks) { + case XK_s: + case XK_S: + /* Emacs "next" */ + *ctl = CTL_DOWN; + break; + case XK_r: + case XK_R: + /* Emacs "previous" */ + *ctl = CTL_UP; + break; + case XK_u: + case XK_U: + *ctl = CTL_WIPE; + break; + case XK_h: + case XK_H: + *ctl = CTL_ERASEONE; + break; + case XK_a: + case XK_A: + *ctl = CTL_ALL; + break; + } + } + + if (*ctl == CTL_NONE && (state & Mod1Mask)) { + switch (ks) { + case XK_j: + case XK_J: + /* Vi "down" */ + *ctl = CTL_DOWN; + break; + case XK_k: + case XK_K: + /* Vi "up" */ + *ctl = CTL_UP; + break; + } + } + + if (*ctl != CTL_NONE) + return (0); + + /* + * For regular characters, only (part of, actually) Latin 1 + * for now. + */ + if (ks < 0x20 || ks > 0x07e) + return (-1); + + *chr = (char)ks; + + return (0); +} diff --git a/mousefunc.c b/mousefunc.c index 5c14062..074f090 100644 --- a/mousefunc.c +++ b/mousefunc.c @@ -106,8 +106,8 @@ mousefunc_window_resize(struct client_ctx *cc, void *arg) /* Recompute window output */ mousefunc_sweep_draw(cc); - /* don't sync more than 60 times / second */ - if ((ev.xmotion.time - time) > (1000 / 60)) { + /* don't sync more than 10 times / second */ + if ((ev.xmotion.time - time) > (1000 / 10)) { time = ev.xmotion.time; XSync(X_Dpy, False); client_resize(cc); @@ -128,7 +128,6 @@ mousefunc_window_resize(struct client_ctx *cc, void *arg) if (cc->ptr.y > cc->geom.height) cc->ptr.y = cc->geom.height - cc->bwidth; client_ptrwarp(cc); - return; } } diff --git a/screen.c b/screen.c index a58ece4..da3b3c5 100644 --- a/screen.c +++ b/screen.c @@ -101,8 +101,8 @@ screen_find_xinerama(struct screen_ctx *sc, int x, int y) for (i = 0; i < sc->xinerama_no; i++) { info = &sc->xinerama[i]; - if (x > info->x_org && x < info->x_org + info->width && - y > info->y_org && y < info->y_org + info->height) + if (x >= info->x_org && x < info->x_org + info->width && + y >= info->y_org && y < info->y_org + info->height) return (info); } return (NULL); diff --git a/search.c b/search.c index 8cd6523..7d39884 100644 --- a/search.c +++ b/search.c @@ -42,9 +42,6 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search) { struct winname *wn; struct menu *mi, *tierp[4], *before = NULL; - int ntiers; - - ntiers = sizeof(tierp) / sizeof(tierp[0]); TAILQ_INIT(resultq); @@ -92,14 +89,14 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search) * window. Furthermore, this is denoted by a "!" when * printing the window name in the search menu. */ - if (cc == client_current() && tier < ntiers - 1) + if (cc == client_current() && tier < nitems(tierp) - 1) tier++; /* Clients that are hidden get ranked one up. */ if (cc->flags & CLIENT_HIDDEN && tier > 0) tier--; - assert(tier < ntiers); + assert(tier < nitems(tierp)); /* * If you have a tierp, insert after it, and make it diff --git a/xevents.c b/xevents.c index 3735d40..6af3fc2 100644 --- a/xevents.c +++ b/xevents.c @@ -167,7 +167,7 @@ xev_handle_configurerequest(XEvent *ee) wc.border_width = cc->bwidth; XConfigureWindow(X_Dpy, cc->win, e->value_mask, &wc); - xev_reconfig(cc); + xu_configure(cc); } else { /* let it do what it wants, it'll be ours when we map it. */ wc.x = e->x; @@ -214,25 +214,6 @@ test: } -void -xev_reconfig(struct client_ctx *cc) -{ - XConfigureEvent ce; - - ce.type = ConfigureNotify; - ce.event = cc->win; - ce.window = cc->win; - ce.x = cc->geom.x; - ce.y = cc->geom.y; - ce.width = cc->geom.width; - ce.height = cc->geom.height; - ce.border_width = cc->bwidth; - ce.above = None; - ce.override_redirect = 0; - - XSendEvent(X_Dpy, cc->win, False, StructureNotifyMask, (XEvent *)&ce); -} - static void xev_handle_enternotify(XEvent *ee) { @@ -430,7 +411,6 @@ xev_handle_expose(XEvent *ee) client_draw_border(cc); } - volatile sig_atomic_t _xev_quit = 0; void diff --git a/xutil.c b/xutil.c index c57bea7..76a3fce 100644 --- a/xutil.c +++ b/xutil.c @@ -57,7 +57,7 @@ void xu_btn_grab(Window win, int mask, u_int btn) { int i; - for (i = 0; i < sizeof(ign_mods)/sizeof(*ign_mods); i++) + for (i = 0; i < nitems(ign_mods); i++) XGrabButton(X_Dpy, btn, (mask | ign_mods[i]), win, False, ButtonMask, GrabModeAsync, GrabModeSync, None, None); @@ -67,7 +67,7 @@ void xu_btn_ungrab(Window win, int mask, u_int btn) { int i; - for (i = 0; i < sizeof(ign_mods)/sizeof(*ign_mods); i++) + for (i = 0; i < nitems(ign_mods); i++) XUngrabButton(X_Dpy, btn, (mask | ign_mods[i]), win); } @@ -98,7 +98,7 @@ xu_key_grab(Window win, int mask, int keysym) (XKeycodeToKeysym(X_Dpy, code, 1) == keysym)) mask |= ShiftMask; - for (i = 0; i < sizeof(ign_mods)/sizeof(*ign_mods); i++) + for (i = 0; i < nitems(ign_mods); i++) XGrabKey(X_Dpy, code, (mask | ign_mods[i]), win, True, GrabModeAsync, GrabModeAsync); } @@ -114,10 +114,29 @@ xu_key_ungrab(Window win, int mask, int keysym) (XKeycodeToKeysym(X_Dpy, code, 1) == keysym)) mask |= ShiftMask; - for (i = 0; i < sizeof(ign_mods)/sizeof(*ign_mods); i++) + for (i = 0; i < nitems(ign_mods); i++) XUngrabKey(X_Dpy, code, (mask | ign_mods[i]), win); } +void +xu_configure(struct client_ctx *cc) +{ + XConfigureEvent ce; + + ce.type = ConfigureNotify; + ce.event = cc->win; + ce.window = cc->win; + ce.x = cc->geom.x; + ce.y = cc->geom.y; + ce.width = cc->geom.width; + ce.height = cc->geom.height; + ce.border_width = cc->bwidth; + ce.above = None; + ce.override_redirect = 0; + + XSendEvent(X_Dpy, cc->win, False, StructureNotifyMask, (XEvent *)&ce); +} + void xu_sendmsg(Window win, Atom atm, long val) {