]> Dogcows Code - chaz/openbox/blobdiff - openbox/focus.c
oh, 2 things in this commit..
[chaz/openbox] / openbox / focus.c
index 59e07f5e19ee2659206a78d947befa1f3ca3723c..3fba876bf1fce4d03f4ec488f07d995fd1454d32 100644 (file)
@@ -1,7 +1,8 @@
 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
 
    focus.c for the Openbox window manager
-   Copyright (c) 2003        Ben Jansens
+   Copyright (c) 2006        Mikael Magnusson
+   Copyright (c) 2003-2007   Dana Jansens
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -49,23 +50,24 @@ struct {
 } focus_indicator;
 
 RrAppearance *a_focus_indicator;
-RrColor *color_black;
 RrColor *color_white;
 
 static ObIconPopup *focus_cycle_popup;
 
 static void focus_cycle_destructor(ObClient *client, gpointer data)
 {
-    /* end cycling if the target disappears */
+    /* end cycling if the target disappears. CurrentTime is fine, time won't
+       be used
+    */
     if (focus_cycle_target == client)
-        focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE);
+        focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, CurrentTime);
 }
 
-static Window createWindow(Window parent, unsigned long mask,
-                          XSetWindowAttributes *attrib)
+static Window createWindow(Window parent, gulong mask,
+                           XSetWindowAttributes *attrib)
 {
     return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
-                        RrDepth(ob_rr_inst), InputOutput,
+                         RrDepth(ob_rr_inst), InputOutput,
                          RrVisual(ob_rr_inst), mask, attrib);
                        
 }
@@ -107,7 +109,6 @@ void focus_startup(gboolean reconfig)
         stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.right));
         stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.bottom));
 
-        color_black = RrColorNew(ob_rr_inst, 0, 0, 0);
         color_white = RrColorNew(ob_rr_inst, 0xff, 0xff, 0xff);
 
         a_focus_indicator = RrAppearanceNew(ob_rr_inst, 4);
@@ -140,9 +141,8 @@ 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_black);
         RrColorFree(color_white);
 
         RrAppearanceFree(a_focus_indicator);
@@ -183,13 +183,15 @@ 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. */
+    /* in the middle of cycling..? kill it. CurrentTime is fine, time won't
+       be used.
+    */
     if (focus_cycle_target)
-        focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE);
+        focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, CurrentTime);
 
     old = focus_client;
     focus_client = client;
@@ -203,21 +205,30 @@ void focus_set_client(ObClient *client)
         active = client ? client->window : None;
         PROP_SET32(RootWindow(ob_display, ob_screen),
                    net_active_window, window, active);
+
+        /* remove hiliting from the window when it gets focused */
+        if (client != NULL)
+            client_hilite(client, FALSE);
     }
 }
 
 /* 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)
+static ObClient *find_transient_recursive(ObClient *c, ObClient *top,
+                                          ObClient *skip)
 {
     GSList *it;
     ObClient *ret;
 
-    for (it = c->transients; it; it = it->next) {
+    for (it = c->transients; it; it = g_slist_next(it)) {
         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;
+        if (ret && ret != skip && client_normal(ret) &&
+            client_can_focus(ret) && client_validate(ret))
+            return ret;
+        if (it->data != skip && client_normal(it->data) &&
+            client_can_focus(it->data) && client_validate(it->data))
+            return it->data;
     }
     return NULL;
 }
@@ -237,54 +248,65 @@ static ObClient* focus_fallback_transient(ObClient *top, ObClient *old)
         return NULL;
 }
 
-ObClient* focus_fallback_target(ObFocusFallbackType type)
+ObClient* focus_fallback_target(gboolean allow_refocus)
 {
     GList *it;
-    ObClient *old = NULL;
+    ObClient *old;
     ObClient *target = NULL;
 
     old = focus_client;
 
-    if (type == OB_FOCUS_FALLBACK_UNFOCUSING && old) {
-        if (old->transient_for) {
-            gboolean trans = FALSE;
-
-            if (!config_focus_follow)
-                trans = TRUE;
-            else {
-                if ((target = client_under_pointer()) &&
-                    client_search_transient
-                    (client_search_top_transient(target), old))
+    if (!allow_refocus && old && old->transient_for) {
+        gboolean trans = FALSE;
+
+        if (!config_focus_follow || config_focus_last)
+            trans = TRUE;
+        else if ((target = client_under_pointer()) &&
+                 client_search_transient
+                 (client_search_top_parent(target), old))
+            trans = TRUE;
+
+        /* try for transient relations */
+        if (trans) {
+            if (old->transient_for == OB_TRAN_GROUP) {
+                for (it = focus_order[screen_desktop]; it;
+                     it = g_list_next(it))
                 {
-                    trans = TRUE;
-                }
-            }
-
-            /* try for transient relations */
-            if (trans) {
-                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 ((target =
-                                     focus_fallback_transient(sit->data, old)))
-                                    return target;
+                    GSList *sit;
+
+                    for (sit = old->group->members; sit;
+                         sit = g_slist_next(sit))
+                    {
+                        if (sit->data == it->data)
+                            if ((target =
+                                 focus_fallback_transient(sit->data, old)))
+                            {
+                                ob_debug("found in transient #1\n");
+                                return target;
+                            }
                     }
-                } else {
-                    if ((target =
-                         focus_fallback_transient(old->transient_for, old)))
-                        return target;
+                }
+            } else {
+                if ((target =
+                     focus_fallback_transient(old->transient_for, old)))
+                {
+                    ob_debug("found in transient #2\n");
+                    return target;
                 }
             }
         }
     }
 
