From ab78ee418524597b198dcac2619107fed250985e Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Thu, 11 Feb 2010 09:46:16 -0500 Subject: [PATCH] don't strip the xkey event states, and make the menus work with non-US stuff. xkb needs to read the state in the event to translate it into a character properly. menus have to respond to keypress events to work with non-US keyboard stuff, so make that happen but still exec stuff on keyrelease --- openbox/actions/cyclewindows.c | 11 +- openbox/actions/desktop.c | 13 +- openbox/actions/directionalwindows.c | 11 +- openbox/actions/execute.c | 7 - openbox/event.c | 234 +++++++++++++-------------- openbox/keyboard.c | 20 ++- openbox/menuframe.c | 3 +- openbox/moveresize.c | 6 +- openbox/prompt.c | 7 +- 9 files changed, 171 insertions(+), 141 deletions(-) diff --git a/openbox/actions/cyclewindows.c b/openbox/actions/cyclewindows.c index d1112242..cad08700 100644 --- a/openbox/actions/cyclewindows.c +++ b/openbox/actions/cyclewindows.c @@ -5,6 +5,7 @@ #include "openbox/focus_cycle.h" #include "openbox/openbox.h" #include "gettext.h" +#include "obt/keyboard.h" typedef struct { gboolean linear; @@ -172,6 +173,14 @@ static gboolean i_input_func(guint initial_state, gboolean *used) { Options *o = options; + guint mods; + + mods = obt_keyboard_only_modmasks(e->xkey.state); + if (e->type == KeyRelease) { + /* remove from the state the mask of the modifier key being + released, if it is a modifier key being released that is */ + mods &= ~obt_keyboard_keycode_to_modmask(e->xkey.keycode); + } if (e->type == KeyPress) { /* Escape cancels no matter what */ @@ -192,7 +201,7 @@ static gboolean i_input_func(guint initial_state, } /* They released the modifiers */ else if (e->type == KeyRelease && initial_state && - (e->xkey.state & initial_state) == 0) + (mods & initial_state) == 0) { o->cancel = FALSE; o->state = e->xkey.state; diff --git a/openbox/actions/desktop.c b/openbox/actions/desktop.c index 5b0282cc..e794bf8b 100644 --- a/openbox/actions/desktop.c +++ b/openbox/actions/desktop.c @@ -2,7 +2,7 @@ #include "openbox/screen.h" #include "openbox/client.h" #include "openbox/openbox.h" -#include +#include "obt/keyboard.h" typedef enum { LAST, @@ -300,6 +300,15 @@ static gboolean i_input_func(guint initial_state, gpointer options, gboolean *used) { + guint mods; + + mods = obt_keyboard_only_modmasks(e->xkey.state); + if (e->type == KeyRelease) { + /* remove from the state the mask of the modifier key being + released, if it is a modifier key being released that is */ + mods &= ~obt_keyboard_keycode_to_modmask(e->xkey.keycode); + } + if (e->type == KeyPress) { /* Escape cancels no matter what */ if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) { @@ -315,7 +324,7 @@ static gboolean i_input_func(guint initial_state, } /* They released the modifiers */ else if (e->type == KeyRelease && initial_state && - (e->xkey.state & initial_state) == 0) + (mods & initial_state) == 0) { return FALSE; } diff --git a/openbox/actions/directionalwindows.c b/openbox/actions/directionalwindows.c index 2cca450c..bf735209 100644 --- a/openbox/actions/directionalwindows.c +++ b/openbox/actions/directionalwindows.c @@ -256,6 +256,15 @@ static gboolean i_input_func(guint initial_state, gpointer options, gboolean *used) { + guint mods; + + mods = obt_keyboard_only_modmasks(e->xkey.state); + if (e->type == KeyRelease) { + /* remove from the state the mask of the modifier key being + released, if it is a modifier key being released that is */ + mods &= ~obt_keyboard_keycode_to_modmask(e->xkey.keycode); + } + if (e->type == KeyPress) { /* Escape cancels no matter what */ if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) { @@ -273,7 +282,7 @@ static gboolean i_input_func(guint initial_state, } /* They released the modifiers */ else if (e->type == KeyRelease && initial_state && - (e->xkey.state & initial_state) == 0) + (mods & initial_state) == 0) { end_cycle(FALSE, e->xkey.state, options); return FALSE; diff --git a/openbox/actions/execute.c b/openbox/actions/execute.c index 0e9e7387..618153b0 100644 --- a/openbox/actions/execute.c +++ b/openbox/actions/execute.c @@ -23,13 +23,6 @@ typedef struct { static gpointer setup_func(xmlNodePtr node); static void free_func(gpointer options); static gboolean run_func(ObActionsData *data, gpointer options); -/* -static gboolean i_input_func(guint initial_state, - XEvent *e, - gpointer options, - gboolean *used); -static void i_cancel_func(gpointer options); -*/ void action_execute_startup(void) { diff --git a/openbox/event.c b/openbox/event.c index 5ed8956e..04d682a2 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -270,13 +270,8 @@ static void event_hack_mods(XEvent *e) e->xbutton.state = obt_keyboard_only_modmasks(e->xbutton.state); break; case KeyPress: - //e->xkey.state = obt_keyboard_only_modmasks(e->xkey.state); break; case KeyRelease: - //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); break; case MotionNotify: e->xmotion.state = obt_keyboard_only_modmasks(e->xmotion.state); @@ -1812,153 +1807,152 @@ static gboolean event_handle_menu_input(XEvent *ev) f->child == e->frame) menu_frame_select(e->frame, e, FALSE); } - /* Allow control while going thru the menu */ - else if (ev->type == KeyPress && (state & ~ControlMask) == 0) { - guint keycode, state; - static gunichar unikey; + else { + static guint keycode; + static gboolean doexec; ObMenuFrame *frame; + guint mods; + gunichar unikey; - keycode = ev->xkey.keycode; - state = obt_keyboard_only_modmasks(ev->xkey.state); + g_assert(ev->type == KeyPress || ev->type == KeyRelease); + + /* get the modifiers */ + mods = 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 */ - frame->got_press = TRUE; + /* Allow control while going thru the menu */ + else if (ev->type == KeyPress && (mods & ~ControlMask) == 0) { + /* remember the last pressed key */ + keycode = ev->xkey.keycode; + doexec = FALSE; - if (ob_keycode_match(keycode, OB_KEY_ESCAPE)) { - menu_frame_hide_all(); - ret = TRUE; - } + frame->got_press = 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); + if (ob_keycode_match(ev->xkey.keycode, OB_KEY_ESCAPE)) { + menu_frame_hide_all(); + ret = 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); + else if (ob_keycode_match(ev->xkey.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; } - 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(ev->xkey.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_HOME)) { - menu_frame_select_first(frame); - ret = TRUE; - } + else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_UP)) { + menu_frame_select_previous(frame); + ret = TRUE; + } - else if (ob_keycode_match(keycode, OB_KEY_END)) { - menu_frame_select_last(frame); - ret = TRUE; - } + else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_DOWN)) { + menu_frame_select_next(frame); + ret = TRUE; + } - /* Remember the last keypress */ - else { - unikey = obt_keyboard_keypress_to_unichar(&ev->xkey); - ret = !!unikey; - } - } + else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_HOME)) { + menu_frame_select_first(frame); + ret = TRUE; + } - /* Use KeyRelease events for running things so that the key release - doesn't get sent to the focused application. + else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_END)) { + menu_frame_select_last(frame); + ret = TRUE; + } - 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); + /* keyboard accelerator shortcuts. (if it was a valid key) */ + else if ((unikey = obt_keyboard_keypress_to_unichar(&ev->xkey))) { + 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 (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); + it = start; + do { + ObMenuEntryFrame *e = it->data; + gunichar entrykey = 0; - ret = TRUE; - } + 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; - /* 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 (unikey == entrykey) { + if (found == NULL) found = e; + ++num_found; + } - it = start; - do { - ObMenuEntryFrame *e = it->data; - gunichar entrykey = 0; + /* next with wraparound */ + it = g_list_next(it); + if (it == NULL) it = frame->entries; + } while (it != start); - 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; + if (found) { + menu_frame_select(frame, found, TRUE); + /* execute this when the key is released */ + doexec = num_found == 1; - if (unikey == entrykey) { - if (found == NULL) found = e; - ++num_found; + ret = TRUE; } + } + } - /* next with wraparound */ - it = g_list_next(it); - if (it == NULL) it = frame->entries; - } while (it != start); + /* Use KeyRelease events for running things so that the key release + doesn't get sent to the focused application. - 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); - } + Allow ControlMask only, and don't bother if the menu is empty */ + else if (ev->type == KeyRelease && (mods & ~ControlMask) == 0 && + frame->entries && frame->got_press) + { + if (ob_keycode_match(ev->xkey.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, ev->xkey.state); ret = TRUE; } + + if (doexec && keycode == ev->xkey.keycode) { + if (frame->selected->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) + menu_entry_frame_execute(frame->selected, ev->xkey.state); + else + menu_frame_select_next(frame->child); + } } } -} return ret; } diff --git a/openbox/keyboard.c b/openbox/keyboard.c index 5f7531e3..e2b72b36 100644 --- a/openbox/keyboard.c +++ b/openbox/keyboard.c @@ -33,6 +33,7 @@ #include "moveresize.h" #include "popup.h" #include "gettext.h" +#include "obt/keyboard.h" #include @@ -175,9 +176,17 @@ gboolean keyboard_process_interactive_grab(const XEvent *e, ObClient **client) gboolean handled = FALSE; gboolean done = FALSE; gboolean cancel = FALSE; + guint state; + + state = obt_keyboard_only_modmasks(ev->xkey.state); + if (e->type == KeyRelease) { + /* remove from the state the mask of the modifier key being + released, if it is a modifier key being released that is */ + state &= ~obt_keyboard_keycode_to_modmask(e->xkey.keycode); + } if (istate.active) { - if ((e->type == KeyRelease && !(istate.state & e->xkey.state))) { + if ((e->type == KeyRelease && !(istate.state & state))) { done = TRUE; handled = TRUE; } else if (e->type == KeyPress) { @@ -194,7 +203,7 @@ gboolean keyboard_process_interactive_grab(const XEvent *e, ObClient **client) } if (done) - keyboard_interactive_end(e->xkey.state, cancel, e->xkey.time,TRUE); + keyboard_interactive_end(state, cancel, e->xkey.time,TRUE); if (handled) *client = istate.client; @@ -208,6 +217,7 @@ gboolean keyboard_event(ObClient *client, const XEvent *e) { KeyBindingTree *p; gboolean used; + guint state; if (e->type == KeyRelease) { grab_key_passive_count(-1); @@ -217,8 +227,10 @@ gboolean keyboard_event(ObClient *client, const XEvent *e) g_assert(e->type == KeyPress); grab_key_passive_count(1); + state = obt_keyboard_only_modmasks(e->xkey.state); + if (e->xkey.keycode == config_keyboard_reset_keycode && - e->xkey.state == config_keyboard_reset_state) + state == config_keyboard_reset_state) { obt_main_loop_timeout_remove(ob_main_loop, chain_timeout); keyboard_reset_chains(-1); @@ -232,7 +244,7 @@ gboolean keyboard_event(ObClient *client, const XEvent *e) p = curpos->first_child; while (p) { if (p->key == e->xkey.keycode && - p->state == e->xkey.state) + p->state == state) { /* if we hit a key binding, then close any open menus and run it */ if (menu_frame_visible) diff --git a/openbox/menuframe.c b/openbox/menuframe.c index e850f2d8..f8978b17 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -1264,9 +1264,10 @@ void menu_entry_frame_execute(ObMenuEntryFrame *self, guint state) GSList *acts = self->entry->data.normal.actions; ObClient *client = self->frame->client; ObMenuFrame *frame = self->frame; + guint mods = obt_keyboard_only_modmasks(state); /* release grabs before executing the shit */ - if (!(state & ControlMask)) { + if (!(mods & ControlMask)) { event_cancel_all_key_grabs(); frame = NULL; } diff --git a/openbox/moveresize.c b/openbox/moveresize.c index ec9cb103..e125bbcd 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -923,13 +923,15 @@ gboolean moveresize_event(XEvent *e) ob_keycode_match(e->xkey.keycode, OB_KEY_DOWN) || ob_keycode_match(e->xkey.keycode, OB_KEY_UP)) { + guint state = obt_keyboard_only_modmasks(e->xkey.state); + if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD)) { - resize_with_keys(e->xkey.keycode, e->xkey.state); + resize_with_keys(e->xkey.keycode, state); used = TRUE; } else if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD)) { - move_with_keys(e->xkey.keycode, e->xkey.state); + move_with_keys(e->xkey.keycode, state); used = TRUE; } } diff --git a/openbox/prompt.c b/openbox/prompt.c index 4f8930d7..1bf84c80 100644 --- a/openbox/prompt.c +++ b/openbox/prompt.c @@ -520,15 +520,16 @@ void prompt_hide(ObPrompt *self) gboolean prompt_key_event(ObPrompt *self, XEvent *e) { gboolean shift; - guint shift_mask; + guint shift_mask, state; if (e->type != KeyPress) return FALSE; shift_mask = obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT); - shift = !!(e->xkey.state & shift_mask); + state = obt_keyboard_only_modmasks(e->xkey.state); + shift = !!(state & shift_mask); /* only accept shift */ - if (e->xkey.state != 0 && e->xkey.state != shift_mask) + if (state != 0 && state != shift_mask) return FALSE; if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) -- 2.39.2