scary commit..but here goes.
[mikachu/openbox.git] / openbox / focus.c
index 63d2c97..f867ff1 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
 
    focus.c for the Openbox window manager
-   Copyright (c) 2004        Mikael Magnusson
+   Copyright (c) 2006        Mikael Magnusson
    Copyright (c) 2003        Ben Jansens
 
    This program is free software; you can redistribute it and/or modify
@@ -58,7 +58,7 @@ static void focus_cycle_destructor(ObClient *client, gpointer data)
 {
     /* end cycling if the target disappears */
     if (focus_cycle_target == client)
-        focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE);
+        focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
 }
 
 static Window createWindow(Window parent, gulong mask,
@@ -87,25 +87,20 @@ void focus_startup(gboolean reconfig)
         focus_indicator.right.obwin.type = Window_Internal;
         focus_indicator.bottom.obwin.type = Window_Internal;
 
-        attr.save_under = True;
         attr.override_redirect = True;
         attr.background_pixel = BlackPixel(ob_display, ob_screen);
         focus_indicator.top.win =
             createWindow(RootWindow(ob_display, ob_screen),
-                         CWOverrideRedirect | CWBackPixel | CWSaveUnder,
-                         &attr);
+                         CWOverrideRedirect | CWBackPixel, &attr);
         focus_indicator.left.win =
             createWindow(RootWindow(ob_display, ob_screen),
-                         CWOverrideRedirect | CWBackPixel | CWSaveUnder,
-                         &attr);
+                         CWOverrideRedirect | CWBackPixel, &attr);
         focus_indicator.right.win =
             createWindow(RootWindow(ob_display, ob_screen),
-                         CWOverrideRedirect | CWBackPixel | CWSaveUnder,
-                         &attr);
+                         CWOverrideRedirect | CWBackPixel, &attr);
         focus_indicator.bottom.win =
             createWindow(RootWindow(ob_display, ob_screen),
-                         CWOverrideRedirect | CWBackPixel | CWSaveUnder,
-                         &attr);
+                         CWOverrideRedirect | CWBackPixel, &attr);
 
         stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.top));
         stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.left));
@@ -144,7 +139,7 @@ void focus_shutdown(gboolean reconfig)
         g_free(focus_order);
 
         /* reset focus to root */
-        XSetInputFocus(ob_display, PointerRoot, RevertToNone, event_lasttime);
+        XSetInputFocus(ob_display, PointerRoot, RevertToNone, CurrentTime);
 
         RrColorFree(color_white);
 
@@ -186,13 +181,13 @@ void focus_set_client(ObClient *client)
 #endif
         /* when nothing will be focused, send focus to the backup target */
         XSetInputFocus(ob_display, screen_support_win, RevertToNone,
-                       event_lasttime);
+                       event_curtime);
         XSync(ob_display, FALSE);
     }
 
     /* in the middle of cycling..? kill it. */
     if (focus_cycle_target)
-        focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE);
+        focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
 
     old = focus_client;
     focus_client = client;
@@ -249,7 +244,8 @@ ObClient* focus_fallback_target(ObFocusFallbackType type)
 
     old = focus_client;
 
