static void event_handle_dock(ObDock *s, XEvent *e);
static void event_handle_dockapp(ObDockApp *app, XEvent *e);
static void event_handle_client(ObClient *c, XEvent *e);
-static void event_handle_user_input(ObClient *client, XEvent *e);
+static gboolean event_handle_user_input(ObClient *client, XEvent *e);
static gboolean is_enter_focus_event_ignored(gulong serial);
static void event_ignore_enter_range(gulong start, gulong end);
ObWindow *obwin = NULL;
ObMenuFrame *menu = NULL;
ObPrompt *prompt = NULL;
+ gboolean used;
/* make a copy we can mangle */
ee = *ec;
}
#endif
- if (prompt && event_handle_prompt(prompt, e))
- ;
- else if (e->type == ButtonPress || e->type == ButtonRelease) {
+ if (e->type == ButtonPress || e->type == ButtonRelease) {
/* If the button press was on some non-root window, or was physically
on the root window, then process it */
if (window != obt_root(ob_screen) ||
e->xbutton.subwindow == None)
{
- event_handle_user_input(client, e);
+ used = event_handle_user_input(client, e);
}
/* Otherwise only process it if it was physically on an openbox
internal window */
if ((w = window_find(e->xbutton.subwindow)) &&
WINDOW_IS_INTERNAL(w))
{
- event_handle_user_input(client, e);
+ used = event_handle_user_input(client, e);
}
}
}
else if (e->type == KeyPress || e->type == KeyRelease ||
e->type == MotionNotify)
- event_handle_user_input(client, e);
+ used = event_handle_user_input(client, e);
+
+ if (prompt && !used)
+ used = event_handle_prompt(prompt, e);
/* if something happens and it's not from an XEvent, then we don't know
the time */
else if (ob_keycode_match(keycode, OB_KEY_LEFT)) {
/* Left goes to the parent menu */
- if (frame->parent)
+ 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->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;
}
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_END)) {
+ menu_frame_select_last(frame);
+ ret = TRUE;
+ }
}
/* Use KeyRelease events for running things so that the key release
return ret;
}
+static Bool event_look_for_menu_enter(Display *d, XEvent *ev, XPointer arg)
+{
+ ObMenuFrame *f = (ObMenuFrame*)arg;
+ ObMenuEntryFrame *e;
+ return ev->type == EnterNotify &&
+ (e = g_hash_table_lookup(menu_frame_map, &ev->xcrossing.window)) &&
+ !e->ignore_enters && e->frame == f;
+}
+
static void event_handle_menu(ObMenuFrame *frame, XEvent *ev)
{
ObMenuFrame *f;
if (ev->xcrossing.detail == NotifyInferior)
break;
- if ((e = g_hash_table_lookup(menu_frame_map, &ev->xcrossing.window)) &&
- (f = find_active_menu()) && f->selected == e &&
- e->entry->type != OB_MENU_ENTRY_TYPE_SUBMENU)
+ if ((e = g_hash_table_lookup(menu_frame_map, &ev->xcrossing.window)))
{
- ObMenuEntryFrame *u = menu_entry_frame_under(ev->xcrossing.x_root,
- ev->xcrossing.y_root);
- /* if we're just going from one entry in the menu to the next,
- don't unselect stuff first */
- if (!u || e->frame != u->frame)
+ XEvent ce;
+
+ /* check if an EnterNotify event is coming, and if not, then select
+ nothing in the menu */
+ if (XCheckIfEvent(obt_display, &ce, event_look_for_menu_enter,
+ (XPointer)e->frame))
+ XPutBackEvent(obt_display, &ce);
+ else
menu_frame_select(e->frame, NULL, FALSE);
}
break;
}
}
-static void event_handle_user_input(ObClient *client, XEvent *e)
+static gboolean event_handle_user_input(ObClient *client, XEvent *e)
{
g_assert(e->type == ButtonPress || e->type == ButtonRelease ||
e->type == MotionNotify || e->type == KeyPress ||
/* don't use the event if the menu used it, but if the menu
didn't use it and it's a keypress that is bound, it will
close the menu and be used */
- return;
+ return TRUE;
}
/* if the keyboard interactive action uses the event then dont
use it for bindings. likewise is moveresize uses the event. */
- if (!actions_interactive_input_event(e) && !moveresize_event(e)) {
- if (moveresize_in_progress)
- /* make further actions work on the client being
- moved/resized */
- client = moveresize_client;
-
- if (e->type == ButtonPress ||
- e->type == ButtonRelease ||
- e->type == MotionNotify)
- {
- /* the frame may not be "visible" but they can still click on it
- in the case where it is animating before disappearing */
- if (!client || !frame_iconify_animating(client->frame))
- mouse_event(client, e);
- } else
- keyboard_event((focus_cycle_target ? focus_cycle_target :
- (client ? client : focus_client)), e);
- }
+ if (actions_interactive_input_event(e) || moveresize_event(e))
+ return TRUE;
+
+ if (moveresize_in_progress)
+ /* make further actions work on the client being
+ moved/resized */
+ client = moveresize_client;
+
+ if (e->type == ButtonPress ||
+ e->type == ButtonRelease ||
+ e->type == MotionNotify)
+ {
+ /* the frame may not be "visible" but they can still click on it
+ in the case where it is animating before disappearing */
+ if (!client || !frame_iconify_animating(client->frame))
+ return mouse_event(client, e);
+ } else
+ return keyboard_event((focus_cycle_target ? focus_cycle_target :
+ (client ? client : focus_client)), e);
+
+ return FALSE;
}
static void focus_delay_dest(gpointer data)