X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fevent.c;h=68d511352201e9afe33b584ed4168be7bd558666;hb=ebf24d5224781e47b62cf20fb3852ef9782f200b;hp=483050fa9b49498a4ee57f0e44ddcb084f095e61;hpb=17676168255fcf5cbec9ea5dadcee546c5ab7bbb;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index 483050fa..68d51135 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -42,6 +42,7 @@ typedef struct } ObEventData; static void event_process(const XEvent *e, gpointer data); +static void event_done(gpointer data); static void event_handle_root(XEvent *e); static void event_handle_menu(XEvent *e); static void event_handle_dock(ObDock *s, XEvent *e); @@ -132,7 +133,7 @@ void event_startup(gboolean reconfig) } } - ob_main_loop_x_add(ob_main_loop, event_process, NULL, NULL); + ob_main_loop_x_add(ob_main_loop, event_process, event_done, NULL, NULL); #ifdef USE_SM IceAddConnectionWatch(ice_watch, NULL); @@ -283,24 +284,32 @@ static void event_hack_mods(XEvent *e) static gboolean event_ignore(XEvent *e, ObClient *client) { + gboolean ignore = FALSE; + XEvent ce; + switch(e->type) { case FocusIn: + while (XCheckTypedWindowEvent(ob_display, e->xfocus.window, + FocusIn, &ce)) + { + if (!INVALID_FOCUSIN(&ce)) { + XPutBackEvent(ob_display, &ce); + ignore = TRUE; + break; + } + } + /* NotifyAncestor is not ignored in FocusIn like it is in FocusOut because of RevertToPointerRoot. If the focus ends up reverting to pointer root on a workspace change, then the FocusIn event that we want will be of type NotifyAncestor. This situation does not occur for FocusOut, so it is safely ignored there. */ - if (INVALID_FOCUSIN(e) || - client == NULL) { + if (ignore || INVALID_FOCUSIN(e) || client == NULL) { #ifdef DEBUG_FOCUS ob_debug("FocusIn on %lx mode %d detail %d IGNORED\n", e->xfocus.window, e->xfocus.mode, e->xfocus.detail); #endif - /* says a client was not found for the event (or a valid FocusIn - event was not found. - */ - e->xfocus.window = None; return TRUE; } @@ -310,10 +319,20 @@ static gboolean event_ignore(XEvent *e, ObClient *client) #endif break; case FocusOut: - if (INVALID_FOCUSOUT(e)) { + while (XCheckTypedWindowEvent(ob_display, e->xfocus.window, + FocusOut, &ce)) + { + if (!INVALID_FOCUSOUT(&ce)) { + XPutBackEvent(ob_display, &ce); + ignore = TRUE; + break; + } + } + + if (ignore || INVALID_FOCUSOUT(e)) { #ifdef DEBUG_FOCUS - ob_debug("FocusOut on %lx mode %d detail %d IGNORED\n", - e->xfocus.window, e->xfocus.mode, e->xfocus.detail); + ob_debug("FocusOut on %lx mode %d detail %d IGNORED\n", + e->xfocus.window, e->xfocus.mode, e->xfocus.detail); #endif return TRUE; } @@ -322,84 +341,6 @@ static gboolean event_ignore(XEvent *e, ObClient *client) ob_debug("FocusOut on %lx mode %d detail %d\n", e->xfocus.window, e->xfocus.mode, e->xfocus.detail); #endif - - { - XEvent fe; - gboolean fallback = TRUE; - - while (TRUE) { - if (!XCheckTypedWindowEvent(ob_display, e->xfocus.window, - FocusOut, &fe)) - if (!XCheckTypedEvent(ob_display, FocusIn, &fe)) - break; - if (fe.type == FocusOut) { -#ifdef DEBUG_FOCUS - ob_debug("found pending FocusOut\n"); -#endif - if (!INVALID_FOCUSOUT(&fe)) { - /* if there is a VALID FocusOut still coming, don't - fallback focus yet, we'll deal with it then */ - XPutBackEvent(ob_display, &fe); - fallback = FALSE; - break; - } - } else { -#ifdef DEBUG_FOCUS - ob_debug("found pending FocusIn\n"); -#endif - /* is the focused window getting a FocusOut/In back to - itself? - */ - if (fe.xfocus.window == e->xfocus.window && - !event_ignore(&fe, client)) { - /* - if focus_client is not set, then we can't do - this. we need the FocusIn. This happens in the - case when the set_focus_client(NULL) in the - focus_fallback function fires and then - focus_fallback picks the currently focused - window (such as on a SendToDesktop-esque action. - */ - if (focus_client) { -#ifdef DEBUG_FOCUS - ob_debug("focused window got an Out/In back to " - "itself IGNORED both\n"); -#endif - return TRUE; - } else { - event_process(&fe, NULL); -#ifdef DEBUG_FOCUS - ob_debug("focused window got an Out/In back to " - "itself but focus_client was null " - "IGNORED just the Out\n"); -#endif - return TRUE; - } - } - - { - ObEventData d; - - /* once all the FocusOut's have been dealt with, if - there is a FocusIn still left and it is valid, then - use it */ - event_process(&fe, &d); - if (!d.ignored) { - ob_debug("FocusIn was OK, so don't fallback\n"); - fallback = FALSE; - break; - } - } - } - } - if (fallback) { -#ifdef DEBUG_FOCUS - ob_debug("no valid FocusIn and no FocusOut events found, " - "falling back\n"); -#endif - focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS); - } - } break; case EnterNotify: case LeaveNotify: @@ -413,7 +354,7 @@ static gboolean event_ignore(XEvent *e, ObClient *client) (e->xcrossing.detail == NotifyAncestor || e->xcrossing.detail == NotifyNonlinearVirtual || e->xcrossing.detail == NotifyVirtual))) { -#ifdef DEBUG_FOCUS +#ifdef aDEBUG_FOCUS ob_debug("%sNotify mode %d detail %d on %lx IGNORED\n", (e->type == EnterNotify ? "Enter" : "Leave"), e->xcrossing.mode, @@ -421,7 +362,7 @@ static gboolean event_ignore(XEvent *e, ObClient *client) #endif return TRUE; } -#ifdef DEBUG_FOCUS +#ifdef aDEBUG_FOCUS ob_debug("%sNotify mode %d detail %d on %lx\n", (e->type == EnterNotify ? "Enter" : "Leave"), e->xcrossing.mode, @@ -545,6 +486,12 @@ static void event_process(const XEvent *ec, gpointer data) } } +static void event_done(gpointer data) +{ + if (!focus_client) + focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS); +} + static void event_handle_root(XEvent *e) { Atom msgtype; @@ -650,27 +597,22 @@ static void event_handle_client(ObClient *client, XEvent *e) break; case FocusIn: #ifdef DEBUG_FOCUS - ob_debug("FocusIn on client for %lx\n", client->window); + ob_debug("Focus%s on client for %lx\n", (e->type==FocusIn?"In":"Out"), + client->window); #endif - if (client != focus_client) { + if (client != focus_client) focus_set_client(client); - frame_adjust_focus(client->frame, TRUE); - } + frame_adjust_focus(client->frame, e->type == FocusIn); break; case FocusOut: #ifdef DEBUG_FOCUS - ob_debug("FocusOut on client for %lx\n", client->window); + ob_debug("Focus%s on client for %lx\n", (e->type==FocusIn?"In":"Out"), + client->window); #endif - /* are we a fullscreen window or a transient of one? (checks layer) - if we are then we need to be iconified since we are losing focus - */ - if (client->layer == OB_STACKING_LAYER_FULLSCREEN && !client->iconic && - !client_search_focus_tree_full(client)) - /* iconify fullscreen windows when they and their transients - aren't focused */ - client_iconify(client, TRUE, TRUE); - frame_adjust_focus(client->frame, FALSE); - break; + if (client == focus_client) + focus_client = NULL; + frame_adjust_focus(client->frame, e->type == FocusIn); + break; case LeaveNotify: con = frame_context(client, e->xcrossing.window); switch (con) { @@ -733,7 +675,7 @@ static void event_handle_client(ObClient *client, XEvent *e) case OB_FRAME_CONTEXT_FRAME: if (client_normal(client)) { if (config_focus_follow) { -#ifdef DEBUG_FOCUS +#ifdef aDEBUG_FOCUS ob_debug("EnterNotify on %lx, focusing window\n", client->window); #endif