]> Dogcows Code - chaz/openbox/blobdiff - openbox/focus.c
provide function to tell if a client has any group siblings
[chaz/openbox] / openbox / focus.c
index 16ab571e9c1928fbaa48fc3601d3e58ee2e41efc..44f8edb213c89cef51313efa7509ce133643c231 100644 (file)
 #include "focus.h"
 #include "stacking.h"
 #include "popup.h"
+#include "render/render.h"
 
 #include <X11/Xlib.h>
 #include <glib.h>
 #include <assert.h>
 
-ObClient *focus_client;
+ObClient *focus_client, *focus_hilite;
 GList **focus_order; /* these lists are created when screen_startup
                         sets the number of desktops */
 ObClient *focus_cycle_target;
 
+struct {
+    InternalWindow top;
+    InternalWindow left;
+    InternalWindow right;
+    InternalWindow bottom;
+} 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)
@@ -49,15 +61,67 @@ static void focus_cycle_destructor(ObClient *client, gpointer data)
         focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE);
 }
 
+static Window createWindow(Window parent, unsigned long mask,
+                          XSetWindowAttributes *attrib)
+{
+    return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
+                        RrDepth(ob_rr_inst), InputOutput,
+                         RrVisual(ob_rr_inst), mask, attrib);
+                       
+}
+
 void focus_startup(gboolean reconfig)
 {
     focus_cycle_popup = icon_popup_new(TRUE);
 
     if (!reconfig) {
+        XSetWindowAttributes attr;
+
         client_add_destructor(focus_cycle_destructor, NULL);
 
         /* start with nothing focused */
         focus_set_client(NULL);
+
+        focus_indicator.top.obwin.type = Window_Internal;
+        focus_indicator.left.obwin.type = Window_Internal;
+        focus_indicator.right.obwin.type = Window_Internal;
+        focus_indicator.bottom.obwin.type = Window_Internal;
+
+        attr.override_redirect = True;
+        attr.background_pixel = BlackPixel(ob_display, ob_screen);
+        focus_indicator.top.win =
+            createWindow(RootWindow(ob_display, ob_screen),
+                         CWOverrideRedirect | CWBackPixel, &attr);
+        focus_indicator.left.win =
+            createWindow(RootWindow(ob_display, ob_screen),
+                         CWOverrideRedirect | CWBackPixel, &attr);
+        focus_indicator.right.win =
+            createWindow(RootWindow(ob_display, ob_screen),
+                         CWOverrideRedirect | CWBackPixel, &attr);
+        focus_indicator.bottom.win =
+            createWindow(RootWindow(ob_display, ob_screen),
+                         CWOverrideRedirect | CWBackPixel, &attr);
+
+        stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.top));
+        stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.left));
+        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);
+        a_focus_indicator->surface.grad = RR_SURFACE_SOLID;
+        a_focus_indicator->surface.relief = RR_RELIEF_FLAT;
+        a_focus_indicator->surface.primary = color_black;
+        a_focus_indicator->texture[0].type = RR_TEXTURE_LINE_ART;
+        a_focus_indicator->texture[0].data.lineart.color = color_white;
+        a_focus_indicator->texture[1].type = RR_TEXTURE_LINE_ART;
+        a_focus_indicator->texture[1].data.lineart.color = color_white;
+        a_focus_indicator->texture[2].type = RR_TEXTURE_LINE_ART;
+        a_focus_indicator->texture[2].data.lineart.color = color_white;
+        a_focus_indicator->texture[3].type = RR_TEXTURE_LINE_ART;
+        a_focus_indicator->texture[3].data.lineart.color = color_white;
     }
 }
 
@@ -76,6 +140,16 @@ void focus_shutdown(gboolean reconfig)
 
         /* reset focus to root */
         XSetInputFocus(ob_display, PointerRoot, RevertToNone, event_lasttime);
+
+        RrColorFree(color_black);
+        RrColorFree(color_white);
+
+        RrAppearanceFree(a_focus_indicator);
+
+        XDestroyWindow(ob_display, focus_indicator.top.win);
+        XDestroyWindow(ob_display, focus_indicator.left.win);
+        XDestroyWindow(ob_display, focus_indicator.right.win);
+        XDestroyWindow(ob_display, focus_indicator.bottom.win);
     }
 }
 