-    if (config_focus_follow) {
+    ob_debug("trying pointer stuff\n");
+    if (config_focus_follow && !config_focus_last)
+    {
         if ((target = client_under_pointer()))
-            if (client_normal(target) && client_can_focus(target))
-                return target;
+            if (allow_refocus || target != old)
+                if (client_normal(target) && client_can_focus(target) &&
+                    client_validate(target)) {
+                    ob_debug("found in pointer stuff\n");
+                    return target;
+                }
     }
 
 #if 0
@@ -292,8 +314,8 @@ ObClient* focus_fallback_target(ObFocusFallbackType type)
         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)
+            for (it = focus_order[screen_desktop]; it; it = g_list_next(it))
+                for (sit = old->group->members; sit; sit = g_slist_next(sit))
                     if (sit->data == it->data)
                         if (sit->data != old && client_normal(sit->data))
                             if (client_can_focus(sit->data))
@@ -301,15 +323,25 @@ ObClient* focus_fallback_target(ObFocusFallbackType type)
         }
 #endif
 
-    for (it = focus_order[screen_desktop]; it != NULL; it = it->next)
-        if (type != OB_FOCUS_FALLBACK_UNFOCUSING || it->data != old)
-            if (client_normal(it->data) && client_can_focus(it->data))
+    ob_debug("trying  the focus order\n");
+    for (it = focus_order[screen_desktop]; it; it = g_list_next(it))
+        if (allow_refocus || it->data != old)
+            if (client_normal(it->data) && client_can_focus(it->data) &&
+                client_validate(it->data))
+            {
+                ob_debug("found in focus order\n");
                 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;
 }
 
-void focus_fallback(ObFocusFallbackType type)
+void focus_fallback(gboolean allow_refocus)
 {
     ObClient *new;
 
@@ -319,7 +351,7 @@ void focus_fallback(ObFocusFallbackType type)
     */
     focus_set_client(NULL);
 
-    if ((new = focus_fallback_target(type)))
+    if ((new = focus_fallback_target(allow_refocus)))
         client_focus(new);
 }
 
@@ -330,7 +362,7 @@ static void popup_cycle(ObClient *c, gboolean show)
     } else {
         Rect *a;
         ObClient *p = c;
-        char *title;
+        gchar *title = NULL;
 
         a = screen_physical_area_monitor(0);
         icon_popup_position(focus_cycle_popup, CenterGravity,
@@ -347,14 +379,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 = NULL;
-        else
-            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)),
@@ -376,12 +407,13 @@ void focus_cycle_draw_indicator()
               frame_adjust_focus(focus_cycle_target->frame, FALSE);
           frame_adjust_focus(focus_cycle_target->frame, TRUE);
         */
-        int x, y, w, h;
-        int wt, wl, wr, wb;
+        gint x, y, w, h;
+        gint wt, wl, wr, wb;
 
         wt = wl = wr = wb = MAX(3,
-                                ob_rr_theme->handle_height +
-                                ob_rr_theme->bwidth * 2);
+                                MAX(1, MAX(ob_rr_theme->paddingx,
+                                           ob_rr_theme->paddingy)) * 2 +
+                                ob_rr_theme->fbwidth * 2);
 
         x = focus_cycle_target->frame->area.x;
         y = focus_cycle_target->frame->area.y;
@@ -502,20 +534,36 @@ static gboolean valid_focus_target(ObClient *ft)
        focus an iconic window, but we want to be able to, so we just check
        if the focus flags on the window allow it, and its on the current
        desktop */
