ipc: strip machinery no peer uses; keep client state in one Keyreq
ipc.c: an AF_UNIX nonblocking connect completes at once or fails with EAGAIN, so the EINPROGRESS/poll/SO_ERROR path and the fcntl juggling were dead; the deadline plumbing checked a clock that cannot fail and re-tested the deadline before every transfer although only waitfd blocks; readfield's truncation and discard loop served the unit test, since every caller owns char[Ipcfieldmax+1]; NULL-argument checks on in-tree encoders are gone (peer validation stays). The primary key frame is Ipckey, not 'legacy'; ipckeysym names the keysym mapping. srv.c: the per-connection capability and caret already lived in the persistent Keyreq; the mirror locals and 'negotiated' flag guarded a protocol rule no client relied on. proccreate never fails in libthread. gtk: focus-out no longer round-trips a reset before closing the socket that releases the engine; the caret dedup compares the packed frame; srvconnect's preedit no-ops and the insimple flag are gone.
This commit is contained in:
104
gtk/main.c
104
gtk/main.c
@@ -1,5 +1,4 @@
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user