+ ret = TRUE;
+ }
+ else if (ev->type == MotionNotify) {
+ ObMenuFrame *f;
+ ObMenuEntryFrame *e;
+
+ if ((e = menu_entry_frame_under(ev->xmotion.x_root,
+ ev->xmotion.y_root)))
+ if (!(f = find_active_menu()) ||
+ f == e->frame ||
+ f->parent == e->frame ||
+ f->child == e->frame)
+ menu_frame_select(e->frame, e, FALSE);
+ }
+ else if (ev->type == KeyPress || ev->type == KeyRelease) {
+ guint mods;
+ ObMenuFrame *frame;
+
+ /* 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 && (mods & ~ControlMask) == 0) {
+ gunichar unikey;
+ KeySym sym;
+
+ frame->got_press = TRUE;
+ frame->press_keycode = ev->xkey.keycode;
+ frame->press_doexec = FALSE;
+
+ sym = obt_keyboard_keypress_to_keysym(ev);
+
+ if (sym == XK_Escape) {
+ menu_frame_hide_all();
+ ret = TRUE;
+ }
+
+ else if (sym == XK_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 (sym == XK_Right) {
+ /* Right goes to the selected submenu */
+ if (frame->selected &&
+ 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 (sym == XK_Up) {
+ menu_frame_select_previous(frame);
+ ret = TRUE;
+ }
+
+ else if (sym == XK_Down) {
+ menu_frame_select_next(frame);
+ ret = TRUE;
+ }
+
+ else if (sym == XK_Home) {
+ menu_frame_select_first(frame);
+ ret = TRUE;
+ }
+
+ else if (sym == XK_End) {
+ menu_frame_select_last(frame);
+ ret = TRUE;
+ }
+
+ else if (sym == XK_Return || sym == XK_KP_Enter) {
+ frame->press_doexec = TRUE;
+ ret = TRUE;
+ }
+
+ /* keyboard accelerator shortcuts. (if it was a valid key) */
+ else if (frame->entries &&
+ (unikey =
+ obt_keyboard_keypress_to_unichar(menu_frame_ic(frame),
+ ev)))
+ {
+ 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;
+ }
+
+ it = start;
+ do {
+ ObMenuEntryFrame *e = it->data;
+ gunichar entrykey = 0;
+
+ 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 (unikey == entrykey) {
+ if (found == NULL) found = e;
+ ++num_found;
+ }
+
+ /* next with wraparound */
+ it = g_list_next(it);
+ if (it == NULL) it = frame->entries;
+ } while (it != start);
+
+ if (found) {
+ 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) {
+ if (frame->press_keycode == ev->xkey.keycode &&
+ frame->got_press &&
+ frame->press_doexec)
+ {
+ if (frame->child)
+ menu_frame_select_next(frame->child);
+ else if (frame->selected)
+ menu_entry_frame_execute(frame->selected, ev->xkey.state);
+ }
+ }
+ }
+
+ return ret;
+}
+
+static gboolean event_look_for_menu_enter(XEvent *ev, gpointer data)
+{
+ const ObMenuFrame *f = (ObMenuFrame*)data;
+ ObMenuEntryFrame *e;
+ return ev->type == EnterNotify &&
+ (e = g_hash_table_lookup(menu_frame_map, &ev->xcrossing.window)) &&
+ e->frame == f && !e->ignore_enters;
+}
+
+static void event_handle_menu(ObMenuFrame *frame, XEvent *ev)
+{
+ ObMenuFrame *f;
+ ObMenuEntryFrame *e;
+
+ switch (ev->type) {