From 33023d7f51810dceb5bbdd314c783d49ac2d891b Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Mon, 17 Aug 2026 10:56:03 +0900 Subject: [PATCH] ipc: a modifier keysym is no key Shift, Control, and their kin were mapped to special keys that the engine then had a range and a check to ignore, and the GTK module made a round trip to the daemon for each press. ipckeysym maps them to key 0, which was already the "no key" every frontend and the engine skip; Kmodfirst, Kmodlast, and ismodkey go. --- ipc.c | 8 +++++--- ipc.h | 2 -- strans.c | 10 ++-------- tests/engine_test.c | 8 ++++---- tests/ipc_live_test.c | 6 +++--- tests/ipc_test.c | 1 + tests/live.c | 2 +- tests/server_test.c | 2 +- 8 files changed, 17 insertions(+), 22 deletions(-) diff --git a/ipc.c b/ipc.c index 8167dc1..b3a107a 100644 --- a/ipc.c +++ b/ipc.c @@ -165,15 +165,17 @@ ipcconnect(void) /* * Engine key for an X keysym and its Unicode value: printable characters - * as themselves, the function keysyms 0xff00-0xffff as Kspec+offset. - * The keypad keys and Shift+Tab (ISO_Left_Tab) fold onto their plain - * counterparts. + * as themselves, the function keysyms 0xff00-0xffff as Kspec+offset, and + * no key at all for a modifier. The keypad keys and Shift+Tab + * (ISO_Left_Tab) fold onto their plain counterparts. */ uint32_t ipckeysym(uint32_t sym, uint32_t unicode) { if(unicode >= ' ' && unicode != 0x7f) return unicode; + if(sym >= 0xffe1 && sym <= 0xffee) + return 0; switch(sym){ case 0xfe20: case 0xff89: diff --git a/ipc.h b/ipc.h index 3275867..660f96f 100644 --- a/ipc.h +++ b/ipc.h @@ -45,8 +45,6 @@ enum Khenkan = Kspec|0x23, Kkana = Kspec|0x27, Kzenkaku = Kspec|0x2a, - Kmodfirst = Kspec|0xe1, - Kmodlast = Kspec|0xee, /* X core modifier bits; GDK and IBus also flag Super at bit 26. */ Mshift = 1<<0, diff --git a/strans.c b/strans.c index 1b660be..602d776 100644 --- a/strans.c +++ b/strans.c @@ -516,17 +516,11 @@ kokey(Rune c, u32int mod) return c; } -static int -ismodkey(u32int ks) -{ - return ks >= Kmodfirst && ks <= Kmodlast; -} - -/* Modifier presses and unmapped keys never engage the engine. */ +/* Modifier presses and unmapped keys, key 0, never engage the engine. */ int keymeaningful(u32int ks) { - return ks != 0 && !ismodkey(ks); + return ks != 0; } static void diff --git a/tests/engine_test.c b/tests/engine_test.c index 8ff3067..e398d50 100644 --- a/tests/engine_test.c +++ b/tests/engine_test.c @@ -252,7 +252,7 @@ engine_active_owner_lifecycle(struct ct *t) CT_EQ_PTR(t, nil, activeowner); CT_EQ_INT(t, 0, im.pre.n); CT_EQ_INT(t, 0, im.raw.n); - ownerrequest(&c, Keypress, Kmodfirst, 0); + ownerrequest(&c, Keypress, 0, 0); CT_EQ_PTR(t, nil, activeowner); res = ownerrequest(&c, Keypress, 'k', 0); CT_EQ_PTR(t, &c, activeowner); @@ -1646,7 +1646,7 @@ engine_emoji_preedit_languages(struct ct *t) im.l = getlang(LangJP); sclear(&com); if(typekeys(t, "ka", &com)){ - CT_CHECK(t, !keystroke(Kmodfirst+2, 0, &com)); + CT_CHECK(t, !keystroke(0, 0, &com)); impre(&im, &shown); checkstr(t, "modifier preserves Japanese", "か", &shown); CT_CHECK(t, keystroke('E', Mctrl, &com)); @@ -1665,7 +1665,7 @@ engine_emoji_preedit_languages(struct ct *t) CT_CHECK(t, keystroke('E', Mctrl, &com)); CT_EQ_INT(t, LangJP, im.l->lang); CT_CHECK(t, keystroke('a', 0, &com)); - CT_CHECK(t, !keystroke(Kmodfirst+2, 0, &com)); + CT_CHECK(t, !keystroke(0, 0, &com)); CT_CHECK(t, search.lang); checkstr(t, "modifier preserves search", "a", &search.text); CT_CHECK(t, !keystroke('P', Mctrl|Mshift, &com)); @@ -2108,7 +2108,7 @@ engine_randomized_stress(struct ct *t) res = ownerrequestat(owner, Keycaret, 0, 0, &pos); else if(op == 24) res = ownerrequest(owner, Keypress, - Kmodfirst + ((rnd >> 20) & 7), 0); + 0, 0); else if(op == 25) res = ownerrequestat(owner, Keypress, 'p', Mctrl, &pos); else if(op == 26) diff --git a/tests/ipc_live_test.c b/tests/ipc_live_test.c index 22ac679..be74c5a 100644 --- a/tests/ipc_live_test.c +++ b/tests/ipc_live_test.c @@ -161,7 +161,7 @@ tryclient(char *path, int64_t deadline, int *client) fd = connectsocket(path, deadline); if(fd < 0) return errno == ETIMEDOUT ? -1 : 0; - if(!sendkey(fd, 1, 0, Kmodfirst)){ + if(!sendkey(fd, 1, 0, 0)){ close(fd); return 0; } @@ -208,7 +208,7 @@ overflowrejected(char *path) fd = connectsocket(path, deadline); if(fd < 0) return fail("overflow connect: %s", strerror(errno)); - if(!sendkey(fd, 1, 0, Kmodfirst)){ + if(!sendkey(fd, 1, 0, 0)){ close(fd); return 1; } @@ -286,7 +286,7 @@ runcapacity(char *path) fail("connect capacity client %d: %s", i, strerror(errno)); goto out; } - if(!requestkey(client[i], 1, 0, Kmodfirst, 0, "", "", + if(!requestkey(client[i], 1, 0, 0, 0, "", "", "capacity modifier")) goto out; } diff --git a/tests/ipc_test.c b/tests/ipc_test.c index 8654e32..26f6a23 100644 --- a/tests/ipc_test.c +++ b/tests/ipc_test.c @@ -60,6 +60,7 @@ ipc_masks_modifiers(struct ct *t) 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, 0, ipckeysym(0xffe1, 0)); /* Shift_L */ 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)); diff --git a/tests/live.c b/tests/live.c index 2395147..6cb1957 100644 --- a/tests/live.c +++ b/tests/live.c @@ -691,5 +691,5 @@ ipcprobe(int fd, char *where) { unsigned char empty[] = {0, 0, 0, 0, 0}; - return ipcrequest(fd, 0, Kmodfirst, empty, sizeof empty, where); + return ipcrequest(fd, 0, 0, empty, sizeof empty, where); } diff --git a/tests/server_test.c b/tests/server_test.c index 0f9d288..da70a31 100644 --- a/tests/server_test.c +++ b/tests/server_test.c @@ -287,7 +287,7 @@ server_connection_ownership(struct ct *t) 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)) + if(!sendkey(t, &b, 1, 0, 0)) goto cleanup; req = nextrequest(t, &f.pump, Keypress); allowrequest(&f.pump);