+ Client *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 (!(type == Fallback_Desktop ?
+ config_focus_last_on_desktop : config_focus_last)) {
+ if (config_focus_follow) focus_under_pointer();
+ return;
+ }
+
+ if (type == Fallback_Unfocusing && old) {
+ /* try for transient relations */
+ if (old->transient_for) {
+ if (old->transient_for == 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;
+ }
+ }
+
+ /* 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_focus(sit->data))
+ return;
+ }
+ }
+
+ for (it = focus_order[screen_desktop]; it != NULL; it = it->next)
+ if (type != Fallback_Unfocusing || it->data != old)
+ if (client_normal(it->data) &&
+ /* dont fall back to 'anonymous' fullscreen windows. theres no
+ checks for this is in transient/group fallbacks. */
+ !((Client*)it->data)->fullscreen &&
+ client_focus(it->data))
+ return;
+
+ /* nothing to focus */
+ focus_set_client(NULL);
+}
+
+static void popup_cycle(Client *c, gboolean show)
+{
+ if (!show) {
+ popup_hide(focus_cycle_popup);
+ } else {
+ Rect *a;
+
+ a = screen_area(c->desktop);
+ popup_position(focus_cycle_popup, CenterGravity,
+ a->x + a->width / 2, a->y + a->height / 2);
+/* popup_size(focus_cycle_popup, a->height/2, a->height/16);
+ popup_show(focus_cycle_popup, c->title,
+ client_icon(c, a->height/16, a->height/16));
+*/
+ /* XXX the size and the font extents need to be related on some level
+ */
+ popup_size(focus_cycle_popup, 320, 48);
+
+ /* use the transient's parent's title/icon */
+ while (c->transient_for && c->transient_for != TRAN_GROUP)
+ c = c->transient_for;
+
+ popup_show(focus_cycle_popup, (c->iconic ? c->icon_title : c->title),
+ client_icon(c, 48, 48));
+ }
+}
+
+Client *focus_cycle(gboolean forward, gboolean linear, gboolean done,
+ gboolean cancel)
+{
+ static Client *first = NULL;
+ static Client *t = NULL;
+ static GList *order = NULL;
+ GList *it, *start, *list;
+ Client *ft;
+
+ if (cancel) {
+ /*if (first) client_focus(first); XXX*/
+ if (focus_cycle_target)
+ frame_adjust_focus(focus_cycle_target->frame, FALSE);
+ if (focus_client)
+ frame_adjust_focus(focus_client->frame, TRUE);
+ goto done_cycle;
+ } else if (done) {
+ if (focus_cycle_target) {
+ if (focus_cycle_target->iconic)
+ client_iconify(focus_cycle_target, FALSE, FALSE);
+ client_focus(focus_cycle_target);
+ stacking_raise(focus_cycle_target);
+ }
+ goto done_cycle;
+ }
+ if (!first) first = focus_client;
+ if (!focus_cycle_target) focus_cycle_target = focus_client;