@@ -131,15 +205,6 @@ void focus_set_client(ObClient *client)
     }
 }
 
-static gboolean focus_under_pointer()
-{
-    ObClient *c;
-
-    if ((c = client_under_pointer()))
-        return client_normal(c) && client_focus(c);
-    return 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)
@@ -156,31 +221,29 @@ static ObClient *find_transient_recursive(ObClient *c, ObClient *top, ObClient *
     return NULL;
 }
 
-static gboolean focus_fallback_transient(ObClient *top, ObClient *old)
+static ObClient* focus_fallback_transient(ObClient *top, ObClient *old)
 {
     ObClient *target = find_transient_recursive(top, top, old);
     if (!target) {
         /* make sure client_normal is true always */
         if (!client_normal(top))
-            return FALSE;
+            return NULL;
         target = top; /* no transient, keep the top */
     }
-    return client_focus(target);
+    if (client_can_focus(target))
+        return target;
+    else
+        return NULL;
 }
 
-void focus_fallback(ObFocusFallbackType type)
+ObClient* focus_fallback_target(ObFocusFallbackType type)
 {
     GList *it;
     ObClient *old = NULL;
+    ObClient *target = 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 == OB_FOCUS_FALLBACK_UNFOCUSING && old) {
         if (old->transient_for) {
             gboolean trans = FALSE;
@@ -188,16 +251,14 @@ void focus_fallback(ObFocusFallbackType type)
             if (!config_focus_follow)
                 trans = TRUE;
             else {
-                ObClient *c;
-
-                if ((c = client_under_pointer()) &&
-                    client_search_transient(client_search_top_transient(c),
-                                            old))
+                if ((target = client_under_pointer()) &&
+                    client_search_transient
+                    (client_search_top_transient(target), old))
+                {
                     trans = TRUE;
+                }
             }
 
-            g_message("trans %d", trans);
-
             /* try for transient relations */
             if (trans) {
                 if (old->transient_for == OB_TRAN_GROUP) {
@@ -206,20 +267,24 @@ void focus_fallback(ObFocusFallbackType type)
 
                         for (sit = old->group->members; sit; sit = sit->next)
                             if (sit->data == it->data)
-                                if (focus_fallback_transient(sit->data, old))
-                                    return;
+                                if ((target =
+                                     focus_fallback_transient(sit->data, old)))
+                                    return target;
                     }
                 } else {
-                    if (focus_fallback_transient(old->transient_for, old))
-                        return;
+                    if ((target =
+                         focus_fallback_transient(old->transient_for, old)))
+                        return target;
                 }
             }
         }
     }
 
-    if (config_focus_follow)
-        if (focus_under_pointer())
-            return;
+    if (config_focus_follow) {
+        if ((target = client_under_pointer()))
+            if (client_normal(target) && client_can_focus(target))
+                return target;
+    }
 
 #if 0
         /* try for group relations */
@@ -230,23 +295,31 @@ void focus_fallback(ObFocusFallbackType type)
                 for (sit = old->group->members; sit; sit = sit->next)
                     if (sit->data == it->data)
                         if (sit->data != old && client_normal(sit->data))
-                            if (client_can_focus(sit->data)) {
-                                gboolean r = client_focus(sit->data);
-                                assert(r);
-                                return;
-                            }
+                            if (client_can_focus(sit->data))
+                                return sit->data;
         }
 #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)) {