-    if (type == OB_FOCUS_FALLBACK_UNFOCUSING && old) {
+    if ((type == OB_FOCUS_FALLBACK_UNFOCUSING
+         || type == OB_FOCUS_FALLBACK_CLOSED) && old) {
         if (old->transient_for) {
             gboolean trans = FALSE;
 
@@ -290,7 +286,9 @@ ObClient* focus_fallback_target(ObFocusFallbackType type)
         }
     }
 
-    if (config_focus_follow && !config_focus_last) {
+    if (config_focus_follow &&
+        (type == OB_FOCUS_FALLBACK_UNFOCUSING || !config_focus_last))
+    {
         if ((target = client_under_pointer()))
             if (client_normal(target) && client_can_focus(target))
                 return target;
@@ -315,6 +313,11 @@ ObClient* focus_fallback_target(ObFocusFallbackType type)
             if (client_normal(it->data) && client_can_focus(it->data))
                 return it->data;
 
+    /* XXX fallback to the "desktop window" if one exists ?
+       could store it while going through all the windows in the loop right
+       above this..
+    */
+
     return NULL;
 }
 
@@ -356,14 +359,13 @@ static void popup_cycle(ObClient *c, gboolean show)
         while (p->transient_for && p->transient_for != OB_TRAN_GROUP)
             p = p->transient_for;
 
-/*
-        if (p != c)
-            title = g_strconcat((c->iconic ? c->icon_title : c->title),
+        if (p != c && !strcmp("", (c->iconic ? c->icon_title : c->title)))
+            title = g_strdup(p->iconic ? p->icon_title : p->title);
+            /*title = g_strconcat((c->iconic ? c->icon_title : c->title),
                                 " - ",
                                 (p->iconic ? p->icon_title : p->title),
                                 NULL);
-*/
-
+            */
         icon_popup_show(focus_cycle_popup,
                         (title ? title :
                          (c->iconic ? c->icon_title : c->title)),
@@ -390,7 +392,7 @@ void focus_cycle_draw_indicator()
 
         wt = wl = wr = wb = MAX(3,
                                 ob_rr_theme->handle_height +
-                                ob_rr_theme->bwidth * 2);
+                                ob_rr_theme->fbwidth * 2);
 
         x = focus_cycle_target->frame->area.x;
         y = focus_cycle_target->frame->area.y;
@@ -539,7 +541,7 @@ static gboolean valid_focus_target(ObClient *ft)
     return FALSE;
 }
 
-void focus_cycle(gboolean forward, gboolean linear,
+void focus_cycle(gboolean forward, gboolean linear, gboolean interactive,
                  gboolean dialog, gboolean done, gboolean cancel)
 {
     static ObClient *first = NULL;
@@ -548,20 +550,26 @@ void focus_cycle(gboolean forward, gboolean linear,
     GList *it, *start, *list;
     ObClient *ft = NULL;
 
-    if (cancel) {
-        focus_cycle_target = NULL;
-        goto done_cycle;
-    } else if (done)
-        goto done_cycle;
+    if (interactive) {
+        if (cancel) {
+            focus_cycle_target = NULL;
+            goto done_cycle;
+        } else if (done)
+            goto done_cycle;
 
-    if (!focus_order[screen_desktop])
-        goto done_cycle;
+        if (!focus_order[screen_desktop])
+            goto done_cycle;
 
-    if (!first) first = focus_client;
-    if (!focus_cycle_target) focus_cycle_target = focus_client;
+        if (!first) first = focus_client;
 
-    if (linear) list = client_list;
-    else        list = focus_order[screen_desktop];
+        if (linear) list = client_list;
+        else        list = focus_order[screen_desktop];
+    } else {
+        if (!focus_order[screen_desktop])
+            goto done_cycle;
+        list = client_list;
+    }
+    if (!focus_cycle_target) focus_cycle_target = focus_client;
 
     start = it = g_list_find(list, focus_cycle_target);
     if (!start) /* switched desktops or something? */
@@ -578,18 +586,24 @@ void focus_cycle(gboolean forward, gboolean linear,
         }
         ft = it->data;
         if (valid_focus_target(ft)) {
-            if (ft != focus_cycle_target) { /* prevents flicker */
+            if (interactive) {
+                if (ft != focus_cycle_target) { /* prevents flicker */
+                    focus_cycle_target = ft;
+                    focus_cycle_draw_indicator();
+                }
+                popup_cycle(ft, dialog);
+                return;
+            } else if (ft != focus_cycle_target) {
                 focus_cycle_target = ft;
-                focus_cycle_draw_indicator();
+                done = TRUE;
+                break;
             }
-            popup_cycle(ft, dialog);
-            return;
         }
     } while (it != start);
 
 done_cycle:
     if (done && focus_cycle_target)
-        client_activate(focus_cycle_target, FALSE);
+        client_activate(focus_cycle_target, FALSE, TRUE);
 
     t = NULL;
     first = NULL;
@@ -597,18 +611,23 @@ done_cycle:
     g_list_free(order);
     order = NULL;
 
-    focus_cycle_draw_indicator();
-    popup_cycle(ft, FALSE);
+    if (interactive) {
+        focus_cycle_draw_indicator();
+        popup_cycle(ft, FALSE);
+    }
 
     return;
 }
 
-void focus_directional_cycle(ObDirection dir,
+void focus_directional_cycle(ObDirection dir, gboolean interactive,
                              gboolean dialog, gboolean done, gboolean cancel)
 {
     static ObClient *first = NULL;
     ObClient *ft = NULL;
 
+    if (!interactive)
+        return;
+
     if (cancel) {
         focus_cycle_target = NULL;
         goto done_cycle;
@@ -646,7 +665,7 @@ void focus_directional_cycle(ObDirection dir,
 
 done_cycle:
     if (done && focus_cycle_target)
-        client_activate(focus_cycle_target, FALSE);
+        client_activate(focus_cycle_target, FALSE, TRUE);
 
     first = NULL;
     focus_cycle_target = NULL;
@@ -733,7 +752,7 @@ static void to_bottom(ObClient *c, guint d)
         /* insert before first iconic window */
         for (it = focus_order[d];
              it && !((ObClient*)it->data)->iconic; it = g_list_next(it));
-        g_list_insert_before(focus_order[d], it, c);
+        focus_order[d] = g_list_insert_before(focus_order[d], it, c);
     }
 }