X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fevent.c;h=f813d3f5cb2a45c9ad2672690b17698cf32a5520;hb=62f8a5c49b852047bf6cc199d2d0c9add41d35a9;hp=e279c9db9918246b9eaf96ea30528122af7cb4ca;hpb=3368b91d544ab8c6510d88e5ad58d070fad62baa;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index e279c9db..f813d3f5 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -56,9 +56,6 @@ #ifdef HAVE_UNISTD_H # include /* for usleep() */ #endif -#ifdef XKB -# include -#endif #ifdef USE_SM #include @@ -260,34 +257,14 @@ 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); break; case KeyRelease: -#ifdef XKB - /* If XKB is present, then the modifiers are all strange from its - magic. Our X core protocol stuff won't work, so we use this to - find what the modifier state is instead. */ - if (XkbGetState(obt_display, XkbUseCoreKbd, &xkb_state) == Success) - e->xkey.state = - obt_keyboard_only_modmasks(xkb_state.compat_state); - else -#endif - { - 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); @@ -661,6 +638,7 @@ static void event_process(const XEvent *ec, gpointer data) modifier map, and rebind all the key bindings as appropriate */ ob_debug("Keyboard map changed. Reloading keyboard bindings."); ob_set_state(OB_STATE_RECONFIGURING); + XRefreshKeyboardMapping(&e->xmapping); obt_keyboard_reload(); keyboard_rebind(); ob_set_state(OB_STATE_RUNNING); @@ -719,22 +697,27 @@ static void event_process(const XEvent *ec, gpointer data) #endif if (e->type == ButtonPress || e->type == ButtonRelease) { + ObWindow *w; + static guint pressed = 0; + static Window pressed_win = None; + /* If the button press was on some non-root window, or was physically - on the root window, then process it */ + on the root window... */ if (window != obt_root(ob_screen) || - e->xbutton.subwindow == None) + e->xbutton.subwindow == None || + /* ...or if it is related to the last button press we handled... */ + pressed == e->xbutton.button || + /* ...or it if it was physically on an openbox + internal window... */ + ((w = window_find(e->xbutton.subwindow)) && + WINDOW_IS_INTERNAL(w))) + /* ...then process the event, otherwise ignore it */ { used = event_handle_user_input(client, e); - } - /* Otherwise only process it if it was physically on an openbox - internal window */ - else { - ObWindow *w; - if ((w = window_find(e->xbutton.subwindow)) && - WINDOW_IS_INTERNAL(w)) - { - used = event_handle_user_input(client, e); + if (e->type == ButtonPress) { + pressed = e->xbutton.button; + pressed_win = e->xbutton.subwindow; } } } @@ -1781,28 +1764,30 @@ static gboolean event_handle_menu_input(XEvent *ev) menu_frame_select(e->frame, e, FALSE); } else if (ev->type == KeyPress || ev->type == KeyRelease) { - guint keycode, state; - gunichar unikey; + guint mods; ObMenuFrame *frame; - keycode = ev->xkey.keycode; - state = ev->xkey.state; - unikey = obt_keyboard_keycode_to_unichar(keycode); + /* 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 */ /* Allow control while going thru the menu */ - else if (ev->type == KeyPress && (state & ~ControlMask) == 0) { + else if (ev->type == KeyPress && (mods & ~ControlMask) == 0) { + gunichar unikey; + frame->got_press = TRUE; + frame->press_keycode = ev->xkey.keycode; + frame->press_doexec = FALSE; - if (ob_keycode_match(keycode, OB_KEY_ESCAPE)) { + if (ob_keycode_match(ev->xkey.keycode, OB_KEY_ESCAPE)) { menu_frame_hide_all(); ret = TRUE; } - else if (ob_keycode_match(keycode, OB_KEY_LEFT)) { + 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 */ @@ -1814,43 +1799,39 @@ static gboolean event_handle_menu_input(XEvent *ev) ret = TRUE; } - else if (ob_keycode_match(keycode, OB_KEY_RIGHT)) { + else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_RIGHT)) { /* Right goes to the selected submenu */ - if (frame->child) menu_frame_select_next(frame->child); + 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)) { + 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_DOWN)) { + else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_DOWN)) { menu_frame_select_next(frame); ret = TRUE; } - } - - /* 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); + else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_HOME)) { + menu_frame_select_first(frame); + ret = TRUE; + } + else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_END)) { + menu_frame_select_last(frame); ret = TRUE; } /* keyboard accelerator shortcuts. (if it was a valid key) */ - else if (unikey != 0) { + else if ((unikey = obt_keyboard_keypress_to_unichar(&ev->xkey))) { GList *start; GList *it; ObMenuEntryFrame *found = NULL; @@ -1888,23 +1869,42 @@ static gboolean event_handle_menu_input(XEvent *ev) } while (it != start); 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); - } + menu_frame_select(frame, found, TRUE); + if (num_found == 1) + frame->press_doexec = TRUE; ret = TRUE; } } } + + /* 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 && (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 (frame->press_keycode == ev->xkey.keycode && + frame->press_doexec) + { + 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;