X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fevent.c;h=383b260136ca6e80dfb1c94de7b21515ca2f4283;hb=6d2650263193aaa7e94b29261c6ba249c0be3fd3;hp=7b8793fa8bc0e28aaa0a59e3d3c7bf943a7dc643;hpb=281c1edb4206b7e7874990b1bd5f66e1e7e43ede;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index 7b8793fa..383b2601 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -85,6 +85,7 @@ static void event_handle_dockapp(ObDockApp *app, XEvent *e); static void event_handle_client(ObClient *c, XEvent *e); static void event_handle_user_time_window_clients(GSList *l, XEvent *e); static void event_handle_user_input(ObClient *client, XEvent *e); +static gboolean is_enter_focus_event_ignored(XEvent *e); static void focus_delay_dest(gpointer data); static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2); @@ -96,7 +97,11 @@ 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; @@ -359,7 +364,7 @@ static Bool event_look_for_focusin(Display *d, XEvent *e, XPointer arg) return e->type == FocusIn && wanted_focusevent(e, FALSE); } -Bool event_look_for_focusin_client(Display *d, XEvent *e, XPointer arg) +static Bool event_look_for_focusin_client(Display *d, XEvent *e, XPointer arg) { return e->type == FocusIn && wanted_focusevent(e, TRUE); } @@ -574,7 +579,6 @@ static void event_process(const XEvent *ec, gpointer data) frame_adjust_focus(client->frame, FALSE); if (client == focus_client) focus_set_client(NULL); - /* focus_set_client has already been called for sure */ client_calc_layer(client); } } else if (timewinclients) @@ -884,7 +888,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_queued_enters(); + event_ignore_enters_leaving_window(client); ob_debug_type(OB_DEBUG_FOCUS, "%sNotify mode %d detail %d on %lx\n", @@ -912,10 +916,8 @@ static void event_handle_client(ObClient *client, XEvent *e) { gboolean nofocus = FALSE; - if (ignore_enter_focus) { - ignore_enter_focus--; + if (is_enter_focus_event_ignored(e)) nofocus = TRUE; - } con = frame_context(client, e->xcrossing.window, e->xcrossing.x, e->xcrossing.y); @@ -1085,7 +1087,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_queued_enters(); + event_ignore_enters_leaving_window(client); } break; } @@ -1181,7 +1183,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_queued_enters(); + event_ignore_enters_leaving_window(client); } else if (msgtype == prop_atoms.net_close_window) { ob_debug("net_close_window for 0x%lx\n", client->window); client_close(client); @@ -1269,7 +1271,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_queued_enters(); + event_ignore_enters_leaving_window(client); } else if (msgtype == prop_atoms.net_restack_window) { if (e->xclient.data.l[0] != 2) { ob_debug_type(OB_DEBUG_APP_BUGS, @@ -1718,35 +1720,90 @@ void event_halt_focus_delay() ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func); } -void event_ignore_queued_enters() +struct ObLookForEnters { - GSList *saved = NULL, *it; - XEvent *e; - - XSync(ob_display, FALSE); + 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)) + { + 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; + } - /* count the events */ - while (TRUE) { - e = g_new(XEvent, 1); - if (XCheckTypedEvent(ob_display, EnterNotify, e)) { - ObWindow *win; - + 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; - - saved = g_slist_append(saved, e); - } else { - g_free(e); - break; + } + + /* 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; } } - /* put the events back */ - for (it = saved; it; it = g_slist_next(it)) { - XPutBackEvent(ob_display, it->data); - g_free(it->data); + 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); + +} + +static gboolean is_enter_focus_event_ignored(XEvent *e) +{ + g_assert(e->type == EnterNotify); + + if (ignore_enter_focus) { + gint i; + + --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; } - g_slist_free(saved); + return FALSE; } gboolean event_time_after(Time t1, Time t2)