-                gboolean r = client_focus(it->data);
-                assert(r);
-                return;
-            }
+            if (client_normal(it->data) && client_can_focus(it->data))
+                return it->data;
+
+    return NULL;
+}
+
+void focus_fallback(ObFocusFallbackType type)
+{
+    ObClient *new;
 
-    /* nothing to focus, and already set it to none above */
+    /* 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 ((new = focus_fallback_target(type)))
+        client_focus(new);
 }
 
 static void popup_cycle(ObClient *c, gboolean show)
@@ -289,6 +362,132 @@ static void popup_cycle(ObClient *c, gboolean show)
     }
 }
 
+void focus_cycle_draw_indicator()
+{
+    if (!focus_cycle_target) {
+        XUnmapWindow(ob_display, focus_indicator.top.win);
+        XUnmapWindow(ob_display, focus_indicator.left.win);
+        XUnmapWindow(ob_display, focus_indicator.right.win);
+        XUnmapWindow(ob_display, focus_indicator.bottom.win);
+    } else {
+        /*
+          if (focus_cycle_target)
+              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;
+
+        wt = wl = wr = wb = MAX(5, ob_rr_theme->handle_height);
+
+        x = focus_cycle_target->frame->area.x;
+        y = focus_cycle_target->frame->area.y;
+        w = focus_cycle_target->frame->area.width;
+        h = wt;
+
+        XMoveResizeWindow(ob_display, focus_indicator.top.win,
+                          x, y, w, h);
+        a_focus_indicator->texture[0].data.lineart.x1 = 0;
+        a_focus_indicator->texture[0].data.lineart.y1 = h-1;
+        a_focus_indicator->texture[0].data.lineart.x2 = 0;
+        a_focus_indicator->texture[0].data.lineart.y2 = 0;
+        a_focus_indicator->texture[1].data.lineart.x1 = 0;
+        a_focus_indicator->texture[1].data.lineart.y1 = 0;
+        a_focus_indicator->texture[1].data.lineart.x2 = w-1;
+        a_focus_indicator->texture[1].data.lineart.y2 = 0;
+        a_focus_indicator->texture[2].data.lineart.x1 = w-1;
+        a_focus_indicator->texture[2].data.lineart.y1 = 0;
+        a_focus_indicator->texture[2].data.lineart.x2 = w-1;
+        a_focus_indicator->texture[2].data.lineart.y2 = h-1;
+        a_focus_indicator->texture[3].data.lineart.x1 = (wl-1);
+        a_focus_indicator->texture[3].data.lineart.y1 = h-1;
+        a_focus_indicator->texture[3].data.lineart.x2 = w - wr;
+        a_focus_indicator->texture[3].data.lineart.y2 = h-1;
+        RrPaint(a_focus_indicator, focus_indicator.top.win,
+                w, h);
+
+        x = focus_cycle_target->frame->area.x;
+        y = focus_cycle_target->frame->area.y;
+        w = wl;
+        h = focus_cycle_target->frame->area.height;
+
+        XMoveResizeWindow(ob_display, focus_indicator.left.win,
+                          x, y, w, h);
+        a_focus_indicator->texture[0].data.lineart.x1 = w-1;
+        a_focus_indicator->texture[0].data.lineart.y1 = 0;
+        a_focus_indicator->texture[0].data.lineart.x2 = 0;
+        a_focus_indicator->texture[0].data.lineart.y2 = 0;
+        a_focus_indicator->texture[1].data.lineart.x1 = 0;
+        a_focus_indicator->texture[1].data.lineart.y1 = 0;
+        a_focus_indicator->texture[1].data.lineart.x2 = 0;
+        a_focus_indicator->texture[1].data.lineart.y2 = h-1;
+        a_focus_indicator->texture[2].data.lineart.x1 = 0;
+        a_focus_indicator->texture[2].data.lineart.y1 = h-1;
+        a_focus_indicator->texture[2].data.lineart.x2 = w-1;
+        a_focus_indicator->texture[2].data.lineart.y2 = h-1;
+        a_focus_indicator->texture[3].data.lineart.x1 = w-1;
+        a_focus_indicator->texture[3].data.lineart.y1 = wt-1;
+        a_focus_indicator->texture[3].data.lineart.x2 = w-1;
+        a_focus_indicator->texture[3].data.lineart.y2 = h - wb;
+        RrPaint(a_focus_indicator, focus_indicator.left.win,
+                w, h);
+
+        x = focus_cycle_target->frame->area.x +
+            focus_cycle_target->frame->area.width - wr;
+        y = focus_cycle_target->frame->area.y;
+        w = wr;
+        h = focus_cycle_target->frame->area.height ;
+
+        XMoveResizeWindow(ob_display, focus_indicator.right.win,
+                          x, y, w, h);
+        a_focus_indicator->texture[0].data.lineart.x1 = 0;
+        a_focus_indicator->texture[0].data.lineart.y1 = 0;
+        a_focus_indicator->texture[0].data.lineart.x2 = w-1;
+        a_focus_indicator->texture[0].data.lineart.y2 = 0;
+        a_focus_indicator->texture[1].data.lineart.x1 = w-1;
+        a_focus_indicator->texture[1].data.lineart.y1 = 0;
+        a_focus_indicator->texture[1].data.lineart.x2 = w-1;
+        a_focus_indicator->texture[1].data.lineart.y2 = h-1;
+        a_focus_indicator->texture[2].data.lineart.x1 = w-1;
+        a_focus_indicator->texture[2].data.lineart.y1 = h-1;
+        a_focus_indicator->texture[2].data.lineart.x2 = 0;
+        a_focus_indicator->texture[2].data.lineart.y2 = h-1;
+        a_focus_indicator->texture[3].data.lineart.x1 = 0;
+        a_focus_indicator->texture[3].data.lineart.y1 = wt-1;
+        a_focus_indicator->texture[3].data.lineart.x2 = 0;
+        a_focus_indicator->texture[3].data.lineart.y2 = h - wb;
+        RrPaint(a_focus_indicator, focus_indicator.right.win,
+                w, h);
+
+        x = focus_cycle_target->frame->area.x;
+        y = focus_cycle_target->frame->area.y +
+            focus_cycle_target->frame->area.height - wb;
+        w = focus_cycle_target->frame->area.width;
+        h = wb;
+
+        XMoveResizeWindow(ob_display, focus_indicator.bottom.win,
+                          x, y, w, h);
+        a_focus_indicator->texture[0].data.lineart.x1 = 0;
+        a_focus_indicator->texture[0].data.lineart.y1 = 0;
+        a_focus_indicator->texture[0].data.lineart.x2 = 0;
+        a_focus_indicator->texture[0].data.lineart.y2 = h-1;
+        a_focus_indicator->texture[1].data.lineart.x1 = 0;
+        a_focus_indicator->texture[1].data.lineart.y1 = h-1;
+        a_focus_indicator->texture[1].data.lineart.x2 = w-1;
+        a_focus_indicator->texture[1].data.lineart.y2 = h-1;
+        a_focus_indicator->texture[2].data.lineart.x1 = w-1;
+        a_focus_indicator->texture[2].data.lineart.y1 = h-1;
+        a_focus_indicator->texture[2].data.lineart.x2 = w-1;
+        a_focus_indicator->texture[2].data.lineart.y2 = 0;
+        a_focus_indicator->texture[3].data.lineart.x1 = wl-1;
+        a_focus_indicator->texture[3].data.lineart.y1 = 0;
+        a_focus_indicator->texture[3].data.lineart.x2 = w - wr;
+        a_focus_indicator->texture[3].data.lineart.y2 = 0;
+        RrPaint(a_focus_indicator, focus_indicator.bottom.win,
+                w, h);
+    }
+}
+
 static gboolean valid_focus_target(ObClient *ft)
 {
     /* we don't use client_can_focus here, because that doesn't let you
@@ -311,10 +510,12 @@ void focus_cycle(gboolean forward, gboolean linear,
     ObClient *ft = NULL;
 
     if (cancel) {
+        /*
         if (focus_cycle_target)
             frame_adjust_focus(focus_cycle_target->frame, FALSE);
         if (focus_client)
             frame_adjust_focus(focus_client->frame, TRUE);
+        */
         focus_cycle_target = NULL;
         goto done_cycle;
     } else if (done && dialog) {
@@ -346,10 +547,8 @@ void focus_cycle(gboolean forward, gboolean linear,
         ft = it->data;
         if (valid_focus_target(ft)) {
             if (ft != focus_cycle_target) { /* prevents flicker */
-                if (focus_cycle_target)
-                    frame_adjust_focus(focus_cycle_target->frame, FALSE);
                 focus_cycle_target = ft;
-                frame_adjust_focus(focus_cycle_target->frame, TRUE);
+                focus_cycle_draw_indicator();
             }
             popup_cycle(ft, dialog);
             return;
@@ -366,6 +565,7 @@ done_cycle:
     g_list_free(order);
     order = NULL;
 
+    focus_cycle_draw_indicator();
     popup_cycle(ft, FALSE);
 
     return;
This page took 0.037822 seconds and 4 git commands to generate.