diff --git a/bench/main.c b/bench/main.c index a252b2d..ae84614 100644 --- a/bench/main.c +++ b/bench/main.c @@ -128,10 +128,10 @@ sendkey(int key, int mod) static int readresp(void) { - char buf[Ipcfieldmax+1]; + char commit[Ipcfieldmax+1], preedit[Ipcfieldmax+1]; Ipcresp resp; - return ipcreadresp(fd, 0, buf, sizeof buf, NULL, 0, &resp); + return ipcreadresp(fd, 0, commit, preedit, &resp); } static double diff --git a/gtk/main.c b/gtk/main.c index 4ccfbab..6c3d53f 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -19,7 +18,6 @@ struct Im int ext; int private; int simpleactive; - int insimple; int simpledone; char pre[Ipcfieldmax+1]; int prelen; @@ -27,10 +25,7 @@ struct Im GdkRectangle cursor; int cursorvalid; int caretsent; - int sentvalid; - int32_t sentx; - int32_t senty; - int32_t senth; + unsigned char sent[Ipccaretsz]; }; typedef struct ImClass ImClass; @@ -86,22 +81,14 @@ srvclose(Im *im) srvdrop(im, 1); } +/* Both buffers are char[Ipcfieldmax+1]. */ static int -validtext(const char *s, size_t n) +readresp(Im *im, int want, char *commit, char *pre, Ipcresp *resp) { - return s[n] == '\0' && memchr(s, '\0', n) == NULL && - g_utf8_validate(s, n, NULL); -} - -static int -readresp(Im *im, int want, char *commit, int ncommit, char *pre, int npre, - Ipcresp *resp) -{ - if(ipcreadresp(im->fd, want, commit, ncommit, pre, npre, - resp) < 0) + if(ipcreadresp(im->fd, want, commit, pre, resp) < 0) return -1; - if(!validtext(commit, resp->commitlen) || - (want && !validtext(pre, resp->preeditlen))){ + if(!g_utf8_validate(commit, resp->commitlen, NULL) || + (want && !g_utf8_validate(pre, resp->preeditlen, NULL))){ errno = EPROTO; return -1; } @@ -117,76 +104,58 @@ dropwindow(Im *im) im->cursorvalid = 0; } +/* Root-relative caret in device pixels; returns whether it is known. */ static int -caretget(Im *im, int *valid, int32_t *x, int32_t *y, int32_t *h) +caretget(Im *im, int32_t *x, int32_t *y, int32_t *h) { gint rx, ry, scale; int64_t sx, sy, sh; - *valid = 0; *x = *y = *h = 0; if(im->win != NULL && gdk_window_is_destroyed(im->win)) dropwindow(im); - if(!im->cursorvalid || im->win == NULL){ - im->cursorvalid = 0; + if(!im->cursorvalid || im->win == NULL || im->cursor.height < 0) return 0; - } #ifdef GDK_WINDOWING_X11 - if(!GDK_IS_X11_WINDOW(im->win)){ - im->cursorvalid = 0; + if(!GDK_IS_X11_WINDOW(im->win)) return 0; - } #else - im->cursorvalid = 0; return 0; #endif - if(im->cursor.height < 0){ - im->cursorvalid = 0; - return 0; - } scale = gdk_window_get_scale_factor(im->win); - if(scale <= 0){ - im->cursorvalid = 0; + if(scale <= 0) return 0; - } /* GDK translates the client-relative point before device scaling. */ gdk_window_get_root_coords(im->win, 0, 0, &rx, &ry); sx = ((int64_t)rx + im->cursor.x) * scale; sy = ((int64_t)ry + im->cursor.y) * scale; sh = (int64_t)im->cursor.height * scale; if(sx < INT32_MIN || sx > INT32_MAX || - sy < INT32_MIN || sy > INT32_MAX || sh > INT32_MAX){ - im->cursorvalid = 0; + sy < INT32_MIN || sy > INT32_MAX || sh > INT32_MAX) return 0; - } - *valid = 1; *x = sx; *y = sy; *h = sh; - return 0; + return 1; } static int sendcaret(Im *im) { unsigned char buf[Ipccaretsz]; - int valid; int32_t x, y, h; + int valid; if(im->fd < 0 || !im->ext) return 0; - caretget(im, &valid, &x, &y, &h); - if(im->caretsent && valid == im->sentvalid && - (!valid || (x == im->sentx && y == im->senty && h == im->senth))) + valid = caretget(im, &x, &y, &h); + ipcpackcaret(buf, valid, x, y, h); + if(im->caretsent && memcmp(buf, im->sent, sizeof buf) == 0) return 0; - if(ipcpackcaret(buf, valid, x, y, h) < 0 || - ipcsend(im->fd, buf, sizeof buf) < 0) + if(ipcsend(im->fd, buf, sizeof buf) < 0) return -1; + memcpy(im->sent, buf, sizeof buf); im->caretsent = 1; - im->sentvalid = valid; - im->sentx = x; - im->senty = y; - im->senth = h; return 0; } @@ -206,17 +175,12 @@ srvconnect(Im *im) /* Marker zero is an old daemon's harmless key-zero response. */ ipcpackcap(buf, im->usepreedit); if(ipcsend(im->fd, buf, sizeof buf) < 0 || - readresp(im, im->usepreedit, commit, sizeof commit, - pre, sizeof pre, &resp) < 0){ + readresp(im, im->usepreedit, commit, pre, &resp) < 0){ srvclose(im); return -1; } - if(im->usepreedit) - setpreedit(im, pre, resp.preeditlen); im->ext = resp.eaten != 0; - if(!im->usepreedit) - setpreedit(im, "", 0); - if(im->ext && sendcaret(im) < 0){ + if(sendcaret(im) < 0){ srvclose(im); return -1; } @@ -228,18 +192,20 @@ simplecommit(GtkIMContext *ctx, const char *s, Im *im) { (void)ctx; (void)s; - if(im->insimple) - im->simpledone = 1; + im->simpledone = 1; } static void simpleend(GtkIMContext *ctx, Im *im) { (void)ctx; - if(im->insimple) - im->simpledone = 1; + im->simpledone = 1; } +/* + * GtkIMContextSimple composes dead keys and Compose sequences; it keeps + * the key stream until it commits, ends its preedit, or rejects a press. + */ static gboolean simplefilter(GtkIMContext *ctx, GdkEventKey *ev, int release) { @@ -249,9 +215,7 @@ simplefilter(GtkIMContext *ctx, GdkEventKey *ev, int release) im = (Im*)ctx; im->simpleactive = 1; im->simpledone = 0; - im->insimple = 1; r = parentim->filter_keypress(ctx, ev); - im->insimple = 0; if((!r && !release) || im->simpledone) im->simpleactive = 0; return r; @@ -271,8 +235,7 @@ sendreset(Im *im) } ipcpackreset(buf, im->usepreedit); if(ipcsend(im->fd, buf, sizeof buf) < 0 || - readresp(im, im->usepreedit, commit, sizeof commit, - pre, sizeof pre, &resp) < 0){ + readresp(im, im->usepreedit, commit, pre, &resp) < 0){ srvclose(im); return; } @@ -297,7 +260,7 @@ kpress(GtkIMContext *ctx, GdkEventKey *ev) } if(im->simpleactive) return simplefilter(ctx, ev, 0); - key = ipckey(ev->keyval, gdk_keyval_to_unicode(ev->keyval)); + key = ipckeysym(ev->keyval, gdk_keyval_to_unicode(ev->keyval)); mod = ipcmod(ev->state); if(im->private || key == 0) return simplefilter(ctx, ev, 0); @@ -310,8 +273,7 @@ kpress(GtkIMContext *ctx, GdkEventKey *ev) } ipcpackreq(buf, im->usepreedit, mod, key); if(ipcsend(im->fd, buf, sizeof buf) < 0 || - readresp(im, im->usepreedit, commit, sizeof commit, - pre, sizeof pre, &resp) < 0){ + readresp(im, im->usepreedit, commit, pre, &resp) < 0){ srvclose(im); return simplefilter(ctx, ev, 0); } @@ -371,8 +333,7 @@ focusout(GtkIMContext *ctx) if(parentim->focus_out != NULL) parentim->focus_out(ctx); im->simpleactive = 0; - sendreset(im); - /* Closing the context connection releases engine ownership. */ + /* Closing the connection releases the engine, which resets it. */ srvclose(im); } @@ -398,8 +359,7 @@ setusepreedit(GtkIMContext *ctx, gboolean use) return; ipcpackcap(buf, use); if(ipcsend(im->fd, buf, sizeof buf) < 0 || - readresp(im, use, commit, sizeof commit, - pre, sizeof pre, &resp) < 0 || + readresp(im, use, commit, pre, &resp) < 0 || !resp.eaten){ srvclose(im); return; diff --git a/ibus.c b/ibus.c index 0ee1430..911d852 100644 --- a/ibus.c +++ b/ibus.c @@ -358,7 +358,7 @@ processkey(Ictx *ctx, u32int sym, u32int state, Keyres *res) { if(state & Relmask || !ctx->focused || hidden(ctx)) return 0; - sendrequest(ctx, Keypress, ipckey(sym, xkb_keysym_to_utf32(sym)), + sendrequest(ctx, Keypress, ipckeysym(sym, xkb_keysym_to_utf32(sym)), ipcmod(state), res); if(preowner != nil && preowner != ctx) checkpreowner(); diff --git a/ipc.c b/ipc.c index 8f48695..5011571 100644 --- a/ipc.c +++ b/ipc.c @@ -1,7 +1,6 @@ #define _POSIX_C_SOURCE 200809L #include -#include #include #include #include @@ -17,57 +16,32 @@ nowms(void) { struct timespec ts; - if(clock_gettime(CLOCK_MONOTONIC, &ts) < 0) - return -1; + clock_gettime(CLOCK_MONOTONIC, &ts); return (int64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000; } static int64_t deadline(void) { - int64_t now; - - now = nowms(); - if(now < 0) - return -1; - return now + Ipcwaitms; -} - -static int -checkdeadline(int64_t until) -{ - int64_t now; - - now = nowms(); - if(now < 0) - return -1; - if(now >= until){ - errno = ETIMEDOUT; - return -1; - } - return 0; + return nowms() + Ipcwaitms; } static int waitfd(int fd, short events, int64_t until) { struct pollfd pfd; - int64_t now, left; + int64_t left; int n; pfd.fd = fd; pfd.events = events; for(;;){ - now = nowms(); - if(now < 0) - return -1; - left = until - now; + left = until - nowms(); if(left <= 0){ errno = ETIMEDOUT; return -1; } - pfd.revents = 0; - n = poll(&pfd, 1, left > INT32_MAX ? INT32_MAX : (int)left); + n = poll(&pfd, 1, left); if(n < 0 && errno == EINTR) continue; if(n < 0) @@ -76,12 +50,7 @@ waitfd(int fd, short events, int64_t until) errno = ETIMEDOUT; return -1; } - if(pfd.revents & POLLNVAL){ - errno = EBADF; - return -1; - } - if(pfd.revents & (events|POLLERR|POLLHUP)) - return 0; + return 0; } } @@ -93,8 +62,6 @@ readwait(int fd, void *buf, size_t n, int64_t until) p = buf; while(n > 0){ - if(checkdeadline(until) < 0) - return -1; r = recv(fd, p, n, MSG_DONTWAIT); if(r < 0 && errno == EINTR) continue; @@ -143,15 +110,10 @@ put32(unsigned char *p, int32_t v) static int32_t get32(const unsigned char *p) { - uint32_t u; - - u = (uint32_t)p[0] | + return (int32_t)((uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) | - ((uint32_t)p[3] << 24); - if(u <= INT32_MAX) - return u; - return -(int32_t)(~u) - 1; + ((uint32_t)p[3] << 24)); } int @@ -160,8 +122,6 @@ ipcpath(char *dst, size_t cap) const char *dir, *sep; int n; - if(dst == NULL || cap == 0) - return -1; dir = getenv("XDG_RUNTIME_DIR"); if(dir != NULL && dir[0] == '/'){ sep = dir[strlen(dir)-1] == '/' ? "" : "/"; @@ -174,13 +134,16 @@ ipcpath(char *dst, size_t cap) return 0; } +/* + * A nonblocking AF_UNIX connect completes at once or fails with EAGAIN + * when the daemon's backlog is full; the socket stays nonblocking because + * every transfer below polls with a deadline. + */ int ipcconnect(void) { struct sockaddr_un addr; - socklen_t nerr; - int e, err, fd, fdflags, flags; - int64_t until; + int e, fd; memset(&addr, 0, sizeof addr); addr.sun_family = AF_UNIX; @@ -188,39 +151,16 @@ ipcconnect(void) errno = ENAMETOOLONG; return -1; } - fd = socket(AF_UNIX, SOCK_STREAM, 0); + fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if(fd < 0) return -1; - fdflags = fcntl(fd, F_GETFD); - if(fdflags < 0 || fcntl(fd, F_SETFD, fdflags|FD_CLOEXEC) < 0) - goto Bad; - flags = fcntl(fd, F_GETFL); - if(flags < 0 || fcntl(fd, F_SETFL, flags|O_NONBLOCK) < 0) - goto Bad; - until = deadline(); - if(until < 0) - goto Bad; if(connect(fd, (struct sockaddr*)&addr, sizeof addr) < 0){ - if(errno != EINPROGRESS && errno != EALREADY && errno != EINTR) - goto Bad; - if(waitfd(fd, POLLOUT, until) < 0) - goto Bad; - nerr = sizeof err; - if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &nerr) < 0) - goto Bad; - if(err != 0){ - errno = err; - goto Bad; - } + e = errno; + close(fd); + errno = e; + return -1; } - if(fcntl(fd, F_SETFL, flags) < 0) - goto Bad; return fd; -Bad: - e = errno; - close(fd); - errno = e; - return -1; } /* @@ -228,7 +168,7 @@ Bad: * as themselves, the function keysyms 0xff00-0xffff as Kspec+offset. */ uint32_t -ipckey(uint32_t sym, uint32_t unicode) +ipckeysym(uint32_t sym, uint32_t unicode) { if(unicode >= ' ' && unicode != 0x7f) return unicode; @@ -277,25 +217,20 @@ ipcpackcap(unsigned char req[Ipcreqsz], int want) req[2] = Ipcopcap; } -int +void ipcpackcaret(unsigned char req[Ipccaretsz], int valid, int32_t x, int32_t y, int32_t h) { - if(valid != 0 && valid != 1) - return -1; - if(valid && h < 0) - return -1; memset(req, 0, Ipccaretsz); req[0] = Ipcext; req[1] = Ipcversion; req[2] = Ipcopcaret; - req[3] = valid; - if(!valid) - return 0; - put32(req + 4, x); - put32(req + 8, y); - put32(req + 12, h); - return 0; + req[3] = valid != 0; + if(valid){ + put32(req + 4, x); + put32(req + 8, y); + put32(req + 12, h); + } } void @@ -314,7 +249,7 @@ int ipcreqtype(const unsigned char req[Ipcreqsz]) { if((req[0] & Ipcext) == 0) - return Ipclegacy; + return Ipckey; if(req[1] != Ipcversion) return Ipcunknown; switch(req[2]){ @@ -335,24 +270,12 @@ int ipcunpackcaret(const unsigned char req[Ipccaretsz], int *valid, int32_t *x, int32_t *y, int32_t *h) { - int32_t wireh; - - if(valid == NULL || x == NULL || y == NULL || h == NULL || - ipcreqtype(req) != Ipccaret) - return -1; - wireh = get32(req + 12); - if(wireh < 0) + if(ipcreqtype(req) != Ipccaret || get32(req + 12) < 0) return -1; *valid = req[3]; - if(!*valid){ - *x = 0; - *y = 0; - *h = 0; - return 0; - } - *x = get32(req + 4); - *y = get32(req + 8); - *h = wireh; + *x = *valid ? get32(req + 4) : 0; + *y = *valid ? get32(req + 8) : 0; + *h = *valid ? get32(req + 12) : 0; return 0; } @@ -371,21 +294,15 @@ ipcpackresp(unsigned char *dst, size_t cap, int eaten, if(ncommit > Ipcfieldmax || npreedit > Ipcfieldmax) return -1; - if((ncommit > 0 && commit == NULL) || - (want && npreedit > 0 && preedit == NULL)) - return -1; n = Ipcresphdrsz + ncommit + (want ? Ipclensz + npreedit : 0); - if(dst == NULL || cap < n) + if(cap < n) return -1; dst[0] = eaten != 0; putlen(dst + 1, ncommit); - if(ncommit > 0) - memcpy(dst + Ipcresphdrsz, commit, ncommit); + memcpy(dst + Ipcresphdrsz, commit, ncommit); if(want){ putlen(dst + Ipcresphdrsz + ncommit, npreedit); - if(npreedit > 0) - memcpy(dst + Ipcresphdrsz + ncommit + Ipclensz, - preedit, npreedit); + memcpy(dst + Ipcresphdrsz + ncommit + Ipclensz, preedit, npreedit); } return n; } @@ -417,14 +334,8 @@ ipcsend(int fd, const void *buf, size_t n) int64_t until; p = buf; - if(n == 0) - return 0; until = deadline(); - if(until < 0) - return -1; while(n > 0){ - if(checkdeadline(until) < 0) - return -1; r = send(fd, p, n, MSG_NOSIGNAL|MSG_DONTWAIT); if(r < 0 && errno == EINTR) continue; @@ -445,73 +356,53 @@ ipcsend(int fd, const void *buf, size_t n) return 0; } +/* Reads a length-prefixed field into dst[Ipcfieldmax+1]. */ static int -readfield(int fd, size_t n, char *dst, size_t cap, size_t *copied, - int64_t until) +readfield(int fd, char *dst, int64_t until) { - unsigned char discard[128]; - size_t keep, part; + unsigned char len[Ipclensz]; + size_t n; - if(cap > 0 && dst == NULL) + if(readwait(fd, len, sizeof len, until) < 0) return -1; - keep = 0; - if(cap > 0) - keep = n >= cap ? cap - 1 : n; - if(keep > 0 && readwait(fd, dst, keep, until) < 0) + n = getlen(len); + if(n > Ipcfieldmax){ + errno = EPROTO; return -1; - if(cap > 0) - dst[keep] = '\0'; - n -= keep; - while(n > 0){ - part = n < sizeof discard ? n : sizeof discard; - if(readwait(fd, discard, part, until) < 0) - return -1; - n -= part; } - *copied = keep; - return 0; + if(readwait(fd, dst, n, until) < 0) + return -1; + dst[n] = '\0'; + return n; } int -ipcreadresp(int fd, int want, char *commit, size_t ccap, - char *preedit, size_t pcap, Ipcresp *resp) +ipcreadresp(int fd, int want, char *commit, char *preedit, Ipcresp *resp) { - unsigned char hdr[Ipcresphdrsz], npreedit[Ipclensz]; - size_t wirelen; + unsigned char eaten; int64_t until; + int n; - if(resp == NULL || (ccap > 0 && commit == NULL) || - (pcap > 0 && preedit == NULL)) - return -1; - if(ccap > 0) - commit[0] = '\0'; - if(pcap > 0) - preedit[0] = '\0'; + commit[0] = '\0'; + preedit[0] = '\0'; memset(resp, 0, sizeof *resp); until = deadline(); - if(until < 0 || readwait(fd, hdr, sizeof hdr, until) < 0) + if(readwait(fd, &eaten, 1, until) < 0) return -1; - if(hdr[0] > 1){ + if(eaten > 1){ errno = EPROTO; return -1; } - resp->eaten = hdr[0]; - wirelen = getlen(hdr + 1); - if(wirelen > Ipcfieldmax){ - errno = EPROTO; - return -1; - } - if(readfield(fd, wirelen, commit, ccap, &resp->commitlen, until) < 0) + resp->eaten = eaten; + n = readfield(fd, commit, until); + if(n < 0) return -1; + resp->commitlen = n; if(!want) return 0; - if(readwait(fd, npreedit, sizeof npreedit, until) < 0) + n = readfield(fd, preedit, until); + if(n < 0) return -1; - wirelen = getlen(npreedit); - if(wirelen > Ipcfieldmax){ - errno = EPROTO; - return -1; - } - return readfield(fd, wirelen, preedit, pcap, &resp->preeditlen, - until); + resp->preeditlen = n; + return 0; } diff --git a/ipc.h b/ipc.h index faea5ce..0cf6074 100644 --- a/ipc.h +++ b/ipc.h @@ -2,7 +2,7 @@ #include /* - * Legacy request: [flags, modifiers, key byte 0, ..., key byte 3]. + * Key request: [flags, modifiers, key byte 0, ..., key byte 3]. * Flags request preedit and distinguish lifecycle reset from physical Escape. * The server identifies the connection as the engine owner; that identity is * not sent on the wire. @@ -10,7 +10,8 @@ * Response: [eaten, commit-length-low, commit-length-high, commit...], * followed, when requested, by * [preedit-length-low, preedit-length-high, preedit...]. - * Lengths are little-endian byte counts; fields are at most Ipcfieldmax bytes. + * Lengths are little-endian byte counts; fields are at most Ipcfieldmax bytes, + * so callers read them into char[Ipcfieldmax+1]. * * Capability control is six bytes: [0x80|want, version, 0, 0, 0, 0]. * Caret control is sixteen bytes: [0x80, version, 1, valid, x, y, h], @@ -58,7 +59,7 @@ enum enum { Ipcunknown = -1, - Ipclegacy, + Ipckey, Ipccap, Ipccaret, }; @@ -72,12 +73,12 @@ struct Ipcresp size_t preeditlen; }; -uint32_t ipckey(uint32_t, uint32_t); +uint32_t ipckeysym(uint32_t, uint32_t); uint32_t ipcmod(uint32_t); void ipcpackreq(unsigned char[Ipcreqsz], int, uint32_t, uint32_t); void ipcpackreset(unsigned char[Ipcreqsz], int); void ipcpackcap(unsigned char[Ipcreqsz], int); -int ipcpackcaret(unsigned char[Ipccaretsz], int, int32_t, int32_t, int32_t); +void ipcpackcaret(unsigned char[Ipccaretsz], int, int32_t, int32_t, int32_t); void ipcunpackreq(const unsigned char[Ipcreqsz], int*, uint32_t*, uint32_t*); int ipcunpackcaret(const unsigned char[Ipccaretsz], int*, int32_t*, int32_t*, int32_t*); int ipcreqtype(const unsigned char[Ipcreqsz]); @@ -85,6 +86,6 @@ int ipcreqreset(const unsigned char[Ipcreqsz]); int ipcpackresp(unsigned char*, size_t, int, const char*, size_t, const char*, size_t, int); int ipcreadn(int, void*, size_t); int ipcsend(int, const void*, size_t); -int ipcreadresp(int, int, char*, size_t, char*, size_t, Ipcresp*); +int ipcreadresp(int, int, char*, char*, Ipcresp*); int ipcpath(char*, size_t); int ipcconnect(void); diff --git a/main.c b/main.c index 8310f52..169ac4e 100644 --- a/main.c +++ b/main.c @@ -61,17 +61,12 @@ threadmain(int argc, char **argv) mapinit(argv[1]); dictinit(argv[1]); srvinit(); - if(proccreate(drawthread, nil, 16384) < 0) - die("can't create draw worker"); - if(proccreate(srvthread, nil, 16384) < 0) - die("can't create server worker"); - if(proccreate(ibusthread, nil, 32768) < 0) - die("can't create IBus worker"); + proccreate(drawthread, nil, 16384); + proccreate(srvthread, nil, 16384); + proccreate(ibusthread, nil, 32768); display = getenv("DISPLAY"); - if(display != nil && display[0] != '\0' && - proccreate(ximthread, nil, 32768) < 0) - die("xim: cannot create worker"); - if(threadcreate(dictthread, nil, 16384) < 0) - die("can't create dictionary worker"); + if(display != nil && display[0] != '\0') + proccreate(ximthread, nil, 32768); + threadcreate(dictthread, nil, 16384); imthread(nil); } diff --git a/srv.c b/srv.c index 41e4cbe..24f684b 100644 --- a/srv.c +++ b/srv.c @@ -11,98 +11,78 @@ static int srvreadreq(int fd, Keyreq *kr, int *want) { uchar req[Ipccaretsz]; - int type, valid; + int valid; int32_t x, y, h; - u32int ks, mod; if(ipcreadn(fd, req, Ipcreqsz) < 0) return -1; - type = ipcreqtype(req); - switch(type){ - case Ipclegacy: - ipcunpackreq(req, want, &mod, &ks); + *want = 0; + kr->ks = 0; + kr->mod = 0; + switch(ipcreqtype(req)){ + case Ipckey: + ipcunpackreq(req, want, &kr->mod, &kr->ks); kr->op = ipcreqreset(req) ? Keyreset : Keypress; - kr->ks = ks; - kr->mod = mod; - break; + return 0; case Ipccap: *want = (req[0] & Ipcreqwant) != 0; kr->op = Keycap; - kr->ks = 0; - kr->mod = 0; - break; + return 0; case Ipccaret: if(ipcreadn(fd, req + Ipcreqsz, Ipccaretsz - Ipcreqsz) < 0 || ipcunpackcaret(req, &valid, &x, &y, &h) < 0) return -1; - *want = 0; kr->op = Keycaret; - kr->ks = 0; - kr->mod = 0; kr->caret.valid = valid; kr->caret.x = x; kr->caret.y = y; kr->caret.h = h; - break; - default: - return -1; + return 0; } - return type; + return -1; } +/* + * One Keyreq persists for the connection: the negotiated capability and + * the last caret ride along with every request, and the socket closing + * releases the engine. + */ static void clientthread(void *arg) { - Channel *reply; - int fd; Keyreq kr; Keyres res; - Caret caret; - uchar out[Ipcmaxresp]; + uchar out[Ipcmaxresp], token; char commit[Maxutf], preedit[Maxutf]; - int cap, n, ncommit, negotiated, npreedit, type, want; - uchar token; + int fd, n, ncommit, npreedit, want; fd = (int)(uintptr)arg; threadsetname("client %d", fd); - reply = chancreate(sizeof(Keyres), 0); - kr.reply = reply; + memset(&kr, 0, sizeof kr); + kr.reply = chancreate(sizeof(Keyres), 0); kr.owner = &fd; - cap = Cclientpreedit; - negotiated = 0; - memset(&caret, 0, sizeof caret); - kr.cap = cap; - kr.caret = caret; - while((type = srvreadreq(fd, &kr, &want)) >= 0){ - if(type == Ipccap){ - cap = want ? Cclientpreedit : 0; - negotiated = 1; - }else if(type == Ipclegacy && !negotiated) - cap = want ? Cclientpreedit : 0; - else if(type == Ipccaret) - caret = kr.caret; - kr.cap = cap; - kr.caret = caret; + kr.cap = Cclientpreedit; + while(srvreadreq(fd, &kr, &want) >= 0){ + if(kr.op != Keycaret) + kr.cap = want ? Cclientpreedit : 0; chansend(keyc, &kr); - chanrecv(reply, &res); - if(type == Ipccaret) + chanrecv(kr.reply, &res); + if(kr.op == Keycaret) continue; ncommit = stoutf(&res.commit, commit, sizeof commit); npreedit = stoutf(&res.preedit, preedit, sizeof preedit); - n = ipcpackresp(out, sizeof out, - type == Ipccap ? 1 : res.eaten, + /* A capability reply is always eaten: it marks the extension. */ + n = ipcpackresp(out, sizeof out, kr.op == Keycap || res.eaten, commit, ncommit, preedit, npreedit, want); if(n < 0 || ipcsend(fd, out, n) < 0) break; } kr.op = Keyrelease; - kr.cap = cap; - kr.caret = caret; kr.ks = 0; kr.mod = 0; chansend(keyc, &kr); - chanrecv(reply, &res); - chanfree(reply); + chanrecv(kr.reply, &res); + chanfree(kr.reply); close(fd); chanrecv(clientc, &token); } @@ -142,9 +122,6 @@ srvthread(void*) close(fd); continue; } - if(proccreate(clientthread, (void*)(uintptr)fd, 8192) < 0){ - chanrecv(clientc, &token); - close(fd); - } + proccreate(clientthread, (void*)(uintptr)fd, 8192); } } diff --git a/tests/gtk_live_test.c b/tests/gtk_live_test.c index 5f22eb5..b926629 100644 --- a/tests/gtk_live_test.c +++ b/tests/gtk_live_test.c @@ -204,7 +204,7 @@ request(Server *s, int fd) e.type = Ecaret; record(s, &e); return 1; - case Ipclegacy: + case Ipckey: ipcunpackreq(buf, &want, &mod, &key); e.want = want; e.key = key; @@ -854,9 +854,8 @@ main(int argc, char **argv) first = eventcount(&srv); closes = closecount(&srv); gtk_im_context_focus_out(ctx); - Check(waitcount(&srv, first + 1) && getevent(&srv, first).type == Ereset, - "focus-out reset missing"); Check(waitclose(&srv, closes + 1), "focus-out did not close connection"); + Check(eventcount(&srv) == first, "focus-out sent a request before closing"); Check(strcmp(log.event, "CE") == 0, "focus-out clear order was %s", log.event); /* Dispose is repeatable, closes the connection, and emits no preedit. */ diff --git a/tests/ipc_test.c b/tests/ipc_test.c index 7ad236d..e648fb2 100644 --- a/tests/ipc_test.c +++ b/tests/ipc_test.c @@ -48,13 +48,13 @@ ipc_masks_modifiers(struct ct *t) CT_CHECK(t, ipcreqreset(buf)); /* Frontends share one keysym and modifier mapping. */ - CT_EQ_UINT(t, 'a', ipckey('a', 'a')); - CT_EQ_UINT(t, '1', ipckey(0xffb1, '1')); /* KP_1 */ - CT_EQ_UINT(t, Kret, ipckey(0xff0d, '\r')); - CT_EQ_UINT(t, Kback, ipckey(0xff08, 8)); - CT_EQ_UINT(t, Kspec + 0xff, ipckey(0xffff, 0x7f)); /* Delete */ - CT_EQ_UINT(t, 0x1f642, ipckey(0x101f642, 0x1f642)); - CT_EQ_UINT(t, 0, ipckey(0xfe03, 0)); /* ISO_Level3_Shift */ + CT_EQ_UINT(t, 'a', ipckeysym('a', 'a')); + CT_EQ_UINT(t, '1', ipckeysym(0xffb1, '1')); /* KP_1 */ + CT_EQ_UINT(t, Kret, ipckeysym(0xff0d, '\r')); + CT_EQ_UINT(t, Kback, ipckeysym(0xff08, 8)); + CT_EQ_UINT(t, Kspec + 0xff, ipckeysym(0xffff, 0x7f)); /* Delete */ + CT_EQ_UINT(t, 0x1f642, ipckeysym(0x101f642, 0x1f642)); + CT_EQ_UINT(t, 0, ipckeysym(0xfe03, 0)); /* ISO_Level3_Shift */ CT_EQ_UINT(t, Mshift|Mctrl, ipcmod(Mshift|Mctrl|(1<<1)|(1<<4))); CT_EQ_UINT(t, Msuper, ipcmod(1<<6)); CT_EQ_UINT(t, Msuper, ipcmod(1<<26)); @@ -96,7 +96,7 @@ ipc_control_and_caret_frames(struct ct *t) CT_EQ_INT(t, 0, want); CT_EQ_UINT(t, 0, key); - CT_EQ_INT(t, 0, ipcpackcaret(buf, 1, -2, 0x01020304, 0x506)); + ipcpackcaret(buf, 1, -2, 0x01020304, 0x506); CT_EQ_MEM(t, caret, buf, sizeof caret); CT_EQ_INT(t, Ipccaret, ipcreqtype(buf)); if(CT_EQ_INT(t, 0, ipcunpackcaret(buf, &valid, &x, &y, &h))){ @@ -105,17 +105,16 @@ ipc_control_and_caret_frames(struct ct *t) CT_EQ_INT(t, 0x01020304, y); CT_EQ_INT(t, 0x506, h); } - CT_EQ_INT(t, 0, ipcpackcaret(buf, 1, INT32_MIN, INT32_MAX, 0)); + ipcpackcaret(buf, 1, INT32_MIN, INT32_MAX, 0); if(CT_EQ_INT(t, 0, ipcunpackcaret(buf, &valid, &x, &y, &h))){ CT_EQ_INT(t, INT32_MIN, x); CT_EQ_INT(t, INT32_MAX, y); CT_EQ_INT(t, 0, h); } - CT_EQ_INT(t, 0, ipcpackcaret(buf, 0, -2, 3, 4)); + ipcpackcaret(buf, 0, -2, 3, 4); CT_EQ_MEM(t, nocaret, buf, sizeof nocaret); if(CT_EQ_INT(t, 0, ipcunpackcaret(buf, &valid, &x, &y, &h))) CT_EQ_INT(t, 0, valid); - CT_EQ_INT(t, -1, ipcpackcaret(buf, 1, 0, 0, -1)); memcpy(bad, caret, sizeof bad); bad[1]++; @@ -139,9 +138,9 @@ ipc_control_and_caret_frames(struct ct *t) CT_EQ_INT(t, Ipcunknown, ipcreqtype(bad)); ipcpackreq(buf, 1, 0, 'a'); - CT_EQ_INT(t, Ipclegacy, ipcreqtype(buf)); + CT_EQ_INT(t, Ipckey, ipcreqtype(buf)); ipcpackreset(buf, 1); - CT_EQ_INT(t, Ipclegacy, ipcreqtype(buf)); + CT_EQ_INT(t, Ipckey, ipcreqtype(buf)); } void @@ -162,7 +161,6 @@ ipc_runtime_path(struct ct *t) snprint(fallback, sizeof fallback, "/tmp/strans.%d", getuid()); CT_EQ_STR(t, fallback, buf); CT_EQ_INT(t, -1, ipcpath(buf, 4)); - CT_EQ_INT(t, -1, ipcpath(nil, sizeof buf)); if(saved != nil){ setenv("XDG_RUNTIME_DIR", saved, 1); free(saved); @@ -200,22 +198,18 @@ ipc_response_pack_boundaries(struct ct *t) CT_EQ_INT(t, -1, ipcpackresp(out, Ipcmaxresp-1, 1, (char*)field, sizeof field, (char*)field, sizeof field, 1)); CT_EQ_INT(t, -1, ipcpackresp(out, sizeof out, 0, - nil, 1, nil, 0, 0)); - CT_EQ_INT(t, -1, ipcpackresp(out, sizeof out, 0, - nil, 0, nil, 1, 1)); - CT_EQ_INT(t, -1, ipcpackresp(out, sizeof out, 0, - (char*)field, Ipcfieldmax+1, nil, 0, 0)); + (char*)field, Ipcfieldmax+1, "", 0, 0)); } void ipc_response_empty_and_preedit(struct ct *t) { uchar first[Ipcmaxresp], second[Ipcmaxresp]; - char commit[16], preedit[16]; + char commit[Ipcfieldmax+1], preedit[Ipcfieldmax+1]; Ipcresp resp; int fd[2], nfirst, nsecond; - nfirst = ipcpackresp(first, sizeof first, 0, nil, 0, nil, 0, 0); + nfirst = ipcpackresp(first, sizeof first, 0, "", 0, "", 0, 0); nsecond = ipcpackresp(second, sizeof second, 1, "go", 2, "kana", 4, 1); if(!CT_CHECK(t, nfirst > 0 && nsecond > 0)) @@ -226,15 +220,13 @@ ipc_response_empty_and_preedit(struct ct *t) } if(CT_EQ_INT(t, 0, ipcsend(fd[0], first, nfirst)) && CT_EQ_INT(t, 0, ipcsend(fd[0], second, nsecond)) && - CT_EQ_INT(t, 0, ipcreadresp(fd[1], 0, commit, sizeof commit, - nil, 0, &resp))){ + CT_EQ_INT(t, 0, ipcreadresp(fd[1], 0, commit, preedit, &resp))){ CT_EQ_INT(t, 0, resp.eaten); CT_EQ_SIZE(t, 0, resp.commitlen); CT_EQ_SIZE(t, 0, resp.preeditlen); CT_EQ_STR(t, "", commit); } - if(CT_EQ_INT(t, 0, ipcreadresp(fd[1], 1, commit, sizeof commit, - preedit, sizeof preedit, &resp))){ + if(CT_EQ_INT(t, 0, ipcreadresp(fd[1], 1, commit, preedit, &resp))){ CT_EQ_INT(t, 1, resp.eaten); CT_EQ_SIZE(t, 2, resp.commitlen); CT_EQ_SIZE(t, 4, resp.preeditlen); @@ -249,14 +241,14 @@ void ipc_response_max_and_drain(struct ct *t) { uchar first[Ipcmaxresp], second[Ipcmaxresp], field[Ipcfieldmax]; - char commit[8], preedit[8]; + char commit[Ipcfieldmax+1], preedit[Ipcfieldmax+1]; Ipcresp resp; int fd[2], nfirst, nsecond; memset(field, 'x', sizeof field); nfirst = ipcpackresp(first, sizeof first, 1, (char*)field, sizeof field, (char*)field, sizeof field, 1); - nsecond = ipcpackresp(second, sizeof second, 0, "ok", 2, nil, 0, 0); + nsecond = ipcpackresp(second, sizeof second, 0, "ok", 2, "", 0, 0); if(!CT_CHECK(t, nfirst == Ipcmaxresp && nsecond > 0)) return; if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0){ @@ -265,15 +257,15 @@ ipc_response_max_and_drain(struct ct *t) } if(CT_EQ_INT(t, 0, ipcsend(fd[0], first, nfirst)) && CT_EQ_INT(t, 0, ipcsend(fd[0], second, nsecond)) && - CT_EQ_INT(t, 0, ipcreadresp(fd[1], 1, commit, sizeof commit, - preedit, sizeof preedit, &resp))){ - CT_EQ_SIZE(t, sizeof commit - 1, resp.commitlen); - CT_EQ_SIZE(t, sizeof preedit - 1, resp.preeditlen); - CT_EQ_STR(t, "xxxxxxx", commit); - CT_EQ_STR(t, "xxxxxxx", preedit); + CT_EQ_INT(t, 0, ipcreadresp(fd[1], 1, commit, preedit, &resp))){ + CT_EQ_SIZE(t, Ipcfieldmax, resp.commitlen); + CT_EQ_SIZE(t, Ipcfieldmax, resp.preeditlen); + CT_EQ_MEM(t, field, commit, Ipcfieldmax); + CT_EQ_MEM(t, field, preedit, Ipcfieldmax); + CT_EQ_INT(t, 0, commit[Ipcfieldmax]); + CT_EQ_INT(t, 0, preedit[Ipcfieldmax]); } - if(CT_EQ_INT(t, 0, ipcreadresp(fd[1], 0, commit, sizeof commit, - nil, 0, &resp))) + if(CT_EQ_INT(t, 0, ipcreadresp(fd[1], 0, commit, preedit, &resp))) CT_EQ_STR(t, "ok", commit); close(fd[0]); close(fd[1]); @@ -283,7 +275,7 @@ void ipc_response_fragmented_and_truncated(struct ct *t) { uchar frame[Ipcmaxresp]; - char commit[8], preedit[8]; + char commit[Ipcfieldmax+1], preedit[Ipcfieldmax+1]; Ipcresp resp; int fd[2], i, n; @@ -299,8 +291,8 @@ ipc_response_fragmented_and_truncated(struct ct *t) CT_ERRORF(t, "fragment send failed"); break; } - if(i == n && CT_EQ_INT(t, 0, ipcreadresp(fd[1], 1, - commit, sizeof commit, preedit, sizeof preedit, &resp))){ + if(i == n && CT_EQ_INT(t, 0, ipcreadresp(fd[1], 1, commit, preedit, + &resp))){ CT_EQ_STR(t, "abc", commit); CT_EQ_STR(t, "xy", preedit); } @@ -313,8 +305,7 @@ ipc_response_fragmented_and_truncated(struct ct *t) } CT_EQ_INT(t, 0, ipcsend(fd[0], frame, n-1)); shutdown(fd[0], SHUT_WR); - CT_EQ_INT(t, -1, ipcreadresp(fd[1], 1, commit, sizeof commit, - preedit, sizeof preedit, &resp)); + CT_EQ_INT(t, -1, ipcreadresp(fd[1], 1, commit, preedit, &resp)); close(fd[0]); close(fd[1]); @@ -325,8 +316,7 @@ ipc_response_fragmented_and_truncated(struct ct *t) frame[0] = 2; CT_EQ_INT(t, 0, ipcsend(fd[0], frame, n)); errno = 0; - CT_EQ_INT(t, -1, ipcreadresp(fd[1], 1, commit, sizeof commit, - preedit, sizeof preedit, &resp)); + CT_EQ_INT(t, -1, ipcreadresp(fd[1], 1, commit, preedit, &resp)); CT_EQ_INT(t, EPROTO, errno); close(fd[0]); close(fd[1]); @@ -351,7 +341,7 @@ ipc_broken_peer_send(struct ct *t) static void ipcclientdeadlines(struct ct *t) { - char fill[4096], commit[8]; + char fill[4096], commit[Ipcfieldmax+1], preedit[Ipcfieldmax+1]; Ipcresp resp; int fd[2]; int64_t start, elapsed; @@ -363,8 +353,7 @@ ipcclientdeadlines(struct ct *t) } start = nowms(); errno = 0; - CT_EQ_INT(t, -1, ipcreadresp(fd[0], 0, commit, sizeof commit, - nil, 0, &resp)); + CT_EQ_INT(t, -1, ipcreadresp(fd[0], 0, commit, preedit, &resp)); elapsed = nowms() - start; CT_EQ_INT(t, ETIMEDOUT, errno); CT_CHECK(t, elapsed >= 0 && elapsed < 4*Ipcwaitms); diff --git a/tests/server_test.c b/tests/server_test.c index 8b9b778..13e3677 100644 --- a/tests/server_test.c +++ b/tests/server_test.c @@ -169,13 +169,12 @@ allowrequest(Enginegate *g) } static int -readreply(struct ct *t, Testclient *client, int want, char *preedit, int npreedit) +readreply(struct ct *t, Testclient *client, int want, char *preedit) { - char commit[Maxutf]; + char commit[Ipcfieldmax+1]; Ipcresp resp; - if(ipcreadresp(client->peer, want, commit, sizeof commit, - preedit, npreedit, &resp) < 0) + if(ipcreadresp(client->peer, want, commit, preedit, &resp) < 0) return CT_ERRORF(t, "response read failed: %s", strerror(errno)); CT_EQ_STR(t, "", commit); return resp.eaten; @@ -247,7 +246,7 @@ server_connection_ownership(struct ct *t) Keyreq req; Drawcmd dc; Str shown; - char preedit[Maxutf]; + char preedit[Ipcfieldmax+1]; void *aowner, *bowner, *cowner; uchar byte, token; ssize_t n; @@ -279,14 +278,14 @@ server_connection_ownership(struct ct *t) req = nextrequest(t, &gate, Keypress); aowner = req.owner; allowrequest(&gate); - CT_CHECK(t, readreply(t, &a, 1, preedit, sizeof preedit)); + CT_CHECK(t, readreply(t, &a, 1, preedit)); CT_EQ_STR(t, "k", preedit); if(!sendkey(t, &a, 1, 0, 'a')) goto cleanup; req = nextrequest(t, &gate, Keypress); CT_EQ_PTR(t, aowner, req.owner); allowrequest(&gate); - CT_CHECK(t, readreply(t, &a, 1, preedit, sizeof preedit)); + CT_CHECK(t, readreply(t, &a, 1, preedit)); CT_EQ_STR(t, "か", preedit); CT_EQ_PTR(t, aowner, testengineowner()); @@ -296,7 +295,7 @@ server_connection_ownership(struct ct *t) bowner = req.owner; CT_CHECK(t, bowner != aowner); allowrequest(&gate); - CT_CHECK(t, readreply(t, &b, 1, preedit, sizeof preedit)); + CT_CHECK(t, readreply(t, &b, 1, preedit)); CT_EQ_STR(t, "ん", preedit); CT_EQ_PTR(t, bowner, testengineowner()); @@ -305,14 +304,14 @@ server_connection_ownership(struct ct *t) req = nextrequest(t, &gate, Keyreset); CT_EQ_PTR(t, aowner, req.owner); allowrequest(&gate); - CT_CHECK(t, readreply(t, &a, 1, preedit, sizeof preedit)); + CT_CHECK(t, readreply(t, &a, 1, preedit)); CT_EQ_STR(t, "", preedit); CT_EQ_PTR(t, bowner, testengineowner()); if(!sendkey(t, &b, 1, 0, Kmodfirst)) goto cleanup; req = nextrequest(t, &gate, Keypress); allowrequest(&gate); - CT_CHECK(t, !readreply(t, &b, 1, preedit, sizeof preedit)); + CT_CHECK(t, !readreply(t, &b, 1, preedit)); CT_EQ_STR(t, "ん", preedit); disconnectclient(t, &gate, &a, aowner); @@ -321,12 +320,12 @@ server_connection_ownership(struct ct *t) goto cleanup; req = nextrequest(t, &gate, Keypress); allowrequest(&gate); - CT_CHECK(t, readreply(t, &b, 1, preedit, sizeof preedit)); + CT_CHECK(t, readreply(t, &b, 1, preedit)); if(!sendkey(t, &b, 1, 0, 'a')) goto cleanup; req = nextrequest(t, &gate, Keypress); allowrequest(&gate); - CT_CHECK(t, readreply(t, &b, 1, preedit, sizeof preedit)); + CT_CHECK(t, readreply(t, &b, 1, preedit)); CT_EQ_STR(t, "にゃ", preedit); if(!sendreset(t, &b, 1)) @@ -334,7 +333,7 @@ server_connection_ownership(struct ct *t) req = nextrequest(t, &gate, Keyreset); CT_EQ_PTR(t, bowner, req.owner); allowrequest(&gate); - CT_CHECK(t, readreply(t, &b, 1, preedit, sizeof preedit)); + CT_CHECK(t, readreply(t, &b, 1, preedit)); CT_EQ_STR(t, "", preedit); CT_EQ_PTR(t, bowner, testengineowner()); @@ -343,7 +342,7 @@ server_connection_ownership(struct ct *t) req = nextrequestcap(t, &gate, Keypress, 0); CT_EQ_PTR(t, bowner, req.owner); allowrequest(&gate); - CT_CHECK(t, readreply(t, &b, 0, nil, 0)); + CT_CHECK(t, readreply(t, &b, 0, preedit)); errno = 0; n = recv(b.peer, &byte, 1, MSG_PEEK|MSG_DONTWAIT); CT_EQ_INT(t, -1, n); @@ -353,7 +352,7 @@ server_connection_ownership(struct ct *t) goto cleanup; req = nextrequest(t, &gate, Keypress); allowrequest(&gate); - CT_CHECK(t, readreply(t, &b, 1, preedit, sizeof preedit)); + CT_CHECK(t, readreply(t, &b, 1, preedit)); CT_EQ_STR(t, "か", preedit); disconnectclient(t, &gate, &b, bowner); @@ -410,7 +409,7 @@ server_extension_stream(struct ct *t) Keyreq req; Drawcmd dc; uchar frame[Ipccaretsz], token; - char preedit[Maxutf]; + char preedit[Ipcfieldmax+1]; void *aowner, *bowner; int gateactive; @@ -442,10 +441,10 @@ server_extension_stream(struct ct *t) aowner = req.owner; CT_EQ_PTR(t, nil, testengineowner()); allowrequest(&gate); - CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit, sizeof preedit)); + CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit)); CT_EQ_STR(t, "", preedit); - CT_EQ_INT(t, 0, ipcpackcaret(frame, 1, -101, -7, 23)); + ipcpackcaret(frame, 1, -101, -7, 23); if(!sendframe(t, &a, frame, Ipccaretsz, 1)) goto cleanup; req = nextrequest(t, &gate, Keycaret); @@ -468,7 +467,7 @@ server_extension_stream(struct ct *t) CT_EQ_INT(t, -7, req.caret.y); CT_EQ_INT(t, 23, req.caret.h); allowrequest(&gate); - CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit, sizeof preedit)); + CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit)); CT_EQ_STR(t, "k", preedit); CT_EQ_PTR(t, aowner, testengineowner()); @@ -479,7 +478,7 @@ server_extension_stream(struct ct *t) CT_EQ_PTR(t, aowner, req.owner); CT_EQ_INT(t, 1, req.caret.valid); allowrequest(&gate); - CT_EQ_INT(t, 1, readreply(t, &a, 0, nil, 0)); + CT_EQ_INT(t, 1, readreply(t, &a, 0, preedit)); /* Reset is still the old six-byte frame and does not discard caret. */ ipcpackreset(frame, 0); @@ -492,14 +491,14 @@ server_extension_stream(struct ct *t) CT_EQ_INT(t, -7, req.caret.y); CT_EQ_INT(t, 23, req.caret.h); allowrequest(&gate); - CT_EQ_INT(t, 1, readreply(t, &a, 0, nil, 0)); + CT_EQ_INT(t, 1, readreply(t, &a, 0, preedit)); ipcpackcap(frame, Cclientpreedit); if(!sendframe(t, &a, frame, Ipcreqsz, 0)) goto cleanup; req = nextrequest(t, &gate, Keycap); allowrequest(&gate); - CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit, sizeof preedit)); + CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit)); CT_EQ_STR(t, "", preedit); ipcpackreq(frame, 1, 0, 'n'); if(!sendframe(t, &a, frame, Ipcreqsz, 0)) @@ -508,7 +507,7 @@ server_extension_stream(struct ct *t) CT_EQ_INT(t, 1, req.caret.valid); CT_EQ_INT(t, -101, req.caret.x); allowrequest(&gate); - CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit, sizeof preedit)); + CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit)); CT_EQ_STR(t, "ん", preedit); disconnectclient(t, &gate, &a, aowner); @@ -520,7 +519,7 @@ server_extension_stream(struct ct *t) bowner = req.owner; CT_EQ_INT(t, 0, req.caret.valid); allowrequest(&gate); - CT_EQ_INT(t, 1, readreply(t, &b, 1, preedit, sizeof preedit)); + CT_EQ_INT(t, 1, readreply(t, &b, 1, preedit)); CT_EQ_STR(t, "k", preedit); disconnectclient(t, &gate, &b, bowner); @@ -554,7 +553,7 @@ server_rejects_unknown_extension(struct ct *t) Keyreq req; Drawcmd dc; uchar frame[Ipccaretsz], token; - char preedit[Maxutf]; + char preedit[Ipcfieldmax+1]; void *owner; int gateactive; @@ -580,7 +579,7 @@ server_rejects_unknown_extension(struct ct *t) if(!startclient(t, &badver)) goto cleanup; - CT_EQ_INT(t, 0, ipcpackcaret(frame, 1, 3, 4, 5)); + ipcpackcaret(frame, 1, 3, 4, 5); frame[1]++; if(!sendframe(t, &badver, frame, sizeof frame, 0)) goto cleanup; @@ -592,7 +591,7 @@ server_rejects_unknown_extension(struct ct *t) if(!startclient(t, &badop)) goto cleanup; - CT_EQ_INT(t, 0, ipcpackcaret(frame, 1, 3, 4, 5)); + ipcpackcaret(frame, 1, 3, 4, 5); frame[2]++; if(!sendframe(t, &badop, frame, sizeof frame, 1)) goto cleanup; @@ -608,7 +607,7 @@ server_rejects_unknown_extension(struct ct *t) req = nextrequest(t, &gate, Keypress); owner = req.owner; allowrequest(&gate); - CT_EQ_INT(t, 1, readreply(t, &good, 1, preedit, sizeof preedit)); + CT_EQ_INT(t, 1, readreply(t, &good, 1, preedit)); CT_EQ_STR(t, "k", preedit); disconnectclient(t, &gate, &good, owner); diff --git a/xim/xim.c b/xim/xim.c index 6de7125..6f20482 100644 --- a/xim/xim.c +++ b/xim/xim.c @@ -555,7 +555,7 @@ kpress(Ic *state, xcb_key_press_event_t *ev) int n, wasvalid; key = keymaplookup(kstate, ev->detail, ev->state); - key = ipckey(key, xkb_keysym_to_utf32(key)); + key = ipckeysym(key, xkb_keysym_to_utf32(key)); if(meaningful(key)){ wasvalid = state->caret.valid; refreshplace(state);