the key translation stuff works but the menu event code is a bit of a train wreck.
authorDana Jansens <danakj@orodu.net>
Wed, 10 Feb 2010 22:13:28 +0000 (17:13 -0500)
committerDana Jansens <danakj@orodu.net>
Wed, 10 Feb 2010 22:13:28 +0000 (17:13 -0500)
obt/keyboard.c
obt/keyboard.h
openbox/event.c
openbox/menuframe.c

index 738888ef10d7d68da2d34df0134cb1c2097b934b..0ca93c0e724c725c08f98e9de478c173c91398c9 100644 (file)
@@ -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;
 }
index ae9f997128ddd8236123a9d8d8f60dc6c15502ec..431e81427be1b0733c90ef5719c3c93ca5f6b48e 100644 (file)
@@ -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);
 
index aed501443f654abb6160ac3759467358fc7b7d94..5ed8956e936b6f626e79fbc7950e4b9b5344e754 100644 (file)
@@ -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;
 }
index 5ee55b1cb893d7aa5ea5add6d3142e902c7c62c2..e850f2d8f7a121f2fcc5f7a35865b2c14d081681 100644 (file)
@@ -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();
     }