Cclientpreedit was a one-bit mask that every producer set as "want ? Cclientpreedit : 0" and every consumer masked out again; nothing else was ever going to join it. Keyreq carries clientpre, an int that says whether the client draws the preedit, and the engine and the XIM context keep it under that name.
157 lines
3.3 KiB
C
157 lines
3.3 KiB
C
#include "dat.h"
|
|
#include "fn.h"
|
|
|
|
#include <sys/stat.h>
|
|
#include <sys/un.h>
|
|
|
|
static char adir[256];
|
|
static char sockpath[sizeof(((struct sockaddr_un*)0)->sun_path)];
|
|
static dev_t sockdev;
|
|
static ino_t sockino;
|
|
static Channel *clientc;
|
|
|
|
/* Removes the socket only while it is still the one we announced. */
|
|
static void
|
|
srvunlink(void)
|
|
{
|
|
struct stat st;
|
|
|
|
if(sockpath[0] != '\0' && lstat(sockpath, &st) == 0 &&
|
|
st.st_dev == sockdev && st.st_ino == sockino)
|
|
unlink(sockpath);
|
|
sockpath[0] = '\0';
|
|
}
|
|
|
|
static int
|
|
srvnote(void *v, char *note)
|
|
{
|
|
USED(v);
|
|
USED(note);
|
|
srvunlink();
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
srvreadreq(int fd, Keyreq *kr, int *want)
|
|
{
|
|
uchar req[Ipccaretsz];
|
|
int valid;
|
|
int32_t x, y, h;
|
|
|
|
if(ipcreadn(fd, req, Ipcreqsz) < 0)
|
|
return -1;
|
|
*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;
|
|
return 0;
|
|
case Ipccap:
|
|
*want = (req[0] & Ipcreqwant) != 0;
|
|
kr->op = Keycap;
|
|
return 0;
|
|
case Ipccaret:
|
|
if(ipcreadn(fd, req + Ipcreqsz, Ipccaretsz - Ipcreqsz) < 0 ||
|
|
ipcunpackcaret(req, &valid, &x, &y, &h) < 0)
|
|
return -1;
|
|
kr->op = Keycaret;
|
|
kr->caret.valid = valid;
|
|
kr->caret.x = x;
|
|
kr->caret.y = y;
|
|
kr->caret.h = h;
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* One Keyreq persists for the connection: the negotiated preedit and
|
|
* the last caret ride along with every request, and the socket closing
|
|
* releases the engine.
|
|
*/
|
|
static void
|
|
clientthread(void *arg)
|
|
{
|
|
Keyreq kr;
|
|
Keyres res;
|
|
uchar out[Ipcmaxresp], token;
|
|
char commit[Maxutf], preedit[Maxutf];
|
|
int fd, n, ncommit, npreedit, want;
|
|
|
|
fd = (int)(uintptr)arg;
|
|
threadsetname("client %d", fd);
|
|
memset(&kr, 0, sizeof kr);
|
|
kr.reply = chancreate(sizeof(Keyres), 0);
|
|
kr.owner = &fd;
|
|
kr.clientpre = 1;
|
|
while(srvreadreq(fd, &kr, &want) >= 0){
|
|
if(kr.op != Keycaret)
|
|
kr.clientpre = want;
|
|
chansend(keyc, &kr);
|
|
chanrecv(kr.reply, &res);
|
|
if(kr.op == Keycaret)
|
|
continue;
|
|
ncommit = stoutf(&res.commit, commit, sizeof commit);
|
|
npreedit = stoutf(&res.preedit, preedit, sizeof preedit);
|
|
/* 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.ks = 0;
|
|
kr.mod = 0;
|
|
chansend(keyc, &kr);
|
|
chanrecv(kr.reply, &res);
|
|
chanfree(kr.reply);
|
|
close(fd);
|
|
chanrecv(clientc, &token);
|
|
}
|
|
|
|
void
|
|
srvinit(void)
|
|
{
|
|
struct stat st;
|
|
char *addr;
|
|
|
|
if(ipcpath(sockpath, sizeof sockpath) < 0)
|
|
die("IPC path is too long");
|
|
addr = smprint("unix!%s", sockpath);
|
|
if(addr == nil)
|
|
die("out of memory");
|
|
if(announce(addr, adir) < 0)
|
|
die("IPC endpoint is already in use: %r");
|
|
free(addr);
|
|
if(chmod(sockpath, 0600) < 0 || lstat(sockpath, &st) < 0)
|
|
die("can't protect IPC endpoint: %s", sockpath);
|
|
sockdev = st.st_dev;
|
|
sockino = st.st_ino;
|
|
atexit(srvunlink);
|
|
threadnotify(srvnote, 1);
|
|
}
|
|
|
|
void
|
|
srvthread(void*)
|
|
{
|
|
char ldir[40];
|
|
int fd;
|
|
uchar token;
|
|
|
|
threadsetname("srv");
|
|
token = 0;
|
|
clientc = chancreate(sizeof token, Maxclients);
|
|
for(;;){
|
|
fd = listen(adir, ldir);
|
|
if(fd < 0)
|
|
continue;
|
|
if(channbsend(clientc, &token) <= 0){
|
|
close(fd);
|
|
continue;
|
|
}
|
|
proccreate(clientthread, (void*)(uintptr)fd, 8192);
|
|
}
|
|
}
|