]> Dogcows Code - chaz/openbox/blobdiff - openbox/focus_cycle.c
let you focus cycle to helper windows if there are only dialog windows around in...
[chaz/openbox] / openbox / focus_cycle.c
index 4ff098d71cfd8fb75b712256d5b37ebb7db2972a..ca299c6711833802493aebe64b57a468d0e84e6a 100644 (file)
@@ -32,6 +32,7 @@
 #include <glib.h>
 
 ObClient       *focus_cycle_target = NULL;
+static gboolean focus_cycle_iconic_windows;
 static gboolean focus_cycle_all_desktops;
 static gboolean focus_cycle_dock_windows;
 static gboolean focus_cycle_desktop_windows;
@@ -43,10 +44,6 @@ static ObClient *focus_find_directional    (ObClient *c,
                                             ObDirection dir,
                                             gboolean dock_windows,
                                             gboolean desktop_windows);
-static ObClient *focus_find_directional    (ObClient *c,
-                                            ObDirection dir,
-                                            gboolean dock_windows,
-                                            gboolean desktop_windows);
 
 void focus_cycle_startup(gboolean reconfig)
 {
@@ -58,9 +55,17 @@ void focus_cycle_shutdown(gboolean reconfig)
     if (reconfig) return;
 }
 
-void focus_cycle_stop()
+void focus_cycle_stop(ObClient *ifclient)
 {
-    if (focus_cycle_target) {
+    /* stop focus cycling if the given client is a valid focus target,
+       and so the cycling is being disrupted */
+    if (focus_cycle_target && ifclient &&
+        focus_cycle_target_valid(ifclient,
+                                 focus_cycle_iconic_windows,
+                                 focus_cycle_all_desktops,
+                                 focus_cycle_dock_windows,
+                                 focus_cycle_desktop_windows))
+    {
         focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
         focus_directional_cycle(0, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
     }
@@ -80,7 +85,7 @@ static gboolean focus_target_has_siblings(ObClient *ft,
     for (it = ft->group->members; it; it = g_slist_next(it)) {
         ObClient *c = it->data;
         /* check that it's not a helper window to avoid infinite recursion */
-        if (c != ft && !client_helper(c) &&
+        if (c != ft && c->type == OB_CLIENT_TYPE_NORMAL &&
             focus_cycle_target_valid(c, iconic_windows, all_desktops, FALSE,
                                      FALSE))
         {
@@ -122,7 +127,7 @@ gboolean focus_cycle_target_valid(ObClient *ft,
         ok = ok &&
             ((client_normal(ft) && !client_helper(ft))
              ||
-             /* helper windows are valid targets it... */
+             /* helper windows are valid targets if... */
              (client_helper(ft) &&
               /* ...a window in its group already has focus ... */
               ((focus_client && ft->group == focus_client->group) ||
@@ -140,8 +145,17 @@ gboolean focus_cycle_target_valid(ObClient *ft,
                 ft->modal ||
                 !ft->skip_taskbar);
 
-    /* it's not going to just send fous off somewhere else (modal window) */
-    ok = ok && ft == client_focus_target(ft);
+    /* it's not going to just send focus off somewhere else (modal window),
+       unless that modal window is not one of our valid targets, then let
+       you choose this window and bring the modal one here */
+    {
+        ObClient *cft = client_focus_target(ft);
+        ok = ok && (ft == cft || !focus_cycle_target_valid(cft,
+                                                           iconic_windows,
+                                                           all_desktops,
+                                                           dock_windows,
+                                                           desktop_windows));
+    }
 
     return ok;
 }
@@ -151,7 +165,6 @@ void focus_cycle(gboolean forward, gboolean all_desktops,
                  gboolean linear, gboolean interactive,
                  gboolean dialog, gboolean done, gboolean cancel)
 {
-    static ObClient *first = NULL;
     static ObClient *t = NULL;
     static GList *order = NULL;
     GList *it, *start, *list;
@@ -167,8 +180,6 @@ void focus_cycle(gboolean forward, gboolean all_desktops,
         if (!focus_order)
             goto done_cycle;
 
-        if (!first) first = focus_client;
-
         if (linear) list = client_list;
         else        list = focus_order;
     } else {
@@ -179,13 +190,14 @@ void focus_cycle(gboolean forward, gboolean all_desktops,
 
 
     if (focus_cycle_target == NULL) {
-        focus_cycle_all_desktops = FALSE;
+        focus_cycle_iconic_windows = TRUE;
+        focus_cycle_all_desktops = all_desktops;
         focus_cycle_dock_windows = dock_windows;
         focus_cycle_desktop_windows = desktop_windows;
-        focus_cycle_target = focus_client;
-    }
+        start = it = g_list_find(list, focus_client);
+    } else
+        start = it = g_list_find(list, focus_cycle_target);
 
-    start = it = g_list_find(list, focus_cycle_target);
     if (!start) /* switched desktops or something? */
         start = it = forward ? g_list_last(list) : g_list_first(list);
     if (!start) goto done_cycle;
@@ -199,7 +211,8 @@ void focus_cycle(gboolean forward, gboolean all_desktops,
             if (it == NULL) it = g_list_last(list);
         }
         ft = it->data;
-        if (focus_cycle_target_valid(ft, TRUE,
+        if (focus_cycle_target_valid(ft,
+                                     focus_cycle_iconic_windows,
                                      focus_cycle_all_desktops,
                                      focus_cycle_dock_windows,
                                      focus_cycle_desktop_windows))
@@ -211,7 +224,8 @@ void focus_cycle(gboolean forward, gboolean all_desktops,
                 }
                 if (dialog)
                     /* same arguments as focus_target_valid */
-                    focus_cycle_popup_show(ft, TRUE,
+                    focus_cycle_popup_show(ft,
+                                           focus_cycle_iconic_windows,
                                            focus_cycle_all_desktops,
                                            focus_cycle_dock_windows,
                                            focus_cycle_desktop_windows);
@@ -229,7 +243,6 @@ done_cycle:
         client_activate(focus_cycle_target, FALSE, TRUE);
 
     t = NULL;
-    first = NULL;
     focus_cycle_target = NULL;
     g_list_free(order);
     order = NULL;
@@ -254,7 +267,7 @@ static ObClient *focus_find_directional(ObClient *c, ObDirection dir,
     ObClient *best_client, *cur;
     GList *it;
 
-    if(!client_list)
+    if (!client_list)
         return NULL;
 
     /* first, find the centre coords of the currently focused window */
@@ -262,13 +275,13 @@ static ObClient *focus_find_directional(ObClient *c, ObDirection dir,
     my_cy = c->frame->area.y + c->frame->area.height / 2;
 
     best_score = -1;
-    best_client = NULL;
+    best_client = c;
 
-    for(it = g_list_first(client_list); it; it = g_list_next(it)) {
+    for (it = g_list_first(client_list); it; it = g_list_next(it)) {
         cur = it->data;
 
         /* the currently selected window isn't interesting */
-        if(cur == c)
+        if (cur == c)
             continue;
         if (!focus_cycle_target_valid(it->data, FALSE, FALSE, dock_windows,
                                       desktop_windows))
@@ -281,8 +294,9 @@ static ObClient *focus_find_directional(ObClient *c, ObDirection dir,
         his_cy = (cur->frame->area.y - my_cy)
             + cur->frame->area.height / 2;
 
-        if(dir == OB_DIRECTION_NORTHEAST || dir == OB_DIRECTION_SOUTHEAST ||
-           dir == OB_DIRECTION_SOUTHWEST || dir == OB_DIRECTION_NORTHWEST) {
+        if (dir == OB_DIRECTION_NORTHEAST || dir == OB_DIRECTION_SOUTHEAST ||
+            dir == OB_DIRECTION_SOUTHWEST || dir == OB_DIRECTION_NORTHWEST)
+        {
             gint tx;
             /* Rotate the diagonals 45 degrees counterclockwise.
              * To do this, multiply the matrix /+h +h\ with the
@@ -294,7 +308,7 @@ static ObClient *focus_find_directional(ObClient *c, ObDirection dir,
             his_cx = tx;
         }
 
-        switch(dir) {
+        switch (dir) {
         case OB_DIRECTION_NORTH:
         case OB_DIRECTION_SOUTH:
         case OB_DIRECTION_NORTHEAST:
@@ -316,7 +330,7 @@ static ObClient *focus_find_directional(ObClient *c, ObDirection dir,
         }
 
         /* the target must be in the requested direction */
-        if(distance <= 0)
+        if (distance <= 0)
             continue;
 
         /* Calculate score for this window.  The smaller the better. */
@@ -325,12 +339,13 @@ static ObClient *focus_find_directional(ObClient *c, ObDirection dir,
         /* windows more than 45 degrees off the direction are
          * heavily penalized and will only be chosen if nothing
          * else within a million pixels */
-        if(offset > distance)
+        if (offset > distance)
             score += 1000000;
 
-        if(best_score == -1 || score < best_score)
-            best_client = cur,
-                best_score = score;
+        if (best_score == -1 || score < best_score) {
+            best_client = cur;
+            best_score = score;
+        }
     }
 
     return best_client;
@@ -356,10 +371,10 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows,
         goto done_cycle;
 
     if (focus_cycle_target == NULL) {
+        focus_cycle_iconic_windows = FALSE;
         focus_cycle_all_desktops = FALSE;
         focus_cycle_dock_windows = dock_windows;
         focus_cycle_desktop_windows = desktop_windows;
-        focus_cycle_target = focus_client;
     }
 
     if (!first) first = focus_client;
@@ -367,11 +382,15 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows,
     if (focus_cycle_target)
         ft = focus_find_directional(focus_cycle_target, dir, dock_windows,
                                     desktop_windows);
+    else if (first)
+        ft = focus_find_directional(first, dir, dock_windows, desktop_windows);
     else {
         GList *it;
 
         for (it = focus_order; it; it = g_list_next(it))
-            if (focus_cycle_target_valid(it->data, FALSE, FALSE,
+            if (focus_cycle_target_valid(it->data,
+                                         focus_cycle_iconic_windows,
+                                         focus_cycle_all_desktops,
                                          focus_cycle_dock_windows,
                                          focus_cycle_desktop_windows))
                 ft = it->data;
@@ -383,14 +402,14 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows,
             focus_cycle_draw_indicator(ft);
         }
     }
-    if (focus_cycle_target && dialog) {
+    if (focus_cycle_target && dialog)
         /* same arguments as focus_target_valid */
         focus_cycle_popup_single_show(focus_cycle_target,
-                                      FALSE, FALSE,
+                                      focus_cycle_iconic_windows,
+                                      focus_cycle_all_desktops,
                                       focus_cycle_dock_windows,
                                       focus_cycle_desktop_windows);
-        return;
-    }
+    return;
 
 done_cycle:
     if (done && focus_cycle_target)
This page took 0.035018 seconds and 4 git commands to generate.