From 7d47acd34b34d51065847ac4ddf287e88b080953 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 9 Feb 2010 09:59:43 -0500 Subject: [PATCH] starting to try figure out xkb and how to use it for better international/multilayout support --- obt/display.c | 10 ++++++---- obt/keyboard.c | 4 ++++ openbox/event.c | 50 +++++++++++++++++++++++++++++++++++++---------- openbox/menu.c | 2 +- openbox/openbox.c | 11 +++++++++++ openbox/openbox.h | 1 + 6 files changed, 63 insertions(+), 15 deletions(-) diff --git a/obt/display.c b/obt/display.c index f34fc574..37b12157 100644 --- a/obt/display.c +++ b/obt/display.c @@ -58,8 +58,8 @@ gboolean obt_display_open(const char *display_name) n = display_name ? g_strdup(display_name) : NULL; obt_display = d = XOpenDisplay(n); if (d) { - gint junk; - (void)junk; + gint junk, major, minor; + (void)junk, (void)major, (void)minor; if (fcntl(ConnectionNumber(d), F_SETFD, 1) == -1) g_message("Failed to set display as close-on-exec"); @@ -67,12 +67,14 @@ gboolean obt_display_open(const char *display_name) /* read what extensions are present */ #ifdef XKB + major = XkbMajorVersion; + minor = XkbMinorVersion; obt_display_extension_xkb = XkbQueryExtension(d, &junk, &obt_display_extension_xkb_basep, &junk, - NULL, NULL); + &major, &minor); if (!obt_display_extension_xkb) - g_message("XKB extension is not present on the server"); + g_message("XKB extension is not present on the server or too old"); #endif #ifdef SHAPE diff --git a/obt/keyboard.c b/obt/keyboard.c index 6bb13861..a1d18283 100644 --- a/obt/keyboard.c +++ b/obt/keyboard.c @@ -64,6 +64,7 @@ void obt_keyboard_reload(void) /* note: modmap->max_keypermod can be 0 when there is no valid key layout available */ + XDisplayKeycodes(obt_display, &min_keycode, &max_keycode); keymap = XGetKeyboardMapping(obt_display, min_keycode, max_keycode - min_keycode + 1, @@ -228,6 +229,9 @@ gunichar obt_keyboard_keycode_to_unichar(guint keycode) if (unikey == (gunichar)-1 || unikey == (gunichar)-2 || unikey == 0) unikey = 0; } + if (key) { + g_print("key %s\n", key); + } g_free(key); return unikey; } diff --git a/openbox/event.c b/openbox/event.c index 1e6df48d..b2f9be4e 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -56,9 +56,6 @@ #ifdef HAVE_UNISTD_H # include /* for usleep() */ #endif -#ifdef XKB -# include -#endif #ifdef USE_SM #include @@ -141,6 +138,13 @@ void event_startup(gboolean reconfig) IceAddConnectionWatch(ice_watch, NULL); #endif +#ifdef XKB + /* ask to be notified when the keyboard group changes */ + if (obt_display_extension_xkb) + XkbSelectEventDetails(obt_display, XkbUseCoreKbd, XkbStateNotify, + XkbGroupStateMask, XkbGroupStateMask); +#endif + client_add_destroy_notify(focus_delay_client_dest, NULL); } @@ -650,14 +654,40 @@ static void event_process(const XEvent *ec, gpointer data) event_handle_root(e); else if (e->type == MapRequest) window_manage(window); +#ifdef XKB + else if (obt_display_extension_xkb && + e->type == obt_display_extension_xkb_basep) + { + switch (((XkbAnyEvent*)e)->xkb_type) { + case XkbStateNotify: + /* the effective xkb group changed, so they keyboard layout is now + different */ + if (((XkbStateNotifyEvent*)e)->changed & XkbGroupStateMask) + ob_reconfigure_keyboard(); + + break; + default: + break; + } + } +#endif else if (e->type == MappingNotify) { - /* keyboard layout changes for modifier mapping changes. reload the - modifier map, and rebind all the key bindings as appropriate */ - ob_debug("Keyboard map changed. Reloading keyboard bindings."); - ob_set_state(OB_STATE_RECONFIGURING); - obt_keyboard_reload(); - keyboard_rebind(); - ob_set_state(OB_STATE_RUNNING); + ob_debug("MappingNotify"); + +#ifdef XKB + /* the keyboard map changed, so we might need to listen on a new + device */ + if (obt_display_extension_xkb) { + XkbSelectEvents(obt_display, XkbUseCoreKbd, XkbStateNotifyMask, 0); + XRefreshKeyboardMapping(&e->xmapping); + XkbSelectEventDetails(obt_display, XkbUseCoreKbd, XkbStateNotify, + XkbGroupStateMask, XkbGroupStateMask); + } +#else + XRefreshKeyboardMapping(&e->xmapping); +#endif + + ob_reconfigure_keyboard(); } else if (e->type == ClientMessage) { /* This is for _NET_WM_REQUEST_FRAME_EXTENTS messages. They come for diff --git a/openbox/menu.c b/openbox/menu.c index ac28ade9..812f124a 100644 --- a/openbox/menu.c +++ b/openbox/menu.c @@ -236,7 +236,7 @@ static gunichar parse_shortcut(const gchar *label, gboolean allow_shortcut, /* you have to use a printable ascii character for shortcuts don't allow space either, so you can have like "a _ b" */ - if (VALID_SHORTCUT(*(i+1))) { + if (*(i+1)) { shortcut = g_unichar_tolower(g_utf8_get_char(i+1)); *position = i - *strippedlabel; *always_show = TRUE; diff --git a/openbox/openbox.c b/openbox/openbox.c index d2b66b5b..72a013f6 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -718,6 +718,17 @@ void ob_reconfigure(void) ob_exit(0); } +void ob_reconfigure_keyboard(void) +{ + /* keyboard mapping or group changed, so reload the keyboard map + and rebind all the key bindings */ + ob_debug("Keyboard map changed. Reloading keyboard bindings."); + ob_set_state(OB_STATE_RECONFIGURING); + obt_keyboard_reload(); + keyboard_rebind(); + ob_set_state(OB_STATE_RUNNING); +} + void ob_exit(gint code) { exitcode = code; diff --git a/openbox/openbox.h b/openbox/openbox.h index c43f0a61..be0c1f30 100644 --- a/openbox/openbox.h +++ b/openbox/openbox.h @@ -57,6 +57,7 @@ void ob_exit(gint code); void ob_exit_replace(void); void ob_reconfigure(void); +void ob_reconfigure_keyboard(void); void ob_exit_with_error(const gchar *msg) G_GNUC_NORETURN; -- 2.34.1