From 7071261bde1d100629765ca179a6e8ee662569a6 Mon Sep 17 00:00:00 2001 From: okan Date: Tue, 7 Aug 2012 14:05:49 +0000 Subject: [PATCH 1/5] support multibyte input to menu code; from Alexander Polakov with a tiny tweak. --- calmwm.c | 5 +++++ menu.c | 40 +++++++++++++++++++--------------------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/calmwm.c b/calmwm.c index 911c280..cce800d 100644 --- a/calmwm.c +++ b/calmwm.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,10 @@ main(int argc, char **argv) char *display_name = NULL; int ch; + if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + warnx("no locale support"); + mbtowc(NULL, NULL, MB_CUR_MAX); + while ((ch = getopt(argc, argv, "c:d:")) != -1) { switch (ch) { case 'c': diff --git a/menu.c b/menu.c index 58ed618..29008e6 100644 --- a/menu.c +++ b/menu.c @@ -68,7 +68,7 @@ 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 *, +static int menu_keycode(XKeyEvent *, enum ctltype *, char *); void @@ -208,16 +208,22 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq, { struct menu *mi; enum ctltype ctl; - char chr; + char chr[32]; size_t len; + int clen, i; + wchar_t wc; - if (menu_keycode(e->xkey.keycode, e->xkey.state, &ctl, &chr) < 0) + if (menu_keycode(&e->xkey, &ctl, chr) < 0) return (NULL); switch (ctl) { case CTL_ERASEONE: if ((len = strlen(mc->searchstr)) > 0) { - mc->searchstr[len - 1] = '\0'; + clen = 1; + while (mbtowc(&wc, &mc->searchstr[len-clen], MB_CUR_MAX) == -1) + clen++; + for (i = 1; i <= clen; i++) + mc->searchstr[len - i] = '\0'; mc->changed = 1; } break; @@ -267,13 +273,9 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq, break; } - if (chr != '\0') { - char str[2]; - - str[0] = chr; - str[1] = '\0'; + if (chr[0] != '\0') { mc->changed = 1; - (void)strlcat(mc->searchstr, str, sizeof(mc->searchstr)); + (void)strlcat(mc->searchstr, chr, sizeof(mc->searchstr)); } mc->noresult = 0; @@ -459,14 +461,16 @@ menu_calc_entry(struct screen_ctx *sc, struct menu_ctx *mc, int x, int y) } static int -menu_keycode(KeyCode kc, u_int state, enum ctltype *ctl, char *chr) +menu_keycode(XKeyEvent *ev, enum ctltype *ctl, char *chr) { - int ks; + KeySym ks; + u_int state = ev->state; *ctl = CTL_NONE; - *chr = '\0'; + chr[0] = '\0'; - ks = XkbKeycodeToKeysym(X_Dpy, kc, 0, (state & ShiftMask) ? 1 : 0); + ks = XkbKeycodeToKeysym(X_Dpy, ev->keycode, 0, + (state & ShiftMask) ? 1 : 0); /* Look for control characters. */ switch (ks) { @@ -532,14 +536,8 @@ menu_keycode(KeyCode kc, u_int state, enum ctltype *ctl, char *chr) if (*ctl != CTL_NONE) return (0); - /* - * For regular characters, only (part of, actually) Latin 1 - * for now. - */ - if (ks < 0x20 || ks > 0x07e) + if (XLookupString(ev, chr, 32, &ks, NULL) < 0) return (-1); - *chr = (char)ks; - return (0); } From 86524e21dd53bad45f4586a7cc856062b67f8033 Mon Sep 17 00:00:00 2001 From: okan Date: Sun, 9 Sep 2012 19:47:47 +0000 Subject: [PATCH 2/5] extend client_resize so that it can know when to reset max flags and bwidth; this allows a client to be resized from a max state, which now gets treated like a non-max'd client. based on a diff that does part of this in a different way from Alexander Polakov. --- calmwm.h | 2 +- client.c | 13 +++++++++---- kbfunc.c | 2 +- mousefunc.c | 4 ++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/calmwm.h b/calmwm.h index 849a945..e193dd8 100644 --- a/calmwm.h +++ b/calmwm.h @@ -327,7 +327,7 @@ struct client_ctx *client_new(Window, struct screen_ctx *, int); void client_ptrsave(struct client_ctx *); void client_ptrwarp(struct client_ctx *); void client_raise(struct client_ctx *); -void client_resize(struct client_ctx *); +void client_resize(struct client_ctx *, int); void client_send_delete(struct client_ctx *); void client_setactive(struct client_ctx *, int); void client_setname(struct client_ctx *); diff --git a/client.c b/client.c index 15052eb..8cb119f 100644 --- a/client.c +++ b/client.c @@ -306,7 +306,7 @@ client_maximize(struct client_ctx *cc) cc->flags |= CLIENT_MAXIMIZED; resize: - client_resize(cc); + client_resize(cc, 0); } void @@ -355,7 +355,7 @@ client_vertmaximize(struct client_ctx *cc) cc->flags |= CLIENT_VMAXIMIZED; resize: - client_resize(cc); + client_resize(cc, 0); } void @@ -404,12 +404,17 @@ client_horizmaximize(struct client_ctx *cc) cc->flags |= CLIENT_HMAXIMIZED; resize: - client_resize(cc); + client_resize(cc, 0); } void -client_resize(struct client_ctx *cc) +client_resize(struct client_ctx *cc, int reset) { + if (reset) { + cc->flags &= ~CLIENT_MAXIMIZED; + cc->bwidth = Conf.bwidth; + } + client_draw_border(cc); XMoveResizeWindow(X_Dpy, cc->win, cc->geom.x, diff --git a/kbfunc.c b/kbfunc.c index 0f95df4..2b26416 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -117,7 +117,7 @@ kbfunc_moveresize(struct client_ctx *cc, union arg *arg) cc->geom.h = 1; if ((cc->geom.w += mx) < 1) cc->geom.w = 1; - client_resize(cc); + client_resize(cc, 1); /* Make sure the pointer stays within the window. */ xu_ptr_getpos(cc->win, &cc->ptr.x, &cc->ptr.y); diff --git a/mousefunc.c b/mousefunc.c index b0bd40f..c615052 100644 --- a/mousefunc.c +++ b/mousefunc.c @@ -110,12 +110,12 @@ mousefunc_window_resize(struct client_ctx *cc, void *arg) /* don't resize more than 60 times / second */ if ((ev.xmotion.time - ltime) > (1000 / 60)) { ltime = ev.xmotion.time; - client_resize(cc); + client_resize(cc, 1); } break; case ButtonRelease: if (ltime) - client_resize(cc); + client_resize(cc, 1); XUnmapWindow(X_Dpy, sc->menuwin); XReparentWindow(X_Dpy, sc->menuwin, sc->rootwin, 0, 0); xu_ptr_ungrab(); From 3a45879d76f1fb222417a83d312fba42ae2eadf6 Mon Sep 17 00:00:00 2001 From: okan Date: Sun, 9 Sep 2012 20:52:57 +0000 Subject: [PATCH 3/5] replace with xu_getprop wrapper used everywhere else. --- group.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/group.c b/group.c index f28640c..3370643 100644 --- a/group.c +++ b/group.c @@ -458,18 +458,12 @@ group_update_names(struct screen_ctx *sc) { char **strings, *p; unsigned char *prop_ret; - Atom type_ret; - int format_ret, i = 0, nstrings = 0, n = 0, setnames = 0; - unsigned long bytes_after, num_ret; + int i = 0, j = 0, nstrings = 0, n = 0, setnames = 0; - if (XGetWindowProperty(X_Dpy, sc->rootwin, - ewmh[_NET_DESKTOP_NAMES].atom, 0, 0xffffff, False, - cwmh[UTF8_STRING].atom, &type_ret, &format_ret, - &num_ret, &bytes_after, &prop_ret) == Success && - prop_ret != NULL && format_ret == 8) { - /* failure, just set defaults */ - prop_ret[num_ret - 1] = '\0'; /* paranoia */ - while (i < num_ret) { + if ((j = xu_getprop(sc->rootwin, ewmh[_NET_DESKTOP_NAMES].atom, + cwmh[UTF8_STRING].atom, 0xffffff, (u_char **)&prop_ret)) > 0) { + prop_ret[j - 1] = '\0'; /* paranoia */ + while (i < j) { if (prop_ret[i++] == '\0') nstrings++; } From 637edf38d51024ba88184b1457640f8fa459e693 Mon Sep 17 00:00:00 2001 From: okan Date: Mon, 10 Sep 2012 13:28:04 +0000 Subject: [PATCH 4/5] be explicit in which key masks we allow during keypress and buttonpress events; from Alexander Polakov - makes non-us layout reliable. --- xevents.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xevents.c b/xevents.c index eddf4fe..a155614 100644 --- a/xevents.c +++ b/xevents.c @@ -240,8 +240,8 @@ xev_handle_buttonpress(XEvent *ee) sc = screen_fromroot(e->root); cc = client_find(e->window); - /* Ignore caps lock and numlock */ - e->state &= ~(Mod2Mask | LockMask); + /* only allow the ones we care about */ + e->state &= (ControlMask | Mod1Mask | Mod4Mask | ShiftMask); TAILQ_FOREACH(mb, &Conf.mousebindingq, entry) { if (e->button == mb->button && e->state == mb->modmask) @@ -282,8 +282,8 @@ xev_handle_keypress(XEvent *ee) keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0); skeysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 1); - /* we don't care about caps lock and numlock here */ - e->state &= ~(LockMask | Mod2Mask); + /* only allow the ones we care about */ + e->state &= (ControlMask | Mod1Mask | Mod4Mask | ShiftMask); TAILQ_FOREACH(kb, &Conf.keybindingq, entry) { if (keysym != kb->keysym && skeysym == kb->keysym) From 871fdf56715dbc85b2ad4f058366a06a66615c65 Mon Sep 17 00:00:00 2001 From: okan Date: Wed, 12 Sep 2012 15:09:33 +0000 Subject: [PATCH 5/5] revert previous for now until a way to test more than a few encodings is found --- xevents.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xevents.c b/xevents.c index a155614..eddf4fe 100644 --- a/xevents.c +++ b/xevents.c @@ -240,8 +240,8 @@ xev_handle_buttonpress(XEvent *ee) sc = screen_fromroot(e->root); cc = client_find(e->window); - /* only allow the ones we care about */ - e->state &= (ControlMask | Mod1Mask | Mod4Mask | ShiftMask); + /* Ignore caps lock and numlock */ + e->state &= ~(Mod2Mask | LockMask); TAILQ_FOREACH(mb, &Conf.mousebindingq, entry) { if (e->button == mb->button && e->state == mb->modmask) @@ -282,8 +282,8 @@ xev_handle_keypress(XEvent *ee) keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0); skeysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 1); - /* only allow the ones we care about */ - e->state &= (ControlMask | Mod1Mask | Mod4Mask | ShiftMask); + /* we don't care about caps lock and numlock here */ + e->state &= ~(LockMask | Mod2Mask); TAILQ_FOREACH(kb, &Conf.keybindingq, entry) { if (keysym != kb->keysym && skeysym == kb->keysym)