ipc: share one keysym and modifier mapping across frontends
The keysym-to-engine-key rule lived in ibus.c, xim/xim.c and gtk/main.c, and the copies disagreed: GTK sent keypad digits as special keys while IBus and XIM sent '1'..'9'. Modifiers were rebuilt bit by bit in two places although Mmask already is the X core layout; only the virtual Super bit (26) that GDK and IBus set needs folding. ipckey/ipcmod in ipc.c serve the daemon, the module and the tests.
This commit is contained in:
34
gtk/main.c
34
gtk/main.c
@@ -223,36 +223,6 @@ srvconnect(Im *im)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
|
||||||
kget(uint32_t gdk)
|
|
||||||
{
|
|
||||||
uint32_t u;
|
|
||||||
|
|
||||||
u = gdk_keyval_to_unicode(gdk);
|
|
||||||
if((gdk & 0xff000000) == 0x01000000 && u != 0)
|
|
||||||
return u;
|
|
||||||
if(gdk >= 0xff00 && gdk <= 0xffff)
|
|
||||||
return Kspec + (gdk - 0xff00);
|
|
||||||
return u;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t
|
|
||||||
mget(uint32_t state)
|
|
||||||
{
|
|
||||||
uint32_t m;
|
|
||||||
|
|
||||||
m = 0;
|
|
||||||
if(state & GDK_SHIFT_MASK)
|
|
||||||
m |= Mshift;
|
|
||||||
if(state & GDK_CONTROL_MASK)
|
|
||||||
m |= Mctrl;
|
|
||||||
if(state & GDK_MOD1_MASK)
|
|
||||||
m |= Malt;
|
|
||||||
if(state & GDK_SUPER_MASK)
|
|
||||||
m |= Msuper;
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
simplecommit(GtkIMContext *ctx, const char *s, Im *im)
|
simplecommit(GtkIMContext *ctx, const char *s, Im *im)
|
||||||
{
|
{
|
||||||
@@ -327,8 +297,8 @@ kpress(GtkIMContext *ctx, GdkEventKey *ev)
|
|||||||
}
|
}
|
||||||
if(im->simpleactive)
|
if(im->simpleactive)
|
||||||
return simplefilter(ctx, ev, 0);
|
return simplefilter(ctx, ev, 0);
|
||||||
key = kget(ev->keyval);
|
key = ipckey(ev->keyval, gdk_keyval_to_unicode(ev->keyval));
|
||||||
mod = mget(ev->state);
|
mod = ipcmod(ev->state);
|
||||||
if(im->private || key == 0)
|
if(im->private || key == 0)
|
||||||
return simplefilter(ctx, ev, 0);
|
return simplefilter(ctx, ev, 0);
|
||||||
if(srvconnect(im) < 0)
|
if(srvconnect(im) < 0)
|
||||||
|
|||||||
30
ibus.c
30
ibus.c
@@ -17,7 +17,6 @@ enum
|
|||||||
Maxwatches = 2*Maxconns + 1,
|
Maxwatches = 2*Maxconns + 1,
|
||||||
Maxcontexts = Maxclients,
|
Maxcontexts = Maxclients,
|
||||||
Relmask = 1<<30,
|
Relmask = 1<<30,
|
||||||
Ibussupermask = 1<<26,
|
|
||||||
/* IBus wire constants; the daemon does not link libibus. */
|
/* IBus wire constants; the daemon does not link libibus. */
|
||||||
Ibuscappreedit = 1<<0,
|
Ibuscappreedit = 1<<0,
|
||||||
Ibuspurposepassword = 8,
|
Ibuspurposepassword = 8,
|
||||||
@@ -266,32 +265,6 @@ togglewatch(DBusWatch *w, void *_)
|
|||||||
USED(_);
|
USED(_);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32int
|
|
||||||
kget(u32int sym)
|
|
||||||
{
|
|
||||||
u32int c;
|
|
||||||
|
|
||||||
c = xkb_keysym_to_utf32(sym);
|
|
||||||
if(c >= ' ' && c != 0x7f)
|
|
||||||
return c;
|
|
||||||
if(sym >= 0xff00 && sym <= 0xffff)
|
|
||||||
return Kspec + (sym - 0xff00);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32int
|
|
||||||
mget(u32int state)
|
|
||||||
{
|
|
||||||
u32int m;
|
|
||||||
|
|
||||||
m = 0;
|
|
||||||
if(state & (1<<0)) m |= Mshift;
|
|
||||||
if(state & (1<<2)) m |= Mctrl;
|
|
||||||
if(state & (1<<3)) m |= Malt;
|
|
||||||
if(state & ((1<<6)|Ibussupermask)) m |= Msuper;
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Ictx*
|
static Ictx*
|
||||||
findcontext(DBusConnection *conn, const char *path)
|
findcontext(DBusConnection *conn, const char *path)
|
||||||
{
|
{
|
||||||
@@ -385,7 +358,8 @@ processkey(Ictx *ctx, u32int sym, u32int state, Keyres *res)
|
|||||||
{
|
{
|
||||||
if(state & Relmask || !ctx->focused || hidden(ctx))
|
if(state & Relmask || !ctx->focused || hidden(ctx))
|
||||||
return 0;
|
return 0;
|
||||||
sendrequest(ctx, Keypress, kget(sym), mget(state), res);
|
sendrequest(ctx, Keypress, ipckey(sym, xkb_keysym_to_utf32(sym)),
|
||||||
|
ipcmod(state), res);
|
||||||
if(preowner != nil && preowner != ctx)
|
if(preowner != nil && preowner != ctx)
|
||||||
checkpreowner();
|
checkpreowner();
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
25
ipc.c
25
ipc.c
@@ -223,6 +223,31 @@ Bad:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Engine key for an X keysym and its Unicode value: printable characters
|
||||||
|
* as themselves, the function keysyms 0xff00-0xffff as Kspec+offset.
|
||||||
|
*/
|
||||||
|
uint32_t
|
||||||
|
ipckey(uint32_t sym, uint32_t unicode)
|
||||||
|
{
|
||||||
|
if(unicode >= ' ' && unicode != 0x7f)
|
||||||
|
return unicode;
|
||||||
|
if(sym >= 0xff00 && sym <= 0xffff)
|
||||||
|
return Kspec + (sym - 0xff00);
|
||||||
|
return unicode;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
ipcmod(uint32_t state)
|
||||||
|
{
|
||||||
|
uint32_t m;
|
||||||
|
|
||||||
|
m = state & Mmask;
|
||||||
|
if(state & Msupervirt)
|
||||||
|
m |= Msuper;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ipcpackreq(unsigned char req[Ipcreqsz], int want, uint32_t mod,
|
ipcpackreq(unsigned char req[Ipcreqsz], int want, uint32_t mod,
|
||||||
uint32_t key)
|
uint32_t key)
|
||||||
|
|||||||
4
ipc.h
4
ipc.h
@@ -38,11 +38,13 @@ enum
|
|||||||
Kmodfirst = Kspec|0xe1,
|
Kmodfirst = Kspec|0xe1,
|
||||||
Kmodlast = Kspec|0xee,
|
Kmodlast = Kspec|0xee,
|
||||||
|
|
||||||
|
/* X core modifier bits; GDK and IBus also flag Super at bit 26. */
|
||||||
Mshift = 1<<0,
|
Mshift = 1<<0,
|
||||||
Mctrl = 1<<2,
|
Mctrl = 1<<2,
|
||||||
Malt = 1<<3,
|
Malt = 1<<3,
|
||||||
Msuper = 1<<6,
|
Msuper = 1<<6,
|
||||||
Mmask = Mshift|Mctrl|Malt|Msuper,
|
Mmask = Mshift|Mctrl|Malt|Msuper,
|
||||||
|
Msupervirt = 1<<26,
|
||||||
|
|
||||||
Ipcreqsz = 6,
|
Ipcreqsz = 6,
|
||||||
Ipccaretsz = 16,
|
Ipccaretsz = 16,
|
||||||
@@ -70,6 +72,8 @@ struct Ipcresp
|
|||||||
size_t preeditlen;
|
size_t preeditlen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint32_t ipckey(uint32_t, uint32_t);
|
||||||
|
uint32_t ipcmod(uint32_t);
|
||||||
void ipcpackreq(unsigned char[Ipcreqsz], int, uint32_t, uint32_t);
|
void ipcpackreq(unsigned char[Ipcreqsz], int, uint32_t, uint32_t);
|
||||||
void ipcpackreset(unsigned char[Ipcreqsz], int);
|
void ipcpackreset(unsigned char[Ipcreqsz], int);
|
||||||
void ipcpackcap(unsigned char[Ipcreqsz], int);
|
void ipcpackcap(unsigned char[Ipcreqsz], int);
|
||||||
|
|||||||
@@ -46,6 +46,18 @@ ipc_masks_modifiers(struct ct *t)
|
|||||||
CT_EQ_UINT(t, 0, mod);
|
CT_EQ_UINT(t, 0, mod);
|
||||||
CT_EQ_UINT(t, 0, key);
|
CT_EQ_UINT(t, 0, key);
|
||||||
CT_CHECK(t, ipcreqreset(buf));
|
CT_CHECK(t, ipcreqreset(buf));
|
||||||
|
|
||||||
|
/* Frontends share one keysym and modifier mapping. */
|
||||||
|
CT_EQ_UINT(t, 'a', ipckey('a', 'a'));
|
||||||
|
CT_EQ_UINT(t, '1', ipckey(0xffb1, '1')); /* KP_1 */
|
||||||
|
CT_EQ_UINT(t, Kret, ipckey(0xff0d, '\r'));
|
||||||
|
CT_EQ_UINT(t, Kback, ipckey(0xff08, 8));
|
||||||
|
CT_EQ_UINT(t, Kspec + 0xff, ipckey(0xffff, 0x7f)); /* Delete */
|
||||||
|
CT_EQ_UINT(t, 0x1f642, ipckey(0x101f642, 0x1f642));
|
||||||
|
CT_EQ_UINT(t, 0, ipckey(0xfe03, 0)); /* ISO_Level3_Shift */
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
20
xim/xim.c
20
xim/xim.c
@@ -249,12 +249,6 @@ out:
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32int
|
|
||||||
kget(uint8_t kc, u16int state)
|
|
||||||
{
|
|
||||||
return keymaplookup(kstate, kc, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static xcb_screen_t*
|
static xcb_screen_t*
|
||||||
getscreen(int scr)
|
getscreen(int scr)
|
||||||
{
|
{
|
||||||
@@ -466,7 +460,7 @@ sendrequest(Ic *state, int op, u32int key, u32int mod, Keyres *res)
|
|||||||
kr.cap = state->cap;
|
kr.cap = state->cap;
|
||||||
kr.op = op;
|
kr.op = op;
|
||||||
kr.ks = key;
|
kr.ks = key;
|
||||||
kr.mod = mod & Mmask;
|
kr.mod = ipcmod(mod);
|
||||||
kr.caret = state->caret;
|
kr.caret = state->caret;
|
||||||
kr.reply = replyc;
|
kr.reply = replyc;
|
||||||
chansend(keyc, &kr);
|
chansend(keyc, &kr);
|
||||||
@@ -557,17 +551,11 @@ kpress(Ic *state, xcb_key_press_event_t *ev)
|
|||||||
{
|
{
|
||||||
Keyres res;
|
Keyres res;
|
||||||
char buf[Maxutf];
|
char buf[Maxutf];
|
||||||
u32int key, rune;
|
u32int key;
|
||||||
int n, wasvalid;
|
int n, wasvalid;
|
||||||
|
|
||||||
key = kget(ev->detail, ev->state);
|
key = keymaplookup(kstate, ev->detail, ev->state);
|
||||||
rune = xkb_keysym_to_utf32(key);
|
key = ipckey(key, xkb_keysym_to_utf32(key));
|
||||||
if(rune >= ' ' && rune != 0x7f)
|
|
||||||
key = rune;
|
|
||||||
else if(key >= 0xff00 && key <= 0xffff)
|
|
||||||
key = Kspec + (key - 0xff00);
|
|
||||||
else
|
|
||||||
key = rune;
|
|
||||||
if(meaningful(key)){
|
if(meaningful(key)){
|
||||||
wasvalid = state->caret.valid;
|
wasvalid = state->caret.valid;
|
||||||
refreshplace(state);
|
refreshplace(state);
|
||||||
|
|||||||
Reference in New Issue
Block a user