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)
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;
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;
}
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);
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;
}