-/* finds the first transient that isn't 'skip' and ensure's that client_normal
- is true for it */
-static ObClient *find_transient_recursive(ObClient *c, ObClient *top, ObClient *skip)
-{
- GSList *it;
- ObClient *ret;
-
- for (it = c->transients; it; it = it->next) {
- if (it->data == top) return NULL;
- ret = find_transient_recursive(it->data, top, skip);
- if (ret && ret != skip && client_normal(ret)) return ret;
- if (it->data != skip && client_normal(it->data)) return it->data;
- }
- return NULL;
-}
-
-static gboolean focus_fallback_transient(ObClient *top, ObClient *old)
-{
- ObClient *target = find_transient_recursive(top, top, old);
- if (!target) {
- /* make sure client_normal is true always */
- if (!client_normal(top))
- return FALSE;
- target = top; /* no transient, keep the top */
- }
- return client_focus(target);
-}
-
-void focus_fallback(ObFocusFallbackType type)
-{
- GList *it;
- ObClient *old = NULL;
-
- old = focus_client;
-
- /* unfocus any focused clients.. they can be focused by Pointer events
- and such, and then when I try focus them, I won't get a FocusIn event
- at all for them.
- */
- focus_set_client(NULL);
-
- if (config_focus_follow && focus_under_pointer())
- return;
-
- if (type == OB_FOCUS_FALLBACK_UNFOCUSING && old) {
- /* try for transient relations */
- if (old->transient_for) {
- if (old->transient_for == OB_TRAN_GROUP) {
- for (it = focus_order[screen_desktop]; it; it = it->next) {
- GSList *sit;
-
- for (sit = old->group->members; sit; sit = sit->next)
- if (sit->data == it->data)
- if (focus_fallback_transient(sit->data, old))
- return;
- }
- } else {
- if (focus_fallback_transient(old->transient_for, old))
- return;
- }
- }
-
-#if 0
- /* try for group relations */
- if (old->group) {
- GSList *sit;
-
- for (it = focus_order[screen_desktop]; it != NULL; it = it->next)
- for (sit = old->group->members; sit; sit = sit->next)
- if (sit->data == it->data)
- if (sit->data != old && client_normal(sit->data))
- if (client_can_focus(sit->data)) {
- gboolean r = client_focus(sit->data);
- assert(r);
- return;
- }
+ ob_debug_type(OB_DEBUG_FOCUS, "trying the focus order\n");
+ for (it = focus_order; it; it = g_list_next(it)) {
+ c = it->data;
+ /* fallback focus to a window if:
+ 1. it is on the current desktop. this ignores omnipresent
+ windows, which are problematic in their own rite, unless they are
+ specifically allowed
+ 2. it is a normal type window, don't fall back onto a dock or
+ a splashscreen or a desktop window (save the desktop as a
+ backup fallback though)
+ */
+ if ((allow_omnipresent || c->desktop == screen_desktop) &&
+ client_normal(c) &&
+ (allow_refocus || client_focus_target(c) != old) &&
+ client_focus(c))
+ {
+ ob_debug_type(OB_DEBUG_FOCUS, "found in focus order\n");
+ return c;