X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fevent.c;h=bf2fd932cf1f68e2ab90888cb627743641560b73;hb=96fbc0c6229ff2f13a102da603339472c176bc0b;hp=383b260136ca6e80dfb1c94de7b21515ca2f4283;hpb=6d2650263193aaa7e94b29261c6ba249c0be3fd3;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index 383b2601..bf2fd932 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -38,6 +38,7 @@ #include "mainloop.h" #include "framerender.h" #include "focus.h" +#include "focus_cycle.h" #include "moveresize.h" #include "group.h" #include "stacking.h" @@ -97,11 +98,7 @@ static gboolean menu_hide_delay_func(gpointer data); /* The time for the current event being processed */ Time event_curtime = CurrentTime; -#define NUM_IGNORE_SERIALS 20 - static guint ignore_enter_focus = 0; -/*! This is a 0 terminated list of ignored serials */ -static gulong ignore_enter_serials[NUM_IGNORE_SERIALS+1] = {0}; static gboolean menu_can_hide; static gboolean focus_left_screen = FALSE; @@ -775,7 +772,8 @@ static void event_handle_client(ObClient *client, XEvent *e) { /* use where the press occured */ con = frame_context(client, e->xbutton.window, px, py); - con = mouse_button_frame_context(con, e->xbutton.button); + con = mouse_button_frame_context(con, e->xbutton.button, + e->xbutton.state); if (e->type == ButtonRelease && e->xbutton.button == pb) pb = 0, px = py = -1; @@ -888,7 +886,7 @@ static void event_handle_client(ObClient *client, XEvent *e) corresponding enter events. Pretend like the animating window doesn't even exist..! */ if (frame_iconify_animating(client->frame)) - event_ignore_enters_leaving_window(client); + event_ignore_all_queued_enters(); ob_debug_type(OB_DEBUG_FOCUS, "%sNotify mode %d detail %d on %lx\n", @@ -914,11 +912,6 @@ static void event_handle_client(ObClient *client, XEvent *e) break; case EnterNotify: { - gboolean nofocus = FALSE; - - if (is_enter_focus_event_ignored(e)) - nofocus = TRUE; - con = frame_context(client, e->xcrossing.window, e->xcrossing.x, e->xcrossing.y); switch (con) { @@ -948,22 +941,23 @@ static void event_handle_client(ObClient *client, XEvent *e) if (e->xcrossing.mode == NotifyGrab || e->xcrossing.mode == NotifyUngrab || /*ignore enters when we're already in the window */ - e->xcrossing.detail == NotifyInferior) + e->xcrossing.detail == NotifyInferior || + is_enter_focus_event_ignored(e)) { ob_debug_type(OB_DEBUG_FOCUS, "%sNotify mode %d detail %d on %lx IGNORED\n", (e->type == EnterNotify ? "Enter" : "Leave"), e->xcrossing.mode, e->xcrossing.detail, client?client->window:0); - } else { + } + else { ob_debug_type(OB_DEBUG_FOCUS, "%sNotify mode %d detail %d on %lx, " - "focusing window: %d\n", + "focusing window\n", (e->type == EnterNotify ? "Enter" : "Leave"), e->xcrossing.mode, - e->xcrossing.detail, (client?client->window:0), - !nofocus); - if (!nofocus && config_focus_follow) + e->xcrossing.detail, (client?client->window:0)); + if (config_focus_follow) event_enter_client(client); } break; @@ -1087,7 +1081,7 @@ static void event_handle_client(ObClient *client, XEvent *e) client_configure(client, x, y, w, h, FALSE, TRUE); /* ignore enter events caused by these like ob actions do */ - event_ignore_enters_leaving_window(client); + event_ignore_all_queued_enters(); } break; } @@ -1183,7 +1177,7 @@ static void event_handle_client(ObClient *client, XEvent *e) e->xclient.data.l[1], e->xclient.data.l[2]); /* ignore enter events caused by these like ob actions do */ - event_ignore_enters_leaving_window(client); + event_ignore_all_queued_enters(); } else if (msgtype == prop_atoms.net_close_window) { ob_debug("net_close_window for 0x%lx\n", client->window); client_close(client); @@ -1271,7 +1265,7 @@ static void event_handle_client(ObClient *client, XEvent *e) client_configure(client, x, y, w, h, FALSE, TRUE); /* ignore enter events caused by these like ob actions do */ - event_ignore_enters_leaving_window(client); + event_ignore_all_queued_enters(); } else if (msgtype == prop_atoms.net_restack_window) { if (e->xclient.data.l[0] != 2) { ob_debug_type(OB_DEBUG_APP_BUGS, @@ -1281,8 +1275,8 @@ static void event_handle_client(ObClient *client, XEvent *e) } else { ObClient *sibling = NULL; if (e->xclient.data.l[1]) { - ObWindow *win = g_hash_table_lookup(window_map, - &e->xclient.data.l[1]); + ObWindow *win = g_hash_table_lookup + (window_map, &e->xclient.data.l[1]); if (WINDOW_IS_CLIENT(win) && WINDOW_AS_CLIENT(win) != client) { @@ -1489,8 +1483,11 @@ static gboolean event_handle_menu_keyboard(XEvent *ev) ret = FALSE; else if (keycode == ob_keycode(OB_KEY_ESCAPE) && state == 0) { - /* Escape closes the active menu */ - menu_frame_hide(frame); + /* Escape goes to the parent menu or closes the last one */ + if (frame->parent) + menu_frame_select(frame, NULL, TRUE); + else + menu_frame_hide_all(); } else if (keycode == ob_keycode(OB_KEY_RETURN) && (state == 0 || @@ -1614,6 +1611,10 @@ static gboolean event_handle_menu(XEvent *ev) } break; case LeaveNotify: + /*ignore leaves when we're already in the window */ + 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) @@ -1720,87 +1721,48 @@ void event_halt_focus_delay() ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func); } -struct ObLookForEnters -{ - ObClient *c; - gulong looking_for_enter; -}; - static Bool event_look_for_enters(Display *d, XEvent *e, XPointer arg) { - struct ObLookForEnters *lfe = (struct ObLookForEnters*)arg; - - if (lfe->c != NULL && e->type == LeaveNotify) { - if (g_hash_table_lookup(window_map, &e->xany.window) == lfe->c) - /* found an event leaving this window */ - lfe->looking_for_enter = e->xany.serial; - } else if (e->type == EnterNotify && - (lfe->c == NULL || e->xany.serial == lfe->looking_for_enter)) + if (e->type == EnterNotify && + /* these types aren't used for focusing */ + !(e->xcrossing.mode == NotifyGrab || + e->xcrossing.mode == NotifyUngrab || + e->xcrossing.detail == NotifyInferior)) { ObWindow *win; - gint i; - gboolean ignored = FALSE; - - /* make sure the serial isn't already being ignored */ - for (i = 0; ignore_enter_serials[i] != 0 && !ignored; ++i) { - if (ignore_enter_serials[i] == e->xany.serial) - ignored = TRUE; - } - if (!ignored) { - /* found an enter for that leave, ignore it if it's going to - another window */ - win = g_hash_table_lookup(window_map, &e->xany.window); - if (win && WINDOW_IS_CLIENT(win)) - ++ignore_enter_focus; - } - - /* add it to the ignored list if there is room */ - if (i < NUM_IGNORE_SERIALS) { - ignore_enter_serials[i] = e->xany.serial; - ignore_enter_serials[i+1] = 0; - } + /* found an enter for that leave, ignore it if it's going to + another window */ + win = g_hash_table_lookup(window_map, &e->xany.window); + if (win && WINDOW_IS_CLIENT(win)) + ++ignore_enter_focus; } return False; /* don't disrupt the queue order, just count them */ } void event_ignore_all_queued_enters() { - event_ignore_enters_leaving_window(NULL); -} - -void event_ignore_enters_leaving_window(ObClient *c) -{ - struct ObLookForEnters lfe; XEvent e; XSync(ob_display, FALSE); /* count the events without disrupting them */ ignore_enter_focus = 0; - lfe.c = c; - lfe.looking_for_enter = 0; - XCheckIfEvent(ob_display, &e, event_look_for_enters, (XPointer)&lfe); - + XCheckIfEvent(ob_display, &e, event_look_for_enters, NULL); } static gboolean is_enter_focus_event_ignored(XEvent *e) { - g_assert(e->type == EnterNotify); + g_assert(e->type == EnterNotify && + !(e->xcrossing.mode == NotifyGrab || + e->xcrossing.mode == NotifyUngrab || + e->xcrossing.detail == NotifyInferior)); - if (ignore_enter_focus) { - gint i; + ob_debug_type(OB_DEBUG_FOCUS, "# enters ignored: %d\n", + ignore_enter_focus); + if (ignore_enter_focus) { --ignore_enter_focus; - - /* remove the serial */ - for (i = 0; ignore_enter_serials[i] != 0; ++i) { - if (ignore_enter_serials[i] == e->xany.serial) { - for (; ignore_enter_serials[i+1] != 0; ++i) - ignore_enter_serials[i] = ignore_enter_serials[i+1]; - ignore_enter_serials[i] = 0; - } - } return TRUE; } return FALSE;