+ return FALSE;
+}
+
+/*! @param allow_helpers This is used for calling itself recursively while
+ checking helper windows. */
+static gboolean valid_focus_target(ObClient *ft,
+ gboolean all_desktops,
+ gboolean dock_windows,
+ gboolean desktop_windows)
+{
+ gboolean ok = FALSE;
+
+ /* it's on this desktop unless you want all desktops.
+
+ do this check first because it will usually filter out the most
+ windows */
+ ok = (all_desktops || ft->desktop == screen_desktop ||
+ ft->desktop == DESKTOP_ALL);
+
+ /* the window can receive focus somehow */
+ ok = ok && (ft->can_focus || ft->focus_notify);
+
+ /* it's the right type of window */
+ if (dock_windows || desktop_windows)
+ ok = ok && ((dock_windows && ft->type == OB_CLIENT_TYPE_DOCK) ||
+ (desktop_windows && ft->type == OB_CLIENT_TYPE_DESKTOP));
+ else
+ /* normal non-helper windows are valid targets */
+ ok = ok &&
+ ((client_normal(ft) && !client_helper(ft))
+ ||
+ /* helper windows are valid targets it... */
+ (client_helper(ft) &&
+ /* ...a window in its group already has focus ... */
+ ((focus_client && ft->group == focus_client->group) ||
+ /* ... or if there are no other windows in its group
+ that can be cycled to instead */
+ !has_valid_group_siblings_on_desktop(ft, all_desktops))));
+
+ /* it's not set to skip the taskbar (unless it is a type that would be
+ expected to set this hint */
+ ok = ok && ((ft->type == OB_CLIENT_TYPE_DOCK ||
+ ft->type == OB_CLIENT_TYPE_TOOLBAR ||
+ ft->type == OB_CLIENT_TYPE_MENU ||
+ ft->type == OB_CLIENT_TYPE_UTILITY) ||
+ !ft->skip_taskbar);
+
+ /* it's not going to just send fous off somewhere else (modal window) */
+ ok = ok && ft == client_focus_target(ft);
+
+ return ok;