-    return ((ft->type == OB_CLIENT_TYPE_NORMAL ||
-             ft->type == OB_CLIENT_TYPE_DIALOG ||
-             (!client_has_group_siblings(ft) &&
-              (ft->type == OB_CLIENT_TYPE_TOOLBAR ||
-               ft->type == OB_CLIENT_TYPE_MENU ||
-               ft->type == OB_CLIENT_TYPE_UTILITY))) &&
-            !ft->transients &&
-            ((ft->can_focus || ft->focus_notify) &&
-             !ft->skip_taskbar &&
-             (ft->desktop == screen_desktop || ft->desktop == DESKTOP_ALL)));
+    if ((ft->type == OB_CLIENT_TYPE_NORMAL ||
+         ft->type == OB_CLIENT_TYPE_DIALOG ||
+         (!client_has_group_siblings(ft) &&
+          (ft->type == OB_CLIENT_TYPE_TOOLBAR ||
+           ft->type == OB_CLIENT_TYPE_MENU ||
+           ft->type == OB_CLIENT_TYPE_UTILITY))) &&
+        ((ft->can_focus || ft->focus_notify) &&
+         !ft->skip_pager &&
+         (ft->desktop == screen_desktop || ft->desktop == DESKTOP_ALL)) &&
+        ft == client_focus_target(ft))
+        return TRUE;
+/*
+    {
+        GSList *it;
+
+        for (it = ft->transients; it; it = g_slist_next(it)) {
+            ObClient *c = it->data;
+
+            if (c->frame->visible)
+                return FALSE;
+        }
+        return TRUE;
+    }
+*/
+
+    return FALSE;
 }
 
-void focus_cycle(gboolean forward, gboolean linear,
-                 gboolean dialog, gboolean done, gboolean cancel)
+void focus_cycle(gboolean forward, gboolean linear, gboolean interactive,
+                 gboolean dialog, gboolean done, gboolean cancel, Time time)
 {
     static ObClient *first = NULL;
     static ObClient *t = NULL;
@@ -523,21 +571,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 && dialog) {
-        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? */
@@ -554,18 +607,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, time);
 
     t = NULL;
     first = NULL;
@@ -573,24 +632,29 @@ 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,
-                             gboolean dialog, gboolean done, gboolean cancel)
+void focus_directional_cycle(ObDirection dir, gboolean interactive,
+                             gboolean dialog, gboolean done, gboolean cancel,
+                             Time time)
 {
     static ObClient *first = NULL;
     ObClient *ft = NULL;
 
+    if (!interactive)
+        return;
+
     if (cancel) {
         focus_cycle_target = NULL;
         goto done_cycle;
-    } else if (done && dialog) {
+    } else if (done)
         goto done_cycle;
-    }
 
     if (!focus_order[screen_desktop])
         goto done_cycle;
@@ -623,7 +687,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, time);
 
     first = NULL;
     focus_cycle_target = NULL;
@@ -644,16 +708,19 @@ void focus_order_add_new(ObClient *c)
         d = c->desktop;
         if (d == DESKTOP_ALL) {
             for (i = 0; i < screen_num_desktops; ++i) {
+                g_assert(!g_list_find(focus_order[i], c));
                 if (focus_order[i] && ((ObClient*)focus_order[i]->data)->iconic)
                     focus_order[i] = g_list_insert(focus_order[i], c, 0);
                 else
                     focus_order[i] = g_list_insert(focus_order[i], c, 1);
             }
-        } else
-             if (focus_order[d] && ((ObClient*)focus_order[d]->data)->iconic)
+        } else {
+            g_assert(!g_list_find(focus_order[d], c));
+            if (focus_order[d] && ((ObClient*)focus_order[d]->data)->iconic)
                 focus_order[d] = g_list_insert(focus_order[d], c, 0);
             else
                 focus_order[d] = g_list_insert(focus_order[d], c, 1);
+        }
     }
 }
 
@@ -679,7 +746,7 @@ static void to_top(ObClient *c, guint d)
 
         /* insert before first iconic window */
         for (it = focus_order[d];
-             it && !((ObClient*)it->data)->iconic; it = it->next);
+             it && !((ObClient*)it->data)->iconic; it = g_list_next(it));
         focus_order[d] = g_list_insert_before(focus_order[d], it, c);
     }
 }
@@ -706,8 +773,8 @@ static void to_bottom(ObClient *c, guint d)
 
         /* insert before first iconic window */
         for (it = focus_order[d];
-             it && !((ObClient*)it->data)->iconic; it = it->next);
-        g_list_insert_before(focus_order[d], it, c);
+             it && !((ObClient*)it->data)->iconic; it = g_list_next(it));
+        focus_order[d] = g_list_insert_before(focus_order[d], it, c);
     }
 }
 
This page took 0.037173 seconds and 4 git commands to generate.