From: Dana Jansens Date: Wed, 10 Feb 2010 22:13:28 +0000 (-0500) Subject: the key translation stuff works but the menu event code is a bit of a train wreck. X-Git-Tag: xkb~1 X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=94b028e289d9b417b67478955eaa797daf5d7288;p=dana%2Fopenbox.git the key translation stuff works but the menu event code is a bit of a train wreck. --- diff --git a/obt/keyboard.c b/obt/keyboard.c index 738888ef..0ca93c0e 100644 --- a/obt/keyboard.c +++ b/obt/keyboard.c @@ -28,7 +28,7 @@ Mod2Mask (1<<4), Mod3Mask (1<<5), Mod4Mask (1<<6), Mod5Mask (1<<7) */ #define NUM_MASKS 8 -#define ALL_MASKS 0xff /* an or'ing of all 8 keyboard masks */ +#define ALL_MASKS 0xf /* an or'ing of all 8 keyboard masks */ /* Get the bitflag for the n'th modifier mask */ #define nth_mask(n) (1 << n) @@ -59,6 +59,11 @@ void obt_keyboard_reload(void) gint i, j, k; gchar *aname, *aclass; gchar firstc[7]; + guint ctrl; + + ctrl = XkbPCF_GrabsUseXKBStateMask | + XkbPCF_LookupStateWhenGrabbed; + //XkbSetPerClientControls(obt_display, ctrl, &ctrl); if (started) obt_keyboard_shutdown(); /* free stuff */ started = TRUE; @@ -281,76 +286,101 @@ void obt_keyboard_set_input_context(Window window) XNClientWindow, xic_window, XNFocusWindow, xic_window, NULL); - g_message("Created Input Context (0x%x) for window 0x%x\n", - xic, xic_window); + g_message("Created Input Context (0x%lx) for window 0x%lx", + (gulong)xic, (gulong)xic_window); } -gchar *obt_keyboard_keypress_to_string(XKeyPressedEvent *ev) +gunichar obt_keyboard_keypress_to_unichar(XKeyPressedEvent *ev) { + gunichar unikey = 0; KeySym sym; - int ret; Status status; - gchar *buf; + gchar *buf, fixbuf[4]; /* 4 is enough for a utf8 char */ + gint r, bufsz; + gboolean got_string; + + g_print("state: %x\n", ev->state); + got_string = FALSE; if (xic) { + + buf = fixbuf; + bufsz = sizeof(fixbuf); + #ifdef X_HAVE_UTF8_STRING - ret = Xutf8LookupString(xic, ev, buf, 0, &sym, &status); + r = Xutf8LookupString(xic, ev, buf, bufsz, &sym, &status); #else - ret = XmbLookupString(xic, ev, buf, 0, &sym, &status); + r = XmbLookupString(xic, ev, buf, bufsz, &sym, &status); #endif + g_assert(r <= bufsz); + + g_print("status %d\n", status); + if (status == XBufferOverflow) { - g_message("bufferoverflow"); - buf = g_malloc(ret+1); - buf[ret] = '\0'; + g_message("bufferoverflow, need %d bytes", r); + buf = g_new(char, r); + bufsz = r; + #ifdef X_HAVE_UTF8_STRING - ret = Xutf8LookupString(xic, ev, buf, ret+1, &sym, &status); - g_message("bufferoverflow read %d bytes", ret); + r = Xutf8LookupString(xic, ev, buf, bufsz, &sym, &status); #else - ret = XmbLookupString(xic, ev, buf, ret+1, &sym, &status); + r = XmbLookupString(xic, ev, buf, bufsz, &sym, &status); #endif - if (status == XLookupChars || status == XLookupBoth) { + buf[r] = '\0'; + + g_message("bufferoverflow read %d bytes, status=%d", r, status); + { + int i; + for (i = 0; i < r + 1; ++i) + g_print("%u", (guchar)buf[i]); + g_print("\n"); + } + } + + if ((status == XLookupChars || status == XLookupBoth)) { + g_message("read %d bytes", r); + if ((guchar)buf[0] >= 32) { /* not an ascii control character */ #ifndef X_HAVE_UTF8_STRING + /* convert to utf8 */ gchar *buf2 = buf; - buf = g_locale_to_utf8(buf2, -1, NULL, NULL, NULL); + buf = g_locale_to_utf8(buf2, r, NULL, NULL, NULL); g_free(buf2); #endif - return buf; + + got_string = TRUE; } } - else if (status == XLookupKeySym) - return g_locale_to_utf8(XKeysymToString(sym), -1, - NULL, NULL, NULL); + else + g_message("Bad keycode lookup. Keysym 0x%x Status: %s\n", + (guint) sym, + (status == XBufferOverflow ? "BufferOverflow" : + status == XLookupNone ? "XLookupNone" : + status == XLookupKeySym ? "XLookupKeySym" : + "Unknown status")); + } + else { + buf = fixbuf; + bufsz = sizeof(fixbuf); + r = XLookupString(ev, buf, bufsz, &sym, NULL); + g_assert(r <= bufsz); + if ((guchar)buf[0] >= 32) /* not an ascii control character */ + got_string = TRUE; } - - 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_keypress_to_unichar(XKeyPressedEvent *ev) -{ - gunichar unikey = 0; - char *key; - - if ((key = obt_keyboard_keypress_to_string(ev)) != NULL && - /* don't accept keys that aren't a single letter, like "space" */ - key[1] == '\0') - { - unikey = g_utf8_get_char_validated(key, -1); - if (unikey == (gunichar)-1 || unikey == (gunichar)-2 || unikey == 0) + if (got_string) { + unikey = g_utf8_get_char_validated(buf, -1); + if (unikey == (gunichar)-1 || unikey == (gunichar)-2) unikey = 0; + + if (unikey) { + char *key = g_strndup(buf, r); + g_print("key %s\n", key); + g_free(key); + } } - if (key) { - g_print("key %s\n", key); - } - g_free(key); + + if (buf != fixbuf) g_free(buf); + + g_print("unikey: %lu\n", unikey); return unikey; } diff --git a/obt/keyboard.h b/obt/keyboard.h index ae9f9971..431e8142 100644 --- a/obt/keyboard.h +++ b/obt/keyboard.h @@ -64,9 +64,6 @@ KeyCode* obt_keyboard_keysym_to_keycode(KeySym sym); */ 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 KeyPressEvent to the unicode character it represents */ gunichar obt_keyboard_keypress_to_unichar(XKeyPressedEvent *ev); diff --git a/openbox/event.c b/openbox/event.c index aed50144..5ed8956e 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -264,28 +264,19 @@ static void event_set_curtime(XEvent *e) static void event_hack_mods(XEvent *e) { -#ifdef XKB - XkbStateRec xkb_state; -#endif - switch (e->type) { case ButtonPress: case ButtonRelease: e->xbutton.state = obt_keyboard_only_modmasks(e->xbutton.state); break; case KeyPress: - e->xkey.state = obt_keyboard_only_modmasks(e->xkey.state); + //e->xkey.state = obt_keyboard_only_modmasks(e->xkey.state); break; case KeyRelease: -#ifdef XKB - /* keep only the keyboard modifiers. xkb includes other things here. - (see XKBProto.pdf document: section 2.2.2) */ - e->xkey.state &= 0xf; -#endif - e->xkey.state = obt_keyboard_only_modmasks(e->xkey.state); + //e->xkey.state = obt_keyboard_only_modmasks(e->xkey.state); /* remove from the state the mask of the modifier key being released, if it is a modifier key being released that is */ - e->xkey.state &= ~obt_keyboard_keycode_to_modmask(e->xkey.keycode); + //e->xkey.state &= ~obt_keyboard_keycode_to_modmask(e->xkey.keycode); break; case MotionNotify: e->xmotion.state = obt_keyboard_only_modmasks(e->xmotion.state); @@ -1821,152 +1812,153 @@ static gboolean event_handle_menu_input(XEvent *ev) f->child == e->frame) menu_frame_select(e->frame, e, FALSE); } - else if (ev->type == KeyPress) { + /* Allow control while going thru the menu */ + else if (ev->type == KeyPress && (state & ~ControlMask) == 0) { guint keycode, state; static gunichar unikey; ObMenuFrame *frame; keycode = ev->xkey.keycode; - state = ev->xkey.state; + state = obt_keyboard_only_modmasks(ev->xkey.state); frame = find_active_or_last_menu(); if (frame == NULL) g_assert_not_reached(); /* there is no active menu */ - /* Allow control while going thru the menu */ - else if (ev->type == KeyPress && (state & ~ControlMask) == 0) { - frame->got_press = TRUE; + frame->got_press = TRUE; - if (ob_keycode_match(keycode, OB_KEY_ESCAPE)) { - menu_frame_hide_all(); - ret = TRUE; - } + if (ob_keycode_match(keycode, OB_KEY_ESCAPE)) { + menu_frame_hide_all(); + ret = TRUE; + } - else if (ob_keycode_match(keycode, OB_KEY_LEFT)) { - /* Left goes to the parent menu */ - if (frame->parent) { - /* remove focus from the child */ - menu_frame_select(frame, NULL, TRUE); - /* and put it in the parent */ - menu_frame_select(frame->parent, frame->parent->selected, - TRUE); - } - ret = TRUE; + else if (ob_keycode_match(keycode, OB_KEY_LEFT)) { + /* Left goes to the parent menu */ + if (frame->parent) { + /* remove focus from the child */ + menu_frame_select(frame, NULL, TRUE); + /* and put it in the parent */ + menu_frame_select(frame->parent, frame->parent->selected, + TRUE); } + ret = TRUE; + } - else if (ob_keycode_match(keycode, OB_KEY_RIGHT)) { - /* Right goes to the selected submenu */ - if (frame->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) - { - /* make sure it is visible */ - menu_frame_select(frame, frame->selected, TRUE); - menu_frame_select_next(frame->child); - } - ret = TRUE; + else if (ob_keycode_match(keycode, OB_KEY_RIGHT)) { + /* Right goes to the selected submenu */ + if (frame->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) + { + /* make sure it is visible */ + menu_frame_select(frame, frame->selected, TRUE); + menu_frame_select_next(frame->child); } + ret = TRUE; + } - else if (ob_keycode_match(keycode, OB_KEY_UP)) { - menu_frame_select_previous(frame); - ret = TRUE; - } + else if (ob_keycode_match(keycode, OB_KEY_UP)) { + menu_frame_select_previous(frame); + ret = TRUE; + } - else if (ob_keycode_match(keycode, OB_KEY_DOWN)) { - menu_frame_select_next(frame); - ret = TRUE; - } + else if (ob_keycode_match(keycode, OB_KEY_DOWN)) { + menu_frame_select_next(frame); + ret = TRUE; + } - else if (ob_keycode_match(keycode, OB_KEY_HOME)) { - menu_frame_select_first(frame); - ret = TRUE; - } + else if (ob_keycode_match(keycode, OB_KEY_HOME)) { + menu_frame_select_first(frame); + ret = TRUE; + } - else if (ob_keycode_match(keycode, OB_KEY_END)) { - menu_frame_select_last(frame); - ret = TRUE; - } + else if (ob_keycode_match(keycode, OB_KEY_END)) { + menu_frame_select_last(frame); + ret = TRUE; + } - /* Remember the last keypress */ - else { - unikey = obt_keyboard_keypress_to_unichar(&ev->xkey); - ret = !!unikey; - } + /* 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 - doesn't get sent to the focused application. + /* Use KeyRelease events for running things so that the key release + doesn't get sent to the focused application. - Allow ControlMask only, and don't bother if the menu is empty */ - else if (ev->type == KeyRelease && (state & ~ControlMask) == 0 && - frame->entries && frame->got_press) - { - if (ob_keycode_match(keycode, OB_KEY_RETURN)) { - /* Enter runs the active item or goes into the submenu. - Control-Enter runs it without closing the menu. */ - if (frame->child) - menu_frame_select_next(frame->child); - else if (frame->selected) - menu_entry_frame_execute(frame->selected, state); + Allow ControlMask only, and don't bother if the menu is empty */ + else if (ev->type == KeyRelease && (state & ~ControlMask) == 0 && + frame->entries && frame->got_press) + { + g_print("release unikey %lu\n", unikey); - ret = TRUE; - } + if (ob_keycode_match(keycode, OB_KEY_RETURN)) { + /* Enter runs the active item or goes into the submenu. + Control-Enter runs it without closing the menu. */ + if (frame->child) + menu_frame_select_next(frame->child); + else if (frame->selected) + menu_entry_frame_execute(frame->selected, state); - /* keyboard accelerator shortcuts. (if it was a valid key) */ - else if (unikey != 0) { - GList *start; - GList *it; - ObMenuEntryFrame *found = NULL; - guint num_found = 0; - - /* start after the selected one */ - start = frame->entries; - if (frame->selected) { - for (it = start; frame->selected != it->data; - it = g_list_next(it)) - g_assert(it != NULL); /* nothing was selected? */ - /* next with wraparound */ - start = g_list_next(it); - if (start == NULL) start = frame->entries; - } + ret = TRUE; + } - it = start; - do { - ObMenuEntryFrame *e = it->data; - gunichar entrykey = 0; + /* keyboard accelerator shortcuts. (if it was a valid key) */ + else if (unikey != 0) { + GList *start; + GList *it; + ObMenuEntryFrame *found = NULL; + guint num_found = 0; + + /* start after the selected one */ + start = frame->entries; + if (frame->selected) { + for (it = start; frame->selected != it->data; + it = g_list_next(it)) + g_assert(it != NULL); /* nothing was selected? */ + /* next with wraparound */ + start = g_list_next(it); + if (start == NULL) start = frame->entries; + } - if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) - entrykey = e->entry->data.normal.shortcut; - else if (e->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) - entrykey = e->entry->data.submenu.submenu->shortcut; + it = start; + do { + ObMenuEntryFrame *e = it->data; + gunichar entrykey = 0; - if (unikey == entrykey) { - if (found == NULL) found = e; - ++num_found; - } + if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) + entrykey = e->entry->data.normal.shortcut; + else if (e->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) + entrykey = e->entry->data.submenu.submenu->shortcut; - /* next with wraparound */ - it = g_list_next(it); - if (it == NULL) it = frame->entries; - } while (it != start); + if (unikey == entrykey) { + if (found == NULL) found = e; + ++num_found; + } - if (found) { - if (found->entry->type == OB_MENU_ENTRY_TYPE_NORMAL && - num_found == 1) - { - menu_frame_select(frame, found, TRUE); - usleep(50000); /* highlight the item for a short bit so - the user can see what happened */ - menu_entry_frame_execute(found, state); - } else { - menu_frame_select(frame, found, TRUE); - if (num_found == 1) - menu_frame_select_next(frame->child); - } + /* next with wraparound */ + it = g_list_next(it); + if (it == NULL) it = frame->entries; + } while (it != start); - ret = TRUE; + if (found) { + if (found->entry->type == OB_MENU_ENTRY_TYPE_NORMAL && + num_found == 1) + { + menu_frame_select(frame, found, TRUE); + usleep(50000); /* highlight the item for a short bit so + the user can see what happened */ + menu_entry_frame_execute(found, state); + } else { + menu_frame_select(frame, found, TRUE); + if (num_found == 1) + menu_frame_select_next(frame->child); } + + ret = TRUE; } } } +} return ret; } diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 5ee55b1c..e850f2d8 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -952,7 +952,6 @@ static gboolean menu_frame_show(ObMenuFrame *self) if (menu_frame_visible == NULL) { /* no menus shown yet */ - /* grab the pointer in such a way as to pass through "owner events" so that we can get enter/leave notifies in the menu. */ if (!grab_pointer(TRUE, FALSE, OB_CURSOR_POINTER)) @@ -961,7 +960,6 @@ static gboolean menu_frame_show(ObMenuFrame *self) ungrab_pointer(); return FALSE; } - obt_keyboard_set_input_context(obt_root(ob_screen)); } @@ -1086,7 +1084,6 @@ 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(); }