compose: a sequence belongs to one context
One xkb_compose_state served the whole session, so a dead key left half typed in one window was completed by the first key in the next. Two IBus contexts through the real processkey(), before this: want length 0, got length 2; byte 0: want <end>, got 0xc3 (text) want 0, got 1 (req.op) Context A pressed dead_acute; context B pressed e, got é, and went down the composed-text branch instead of sending a key. Only COMPOSING is sticky -- xkbcommon starts over by itself after COMPOSED and CANCELLED, which the table in compose_test already pins -- and nothing here ever called xkb_compose_state_reset. That static was also fed from three procs, two of them live at once, with no lock, which xkbcommon forbids. Reaching it needs two focused windows, so it cannot be made to fail on demand and has no test: it goes because the sharing goes, not because anything guards it. So a state per frontend, each starting over when the key comes from another context. All are made in composeinit(), on threadmain, before proccreate, because xkb_compose_state_new refs the table and that ref is a plain increment -- b160: mov (%rdi),%edx b16a: add $0x1,%edx b170: mov %edx,(%rdi) -- so making a state from a shared table on two procs would race in place of the feed. Made before the procs exist they can still share the one table. An owner address that gets reused says so with composedrop: ibus hands out a contexts[] slot again, xim can malloc an Ic at a freed one, and wl's single context, which serves every client in turn, drops at every activate and deactivate. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,24 +3,37 @@
|
||||
#include "test.h"
|
||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
||||
|
||||
/* A sequence swallows its keys and hands its text back at the end. */
|
||||
/*
|
||||
* A sequence swallows its keys and hands its text back at the end, and
|
||||
* belongs to the one context, in the one frontend, that started it.
|
||||
*/
|
||||
void
|
||||
compose_sequences(struct ct *t)
|
||||
{
|
||||
static int a, b; /* two input contexts, told apart by address */
|
||||
static const struct {
|
||||
int who;
|
||||
void *owner;
|
||||
u32int sym;
|
||||
int composing;
|
||||
char *text;
|
||||
} keys[] = {
|
||||
{ XKB_KEY_a, 0, "" },
|
||||
{ XKB_KEY_dead_acute, 1, "" },
|
||||
{ XKB_KEY_e, 0, "é" },
|
||||
{ XKB_KEY_Multi_key, 1, "" },
|
||||
{ XKB_KEY_o, 1, "" },
|
||||
{ XKB_KEY_c, 0, "©" },
|
||||
{ XKB_KEY_dead_acute, 1, "" },
|
||||
{ XKB_KEY_Escape, 1, "" },
|
||||
{ XKB_KEY_a, 0, "" },
|
||||
{ Composexim, &a, XKB_KEY_a, 0, "" },
|
||||
{ Composexim, &a, XKB_KEY_dead_acute, 1, "" },
|
||||
{ Composexim, &a, XKB_KEY_e, 0, "é" },
|
||||
{ Composexim, &a, XKB_KEY_Multi_key, 1, "" },
|
||||
{ Composexim, &a, XKB_KEY_o, 1, "" },
|
||||
{ Composexim, &a, XKB_KEY_c, 0, "©" },
|
||||
{ Composexim, &a, XKB_KEY_dead_acute, 1, "" },
|
||||
{ Composexim, &a, XKB_KEY_Escape, 1, "" },
|
||||
{ Composexim, &a, XKB_KEY_a, 0, "" },
|
||||
/* another context of the same frontend starts over */
|
||||
{ Composexim, &a, XKB_KEY_dead_acute, 1, "" },
|
||||
{ Composexim, &b, XKB_KEY_e, 0, "" },
|
||||
/* another frontend does not touch this one's sequence */
|
||||
{ Composexim, &a, XKB_KEY_dead_acute, 1, "" },
|
||||
{ Composewl, &a, XKB_KEY_o, 0, "" },
|
||||
{ Composexim, &a, XKB_KEY_e, 0, "é" },
|
||||
};
|
||||
char buf[Maxutf];
|
||||
int i;
|
||||
@@ -29,9 +42,15 @@ compose_sequences(struct ct *t)
|
||||
return;
|
||||
composeinit();
|
||||
for(i = 0; i < nelem(keys); i++){
|
||||
CT_EQ_INT(t, keys[i].composing,
|
||||
composekey(keys[i].sym, buf, sizeof buf));
|
||||
CT_EQ_INT(t, keys[i].composing, composekey(keys[i].who,
|
||||
keys[i].owner, keys[i].sym, buf, sizeof buf));
|
||||
CT_EQ_STR(t, keys[i].text, buf);
|
||||
}
|
||||
/* a context that goes takes its half-typed sequence with it */
|
||||
CT_EQ_INT(t, 1,
|
||||
composekey(Composewl, &a, XKB_KEY_dead_acute, buf, sizeof buf));
|
||||
composedrop(Composewl, &a);
|
||||
CT_EQ_INT(t, 0, composekey(Composewl, &a, XKB_KEY_e, buf, sizeof buf));
|
||||
CT_EQ_STR(t, "", buf);
|
||||
unsetenv("XCOMPOSEFILE");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user