diff --git a/openbox/action.c b/openbox/action.c index 6d455f1f..73524ae4 100644 --- a/openbox/action.c +++ b/openbox/action.c @@ -1172,7 +1172,7 @@ void action_focus(union ActionData *data) void action_unfocus (union ActionData *data) { if (data->client.any.c == focus_client) - focus_fallback(OB_FOCUS_FALLBACK_UNFOCUSING); + focus_fallback(FALSE); } void action_iconify(union ActionData *data) diff --git a/openbox/client.c b/openbox/client.c index e7c7f62a..b49d3ff8 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -78,6 +78,7 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y); static void client_restore_session_state(ObClient *self); static void client_restore_session_stacking(ObClient *self); static ObAppSettings *client_get_settings_state(ObClient *self); +static void client_unfocus(ObClient *self); void client_startup(gboolean reconfig) { @@ -2515,10 +2516,10 @@ static void client_iconify_recursive(ObClient *self, ob_debug("%sconifying window: 0x%lx\n", (iconic ? "I" : "Uni"), self->window); - self->iconic = iconic; - if (iconic) { if (self->functions & OB_CLIENT_FUNC_ICONIFY) { + self->iconic = iconic; + /* update the focus lists.. iconic windows go to the bottom of the list, put the new iconic window at the 'top of the bottom'. */ @@ -2527,6 +2528,8 @@ static void client_iconify_recursive(ObClient *self, changed = TRUE; } } else { + self->iconic = iconic; + if (curdesk) client_set_desktop(self, screen_desktop, FALSE); @@ -3031,14 +3034,7 @@ gboolean client_focus(ObClient *self) ob_debug("Focusing client \"%s\" at time %u\n", self->title, event_curtime); if (self->can_focus) { - /* RevertToPointerRoot causes much more headache than RevertToNone, so - I choose to use it always, hopefully to find errors quicker, if any - are left. (I hate X. I hate focus events.) - - Update: Changing this to RevertToNone fixed a bug with mozilla (bug - #799. So now it is RevertToNone again. - */ - XSetInputFocus(ob_display, self->window, RevertToNone, + XSetInputFocus(ob_display, self->window, RevertToPointerRoot, event_curtime); } @@ -3073,13 +3069,13 @@ gboolean client_focus(ObClient *self) /* Used when the current client is closed or otherwise hidden, focus_last will then prevent focus from going to the mouse pointer */ -void client_unfocus(ObClient *self) +static void client_unfocus(ObClient *self) { if (focus_client == self) { #ifdef DEBUG_FOCUS ob_debug("client_unfocus for %lx\n", self->window); #endif - focus_fallback(OB_FOCUS_FALLBACK_CLOSED); + focus_fallback(FALSE); } } diff --git a/openbox/client.h b/openbox/client.h index 38480a66..cbb80ede 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -494,9 +494,6 @@ gboolean client_can_focus(ObClient *self); */ gboolean client_focus(ObClient *self); -/*! Remove focus from the client window */ -void client_unfocus(ObClient *self); - /*! Activates the client for use, focusing, uniconifying it, etc. To be used when the user deliberately selects a window for use. @param here If true, then the client is brought to the current desktop; diff --git a/openbox/event.c b/openbox/event.c index 7eef8017..d4d921ef 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -422,7 +422,7 @@ static void event_process(const XEvent *ec, gpointer data) } } -#if 0 /* focus debugging stuff */ +#if 1 /* focus debugging stuff */ if (e->type == FocusIn || e->type == FocusOut) { gint mode = e->xfocus.mode; gint detail = e->xfocus.detail; @@ -655,8 +655,12 @@ static void event_handle_client(ObClient *client, XEvent *e) case FocusOut: /* Look for the followup FocusIn */ if (!XCheckIfEvent(ob_display, &ce, look_for_focusin, NULL)) { - /* There is no FocusIn, move focus where we can still hear events*/ - focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS); + /* There is no FocusIn, this means focus went to a window that + is not being managed. most likely, this went to PointerRoot + or None, meaning the window is no longer around so fallback + focus, but not to that window */ + ob_debug("Focus went to a black hole !\n"); + focus_fallback(FALSE); } else if (ce.xany.window == e->xany.window) { /* If focus didn't actually move anywhere, there is nothing to do*/ break; @@ -667,7 +671,9 @@ static void event_handle_client(ObClient *client, XEvent *e) if (ed.ignored) { /* The FocusIn was ignored, this means it was on a window that isn't a client. */ - focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS); + ob_debug("Focus went to an unmanaged window 0x%x !\n", + ce.xfocus.window); + focus_fallback(TRUE); } } diff --git a/openbox/focus.c b/openbox/focus.c index 201a4349..3fba876b 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -248,7 +248,7 @@ static ObClient* focus_fallback_transient(ObClient *top, ObClient *old) return NULL; } -ObClient* focus_fallback_target(ObFocusFallbackType type) +ObClient* focus_fallback_target(gboolean allow_refocus) { GList *it; ObClient *old; @@ -256,60 +256,57 @@ ObClient* focus_fallback_target(ObFocusFallbackType type) old = focus_client; - if ((type == OB_FOCUS_FALLBACK_UNFOCUSING - || type == OB_FOCUS_FALLBACK_CLOSED) && old) { - if (old->transient_for) { - gboolean trans = FALSE; + if (!allow_refocus && old && old->transient_for) { + gboolean trans = FALSE; - if (!config_focus_follow || config_focus_last) - trans = TRUE; - else if ((target = client_under_pointer()) && - client_search_transient - (client_search_top_parent(target), old)) - trans = TRUE; + if (!config_focus_follow || config_focus_last) + trans = TRUE; + else if ((target = client_under_pointer()) && + client_search_transient + (client_search_top_parent(target), old)) + trans = TRUE; - /* try for transient relations */ - if (trans) { - if (old->transient_for == OB_TRAN_GROUP) { - for (it = focus_order[screen_desktop]; it; - it = g_list_next(it)) + /* try for transient relations */ + if (trans) { + if (old->transient_for == OB_TRAN_GROUP) { + for (it = focus_order[screen_desktop]; it; + it = g_list_next(it)) + { + GSList *sit; + + for (sit = old->group->members; sit; + sit = g_slist_next(sit)) { - GSList *sit; - - for (sit = old->group->members; sit; - sit = g_slist_next(sit)) - { - if (sit->data == it->data) - if ((target = - focus_fallback_transient(sit->data, old))) - { - ob_debug("found in transient #1\n"); - return target; - } - } - } - } else { - if ((target = - focus_fallback_transient(old->transient_for, old))) - { - ob_debug("found in transient #2\n"); - return target; + if (sit->data == it->data) + if ((target = + focus_fallback_transient(sit->data, old))) + { + ob_debug("found in transient #1\n"); + return target; + } } } + } else { + if ((target = + focus_fallback_transient(old->transient_for, old))) + { + ob_debug("found in transient #2\n"); + return target; + } } } } ob_debug("trying pointer stuff\n"); - if (config_focus_follow && - (type == OB_FOCUS_FALLBACK_UNFOCUSING || !config_focus_last)) + if (config_focus_follow && !config_focus_last) { if ((target = client_under_pointer())) - if (client_normal(target) && client_can_focus(target) && - client_validate(target)) { - ob_debug("found in pointer stuff\n"); - return target; - } + if (allow_refocus || target != old) + if (client_normal(target) && client_can_focus(target) && + client_validate(target)) { + ob_debug("found in pointer stuff\n"); + return target; + } } #if 0 @@ -328,7 +325,7 @@ ObClient* focus_fallback_target(ObFocusFallbackType type) ob_debug("trying the focus order\n"); for (it = focus_order[screen_desktop]; it; it = g_list_next(it)) - if (type != OB_FOCUS_FALLBACK_UNFOCUSING || it->data != old) + if (allow_refocus || it->data != old) if (client_normal(it->data) && client_can_focus(it->data) && client_validate(it->data)) { @@ -344,7 +341,7 @@ ObClient* focus_fallback_target(ObFocusFallbackType type) return NULL; } -void focus_fallback(ObFocusFallbackType type) +void focus_fallback(gboolean allow_refocus) { ObClient *new; @@ -354,7 +351,7 @@ void focus_fallback(ObFocusFallbackType type) */ focus_set_client(NULL); - if ((new = focus_fallback_target(type))) + if ((new = focus_fallback_target(allow_refocus))) client_focus(new); } diff --git a/openbox/focus.h b/openbox/focus.h index 81cd5ffe..e71cd2d7 100644 --- a/openbox/focus.h +++ b/openbox/focus.h @@ -50,17 +50,10 @@ void focus_shutdown(gboolean reconfig); send focus anywhere, its called by the Focus event handlers */ void focus_set_client(struct _ObClient *client); -typedef enum { - OB_FOCUS_FALLBACK_UNFOCUSING, /*!< forcefully remove focus from the - current window */ - OB_FOCUS_FALLBACK_CLOSED, /*!< closed the window with focus */ - OB_FOCUS_FALLBACK_NOFOCUS /*!< nothing has focus for some reason */ -} ObFocusFallbackType; - -struct _ObClient* focus_fallback_target(ObFocusFallbackType type); +struct _ObClient* focus_fallback_target(gboolean allow_refocus); /*! Call this when you need to focus something! */ -void focus_fallback(ObFocusFallbackType type); +void focus_fallback(gboolean allow_refocus); /*! Cycle focus amongst windows. */ void focus_cycle(gboolean forward, gboolean linear, gboolean interactive, diff --git a/openbox/openbox.c b/openbox/openbox.c index 8d491a42..c355747f 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -278,7 +278,7 @@ gint main(gint argc, gchar **argv) if (!reconfigure) { /* get all the existing windows */ client_manage_all(); - focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS); + focus_fallback(TRUE); } else { GList *it; diff --git a/openbox/screen.c b/openbox/screen.c index dcb9cd13..0d4f2fb3 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -463,7 +463,7 @@ void screen_set_desktop(guint num) event_ignore_queued_enters(); - focus_hilite = focus_fallback_target(OB_FOCUS_FALLBACK_NOFOCUS); + focus_hilite = focus_fallback_target(TRUE); if (focus_hilite) { frame_adjust_focus(focus_hilite->frame, TRUE); @@ -893,7 +893,7 @@ void screen_show_desktop(gboolean show) client_validate(it->data) && client_focus(it->data)) break; } else { - focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS); + focus_fallback(TRUE); } show = !!show; /* make it boolean */