From: Dana Jansens Date: Tue, 9 Feb 2010 22:29:13 +0000 (-0500) Subject: trying to use keyboard stuff better to get stuff in the menu for the current effectiv... X-Git-Tag: xkb~3 X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=ee9e0893849fe3269075b3d7782b47f1c8106e4a;p=dana%2Fopenbox.git trying to use keyboard stuff better to get stuff in the menu for the current effective group rather than the base group, but no change yet --- diff --git a/obt/display.h b/obt/display.h index ff20f9c9..7a0329ad 100644 --- a/obt/display.h +++ b/obt/display.h @@ -56,6 +56,8 @@ extern gint obt_display_extension_sync_basep; extern Display* obt_display; +/*! Open the X display. You should call g_set_prgname() before calling this + function for X Input Methods to work correctly */ gboolean obt_display_open(const char *display_name); void obt_display_close(void); diff --git a/obt/keyboard.c b/obt/keyboard.c index a1d18283..738888ef 100644 --- a/obt/keyboard.c +++ b/obt/keyboard.c @@ -49,13 +49,70 @@ static gboolean hyper_l = FALSE; static gboolean started = FALSE; +static XIM xim = NULL; +static XIMStyle xim_style = 0; +static XIC xic = NULL; +static Window xic_window = None; + void obt_keyboard_reload(void) { gint i, j, k; + gchar *aname, *aclass; + gchar firstc[7]; if (started) obt_keyboard_shutdown(); /* free stuff */ started = TRUE; + /* initialize the Input Method */ + + aname = g_strdup(g_get_prgname()); + if (!aname) aname = g_strdup("obt"); + + /* capitalize first letter of the class */ + i = g_unichar_to_utf8(g_unichar_toupper(g_utf8_get_char(aname)), + firstc); + firstc[i] = '\0'; + aclass = g_strdup_printf("%s%s", firstc, g_utf8_next_char(aname)); + + g_print("Opening Input Method for %s %s\n", aname, aclass); + xim = XOpenIM(obt_display, NULL, aname, aclass); + + g_free(aclass); + g_free(aname); + + if (!xim) + g_message("Failed to open an Input Method"); + else { + XIMStyles *xim_styles = NULL; + char *r; + + /* get the input method styles */ + r = XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL); + if (r || !xim_styles) + g_message("Input Method does not support any styles"); + if (xim_styles) { + /* pick a style that doesnt need preedit or status */ + for (i = 0; i < xim_styles->count_styles; ++i) { + if (xim_styles->supported_styles[i] == + (XIMPreeditNothing | XIMStatusNothing)) + { + xim_style = xim_styles->supported_styles[i]; + break; + } + } + XFree(xim_styles); + } + + if (!xim_style) + g_message("Input Method does not support a usable style"); + else if (xic_window) + xic = XCreateIC(xim, + XNInputStyle, xim_style, + XNClientWindow, xic_window, + XNFocusWindow, xic_window, + NULL); + } + /* reset the keys to not be bound to any masks */ for (i = 0; i < OBT_KEYBOARD_NUM_MODKEYS; ++i) modkeys_keys[i] = 0; @@ -64,7 +121,6 @@ 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, @@ -105,6 +161,11 @@ void obt_keyboard_shutdown(void) modmap = NULL; XFree(keymap); keymap = NULL; + if (xic) XDestroyIC(xic); + xic = NULL; + if (xim) XCloseIM(xim); + xim = NULL; + xim_style = 0; started = FALSE; } @@ -207,21 +268,79 @@ KeyCode* obt_keyboard_keysym_to_keycode(KeySym sym) return ret; } -gchar *obt_keyboard_keycode_to_string(guint keycode) +void obt_keyboard_set_input_context(Window window) { - KeySym sym; + if (xic) { + XDestroyIC(xic); + xic = NULL; + } + xic_window = window; + if (xic_window) + xic = XCreateIC(xim, + XNInputStyle, xim_style, + XNClientWindow, xic_window, + XNFocusWindow, xic_window, + NULL); + g_message("Created Input Context (0x%x) for window 0x%x\n", + xic, xic_window); +} - if ((sym = XKeycodeToKeysym(obt_display, keycode, 0)) != NoSymbol) +gchar *obt_keyboard_keypress_to_string(XKeyPressedEvent *ev) +{ + KeySym sym; + int ret; + Status status; + gchar *buf; + + if (xic) { +#ifdef X_HAVE_UTF8_STRING + ret = Xutf8LookupString(xic, ev, buf, 0, &sym, &status); +#else + ret = XmbLookupString(xic, ev, buf, 0, &sym, &status); +#endif + if (status == XBufferOverflow) { + g_message("bufferoverflow"); + buf = g_malloc(ret+1); + buf[ret] = '\0'; +#ifdef X_HAVE_UTF8_STRING + ret = Xutf8LookupString(xic, ev, buf, ret+1, &sym, &status); + g_message("bufferoverflow read %d bytes", ret); +#else + ret = XmbLookupString(xic, ev, buf, ret+1, &sym, &status); +#endif + if (status == XLookupChars || status == XLookupBoth) { +#ifndef X_HAVE_UTF8_STRING + gchar *buf2 = buf; + buf = g_locale_to_utf8(buf2, -1, NULL, NULL, NULL); + g_free(buf2); +#endif + return buf; + } + } + else if (status == XLookupKeySym) + return g_locale_to_utf8(XKeysymToString(sym), -1, + NULL, NULL, NULL); + } + + buf = g_malloc(2); + buf[1] = '\0'; + ret = XLookupString(ev, buf, 1, &sym, NULL); + if (ret) + return buf; + + g_free(buf); + if (sym != NoSymbol) return g_locale_to_utf8(XKeysymToString(sym), -1, NULL, NULL, NULL); + return NULL; } -gunichar obt_keyboard_keycode_to_unichar(guint keycode) +gunichar obt_keyboard_keypress_to_unichar(XKeyPressedEvent *ev) { gunichar unikey = 0; char *key; - if ((key = obt_keyboard_keycode_to_string(keycode)) != NULL && + if ((key = obt_keyboard_keypress_to_string(ev)) != NULL && /* don't accept keys that aren't a single letter, like "space" */ key[1] == '\0') { diff --git a/obt/keyboard.h b/obt/keyboard.h index 4fb60186..ae9f9971 100644 --- a/obt/keyboard.h +++ b/obt/keyboard.h @@ -57,11 +57,18 @@ guint obt_keyboard_modkey_to_modmask(ObtModkeysKey key); /*! Convert a KeySym to all the KeyCodes which generate it. */ KeyCode* obt_keyboard_keysym_to_keycode(KeySym sym); -/*! Give the string form of a KeyCode */ -gchar *obt_keyboard_keycode_to_string(guint keycode); +/*! Set the input context to be the given window. This must be called + before using obt_keyboard_keycode_to_unichar() and + obt_keyboard_keycode_to_string(). + @window The window where input focus is (logically). Can be None. +*/ +void obt_keyboard_set_input_context(Window window); + +/*! Give the string form of a KeyPressEvent */ +gchar *obt_keyboard_keypress_to_string(XKeyPressedEvent *ev); -/*! Translate a KeyCode to the unicode character it represents */ -gunichar obt_keyboard_keycode_to_unichar(guint keycode); +/*! Translate a KeyPressEvent to the unicode character it represents */ +gunichar obt_keyboard_keypress_to_unichar(XKeyPressedEvent *ev); G_END_DECLS diff --git a/openbox/event.c b/openbox/event.c index b2f9be4e..da7771e3 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -665,6 +665,18 @@ static void event_process(const XEvent *ec, gpointer data) if (((XkbStateNotifyEvent*)e)->changed & XkbGroupStateMask) ob_reconfigure_keyboard(); + { + //XkbDescPtr kbd; + XkbStateRec state; + + //kbd = XkbAllocKeyboard(); + XkbGetState(obt_display, XkbUseCoreKbd, &state); + g_print("effective group: %d\n", state.group); + g_print("base group: %d\n", state.base_group); + + //XkbFreeKeyboard(kbd, 0, TRUE); + } + break; default: break; @@ -1809,14 +1821,13 @@ static gboolean event_handle_menu_input(XEvent *ev) f->child == e->frame) menu_frame_select(e->frame, e, FALSE); } - else if (ev->type == KeyPress || ev->type == KeyRelease) { + else if (ev->type == KeyPress) { guint keycode, state; - gunichar unikey; + static gunichar unikey; ObMenuFrame *frame; keycode = ev->xkey.keycode; state = ev->xkey.state; - unikey = obt_keyboard_keycode_to_unichar(keycode); frame = find_active_or_last_menu(); if (frame == NULL) @@ -1873,6 +1884,12 @@ static gboolean event_handle_menu_input(XEvent *ev) menu_frame_select_last(frame); ret = TRUE; } + + /* Remember the last keypress */ + else { + unikey = obt_keyboard_keypress_to_unichar(&ev->xkey); + ret = !!unikey; + } } /* Use KeyRelease events for running things so that the key release diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 4ee5d31e..5ee55b1c 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -27,6 +27,7 @@ #include "openbox.h" #include "config.h" #include "obt/prop.h" +#include "obt/keyboard.h" #include "obrender/theme.h" #define PADDING 2 @@ -960,6 +961,8 @@ static gboolean menu_frame_show(ObMenuFrame *self) ungrab_pointer(); return FALSE; } + + obt_keyboard_set_input_context(obt_root(ob_screen)); } menu_frame_update(self); @@ -1082,6 +1085,8 @@ static void menu_frame_hide(ObMenuFrame *self) if (menu_frame_visible == NULL) { /* last menu shown */ + obt_keyboard_set_input_context(None); + ungrab_pointer(); ungrab_keyboard(); }