One wl_surface and one zwp_input_popup_surface_v2, made once; the compositor makes them visible on activate, puts them at the text cursor and takes them down again, so popuparea, popupposition and Caret stay X11-only and popuplayout gets a constant area. Two shm buffers are used in turn, each busy from attach until the compositor releases it, because win.c's single grow-only image would be redrawn while the compositor was still reading it; a picture that arrives while both are busy waits for the next release, and the engine will not send it twice. drawthread no longer runs, so wl.c reads GDK_SCALE itself and calls textinit after it, since setfont reads Fontsz. The buffer is rounded up to a multiple of the scale: one that is not is an invalid_size error at attach, and a preedit alone really does lay out to an odd width at GDK_SCALE=2. drawc is taken where the engine's picture and our surface can part: after every key, after the Keyrelease a deactivate sends, and after the owner poll, hiding for the last two. The poll is not an optimisation -- once another frontend takes the engine, its pictures go unconsumed and no later send will ever say hide. main.c now starts either the Wayland frontend or the X11 popup and XIM, which is where the two popups would otherwise collide. Checked by hand under headless sway 1.12, reading grim screenshots: the hanja list for 가 with its selection and 1-9/125 marker, the emoji search, the popup gone after Escape, and the same at GDK_SCALE=2. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
74 lines
1.2 KiB
C
74 lines
1.2 KiB
C
#include "dat.h"
|
|
#include "fn.h"
|
|
|
|
Channel *drawc;
|
|
Channel *keyc;
|
|
|
|
void
|
|
usage(void)
|
|
{
|
|
fprint(2, "usage: strans mapdir\n");
|
|
threadexitsall("usage");
|
|
}
|
|
|
|
void
|
|
die(char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
fprint(2, "strans: ");
|
|
va_start(ap, fmt);
|
|
vfprint(2, fmt, ap);
|
|
va_end(ap);
|
|
fprint(2, "\n");
|
|
threadexitsall("die");
|
|
}
|
|
|
|
void*
|
|
emalloc(ulong n)
|
|
{
|
|
void *p;
|
|
|
|
p = mallocz(n, 1);
|
|
if(p == nil)
|
|
die("out of memory");
|
|
return p;
|
|
}
|
|
|
|
void*
|
|
erealloc(void *p, ulong n)
|
|
{
|
|
p = realloc(p, n);
|
|
if(p == nil)
|
|
die("out of memory");
|
|
return p;
|
|
}
|
|
|
|
void
|
|
threadmain(int argc, char **argv)
|
|
{
|
|
char *display;
|
|
|
|
if(argc != 2)
|
|
usage();
|
|
|
|
drawc = chancreate(sizeof(Drawcmd), 4);
|
|
keyc = chancreate(sizeof(Keyreq), 0);
|
|
langinit(argv[1]);
|
|
composeinit();
|
|
srvinit();
|
|
proccreate(srvthread, nil, 16384);
|
|
proccreate(ibusthread, nil, 32768);
|
|
/* One popup per session: the Wayland frontend draws its own, so the
|
|
* X11 one and the XIM it serves stand down. */
|
|
if(getenv("WAYLAND_DISPLAY") != nil && wlinit())
|
|
proccreate(wlthread, nil, 32768);
|
|
else{
|
|
proccreate(drawthread, nil, 16384);
|
|
display = getenv("DISPLAY");
|
|
if(display != nil && display[0] != '\0')
|
|
proccreate(ximthread, nil, 32768);
|
|
}
|
|
imthread(nil);
|
|
}
|