From 6d2650263193aaa7e94b29261c6ba249c0be3fd3 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Fri, 18 May 2007 00:11:01 +0000 Subject: [PATCH] super correct enter event ignoring that will only ignore what it has to, yay? --- openbox/action.c | 4 +-- openbox/client.c | 2 +- openbox/client_menu.c | 12 ++++--- openbox/event.c | 97 ++++++++++++++++++++++++++++++++++++++++++--------- openbox/event.h | 10 ++++-- openbox/focus.c | 2 +- openbox/popup.c | 2 +- openbox/screen.c | 2 +- 8 files changed, 100 insertions(+), 31 deletions(-) diff --git a/openbox/action.c b/openbox/action.c index 0a2d2b6..2fd0372 100644 --- a/openbox/action.c +++ b/openbox/action.c @@ -46,8 +46,8 @@ static void client_action_end(union ActionData *data) { if (config_focus_follow) if (data->any.context != OB_FRAME_CONTEXT_CLIENT) { - if (!data->any.button) { - event_ignore_queued_enters(); + if (!data->any.button && data->any.c) { + event_ignore_enters_leaving_window(data->any.c); } else { ObClient *c; diff --git a/openbox/client.c b/openbox/client.c index b0482fa..34af084 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -565,7 +565,7 @@ void client_unmanage(ObClient *self) /* ignore enter events from the unmap so it doesnt mess with the focus */ - event_ignore_queued_enters(); + event_ignore_enters_leaving_window(self); mouse_grab_for_client(self, FALSE); diff --git a/openbox/client_menu.c b/openbox/client_menu.c index 6fa744c..db00265 100644 --- a/openbox/client_menu.c +++ b/openbox/client_menu.c @@ -119,19 +119,15 @@ static void client_menu_execute(ObMenuEntry *e, ObMenuFrame *f, break; case CLIENT_RESTORE: client_maximize(c, FALSE, 0); - event_ignore_queued_enters(); break; case CLIENT_MAXIMIZE: client_maximize(c, TRUE, 0); - event_ignore_queued_enters(); break; case CLIENT_SHADE: client_shade(c, !c->shaded); - event_ignore_queued_enters(); break; case CLIENT_DECORATE: client_set_undecorated(c, !c->undecorated); - event_ignore_queued_enters(); break; case CLIENT_MOVE: /* this needs to grab the keyboard so hide the menu */ @@ -158,6 +154,10 @@ static void client_menu_execute(ObMenuEntry *e, ObMenuFrame *f, g_assert_not_reached(); } + /* we have to ignore all queued enters because the menu has a grab, and the + so the cursor isnt considered inside the client's window */ + event_ignore_all_queued_enters(); + /* update the menu cuz stuff can have changed */ if (f) { client_menu_update(f, NULL); @@ -217,7 +217,9 @@ static void layer_menu_execute(ObMenuEntry *e, ObMenuFrame *f, g_assert_not_reached(); } - event_ignore_queued_enters(); + /* we have to ignore all queued enters because the menu has a grab, and the + so the cursor isnt considered inside the client's window */ + event_ignore_all_queued_enters(); /* update the menu cuz stuff can have changed */ if (f) { diff --git a/openbox/event.c b/openbox/event.c index 99fa955..383b260 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; @@ -883,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", @@ -911,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); @@ -1084,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; } @@ -1180,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); @@ -1268,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, @@ -1717,30 +1720,90 @@ 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) { - guint *count = (guint*)arg; - if (e->type == EnterNotify) { + 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; - - win = g_hash_table_lookup(window_map, &e->xany.window); - if (win && WINDOW_IS_CLIENT(win)) - ++(*count); + 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; + } } return False; /* don't disrupt the queue order, just count them */ } -void event_ignore_queued_enters() +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; - XCheckIfEvent(ob_display, &e, event_look_for_enters, - (XPointer)&ignore_enter_focus); + 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; + } + return FALSE; } gboolean event_time_after(Time t1, Time t2) diff --git a/openbox/event.h b/openbox/event.h index 4fdf292..f794039 100644 --- a/openbox/event.h +++ b/openbox/event.h @@ -39,9 +39,13 @@ void event_shutdown(gboolean reconfig); follows mouse */ void event_enter_client(struct _ObClient *client); -/*! Request that any queued EnterNotify events not be used for distributing - focus */ -void event_ignore_queued_enters(); +/*! Make mouse focus not move if the mouse leaves this client from what + has just transpired. */ +void event_ignore_enters_leaving_window(struct _ObClient *c); + +/*! Make mouse focus not move at all from the stuff that has happened up + till now. */ +void event_ignore_all_queued_enters(); /* Halts any focus delay in progress, use this when the user is selecting a window for focus */ diff --git a/openbox/focus.c b/openbox/focus.c index 301e5dd..e88b688 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -425,7 +425,7 @@ void focus_cycle_draw_indicator() XUnmapWindow(ob_display, focus_indicator.bottom.win); /* kill enter events cause by this unmapping */ - event_ignore_queued_enters(); + event_ignore_all_queued_enters(); } else { /* if (focus_cycle_target) diff --git a/openbox/popup.c b/openbox/popup.c index 91c1849..2768ee2 100644 --- a/openbox/popup.c +++ b/openbox/popup.c @@ -269,7 +269,7 @@ void popup_hide(ObPopup *self) self->mapped = FALSE; /* kill enter events cause by this unmapping */ - event_ignore_queued_enters(); + event_ignore_all_queued_enters(); } else if (self->delay_mapped) { ob_main_loop_timeout_remove(ob_main_loop, popup_show_timeout); self->delay_mapped = FALSE; diff --git a/openbox/screen.c b/openbox/screen.c index a72bd7e..6551da8 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -523,7 +523,7 @@ void screen_set_desktop(guint num, gboolean dofocus) } } - event_ignore_queued_enters(); + event_ignore_all_queued_enters(); if (event_curtime != CurrentTime) screen_desktop_user_time = event_curtime; -- 1.9.1