fix(xim): follow keyboard layout changes
kinit() sets up the XKB extension, after which the server stops sending core MappingNotify to this client, so the refresh branch never fired and strans kept its startup keymap; setxkbmap after launch left every XIM key resolved against the old layout. Select XKB NewKeyboardNotify and MapNotify (with the map parts, or MapNotify is never delivered) and rebuild the keymap on those events instead.
This commit is contained in:
24
xim/xim.c
24
xim/xim.c
@@ -4,6 +4,7 @@
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xkb.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-x11.h>
|
||||
#include <xcb-imdkit/imdkit.h>
|
||||
@@ -37,6 +38,7 @@ enum
|
||||
static xcb_connection_t *conn;
|
||||
static xcb_im_t *xim;
|
||||
static struct xkb_state *kstate;
|
||||
static uint8_t xkbevent;
|
||||
static xcb_window_t rootwin;
|
||||
static Ic *ics;
|
||||
static Ic *preowner;
|
||||
@@ -55,6 +57,7 @@ ximlog(char *msg)
|
||||
fprint(2, "strans: xim: %s\n", msg);
|
||||
}
|
||||
|
||||
/* Reads the server's keymap; XKB-aware clients get XKB events, not MappingNotify. */
|
||||
static int
|
||||
kinit(void)
|
||||
{
|
||||
@@ -70,7 +73,7 @@ kinit(void)
|
||||
context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if(context == nil || !xkb_x11_setup_xkb_extension(conn,
|
||||
XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION,
|
||||
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, nil, nil, nil, nil))
|
||||
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, nil, nil, &xkbevent, nil))
|
||||
goto out;
|
||||
device = xkb_x11_get_core_keyboard_device_id(conn);
|
||||
if(device < 0)
|
||||
@@ -93,6 +96,22 @@ out:
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void
|
||||
kwatch(void)
|
||||
{
|
||||
u16int events, parts;
|
||||
|
||||
events = XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
|
||||
XCB_XKB_EVENT_TYPE_MAP_NOTIFY;
|
||||
parts = XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS |
|
||||
XCB_XKB_MAP_PART_MODIFIER_MAP |
|
||||
XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
|
||||
XCB_XKB_MAP_PART_KEY_ACTIONS | XCB_XKB_MAP_PART_VIRTUAL_MODS |
|
||||
XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP;
|
||||
xcb_xkb_select_events(conn, XCB_XKB_ID_USE_CORE_KBD, events, 0,
|
||||
events, parts, parts, nil);
|
||||
}
|
||||
|
||||
static xcb_screen_t*
|
||||
getscreen(int scr)
|
||||
{
|
||||
@@ -472,6 +491,7 @@ ximinit(void)
|
||||
ximlog("cannot read keyboard mapping");
|
||||
return -1;
|
||||
}
|
||||
kwatch();
|
||||
win = xcb_generate_id(conn);
|
||||
xcb_create_window(conn, XCB_COPY_FROM_PARENT, win, screen->root,
|
||||
0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||
@@ -511,7 +531,7 @@ ximthread(void *arg)
|
||||
break;
|
||||
while((ev = xcb_poll_for_event(conn)) != nil){
|
||||
type = ev->response_type & ~0x80;
|
||||
if(type == XCB_MAPPING_NOTIFY){
|
||||
if(type == xkbevent){
|
||||
if(kinit() < 0)
|
||||
ximlog("cannot refresh keyboard mapping");
|
||||
}else
|
||||
|
||||
Reference in New Issue
Block a user