]> Dogcows Code - chaz/openbox/blobdiff - openbox/focus.c
popups fixes. if the text for the popup is empty now, there wont be extra padding...
[chaz/openbox] / openbox / focus.c
index 755b6ceabe787f8f3f94f86a042d4d25b361f4da..5d9e0fe4a294078ceed942bdc7bcddc207dc7278 100644 (file)
@@ -55,14 +55,10 @@ RrColor *color_white;
 
 static ObIconPopup *focus_cycle_popup;
 
-static void focus_cycle_destructor(ObClient *client, gpointer data)
-{
-    /* 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, TRUE, TRUE, TRUE);
-}
+static gboolean valid_focus_target(ObClient *ft,
+                                   gboolean all_desktops,
+                                   gboolean dock_windows);
+static void focus_cycle_destructor(ObClient *client, gpointer data);
 
 static Window createWindow(Window parent, gulong mask,
                            XSetWindowAttributes *attrib)
@@ -289,38 +285,110 @@ void focus_nothing()
                    event_curtime);
 }
 
-static void popup_cycle(ObClient *c, gboolean show)
+static gchar *popup_get_name(ObClient *c, ObClient **nametarget)
 {
+    ObClient *p;
+    gchar *title = NULL;
+    const gchar *desk = NULL;
+    gchar *ret;
+
+    /* find our highest direct parent, including non-normal windows */
+    for (p = c; p->transient_for && p->transient_for != OB_TRAN_GROUP;
+         p = p->transient_for);
+    if (nametarget) *nametarget = p;
+
+    if (c->desktop != DESKTOP_ALL && c->desktop != screen_desktop)
+        desk = screen_desktop_names[c->desktop];
+
+    /* use the transient's parent's title/icon if we don't have one */
+    if (p != c && !strcmp("", (c->iconic ? c->icon_title : c->title)))
+        title = g_strdup(p->iconic ? p->icon_title : p->title);
+
+    if (title == NULL)
+        title = g_strdup(c->iconic ? c->icon_title : c->title);
+
+    if (desk)
+        ret = g_strdup_printf("%s [%s]", title, desk);
+    else {
+        ret = title;
+        title = NULL;
+    }
+    g_free(title);
+
+    return ret;
+}
+
+static void popup_cycle(ObClient *c, gboolean show,
+                        gboolean all_desktops, gboolean dock_windows)
+{
+    gchar *showtext = NULL;
+    ObClient *showtarget;
+
     if (!show) {
         icon_popup_hide(focus_cycle_popup);
-    } else {
+        return;
+    }
+
+    /* do this stuff only when the dialog is first showing */
+    if (!focus_cycle_popup->popup->mapped &&
+        !focus_cycle_popup->popup->delay_mapped)
+    {
         Rect *a;
-        ObClient *p = c;
-        gchar *title = NULL;
+        gchar **names;
+        GList *targets = NULL, *it;
+        gint n = 0, i;
 
+        /* position the popup */
         a = screen_physical_area_monitor(0);
         icon_popup_position(focus_cycle_popup, CenterGravity,
                             a->x + a->width / 2, a->y + a->height / 2);
-        icon_popup_width(focus_cycle_popup, MAX(a->width/3, POPUP_WIDTH));
         icon_popup_height(focus_cycle_popup, POPUP_HEIGHT);
+        icon_popup_min_width(focus_cycle_popup, POPUP_WIDTH);
+        icon_popup_max_width(focus_cycle_popup,
+                             MAX(a->width/3, POPUP_WIDTH));
 
-        /* use the transient's parent's title/icon */
-        while (p->transient_for && p->transient_for != OB_TRAN_GROUP)
-            p = p->transient_for;
 
-        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)),
-                        client_icon(p, 48, 48));
-        g_free(title);
+        /* make its width to be the width of all the possible titles */
+
+        /* build a list of all the valid focus targets */
+        for (it = focus_order; it; it = g_list_next(it)) {
+            ObClient *ft = it->data;
+            if (valid_focus_target(ft, all_desktops, dock_windows)) {
+                targets = g_list_prepend(targets, ft);
+                ++n;
+            }
+        }
+        /* make it null terminated so we can use g_strfreev */
+        names = g_new(char*, n+1);
+        for (it = targets, i = 0; it; it = g_list_next(it), ++i) {
+            ObClient *ft = it->data;
+            names[i] = popup_get_name(ft, &showtarget);
+
+            /* little optimization.. save this text so we dont have to get it
+               again */
+            if (ft == c)
+                showtext = g_strdup(names[i]);
+        }
+        names[n] = NULL;
+
+        icon_popup_text_width_to_strings(focus_cycle_popup, names, n);
+        g_strfreev(names);
     }
+
+
+    if (!showtext) showtext = popup_get_name(c, &showtarget);
+    icon_popup_show(focus_cycle_popup, showtext,
+                    client_icon(showtarget, 48, 48));
+    g_free(showtext);
+}
+
+static void focus_cycle_destructor(ObClient *client, gpointer data)
+{
+    /* 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, TRUE, TRUE, TRUE);
 }
 
 void focus_cycle_draw_indicator()
@@ -462,47 +530,45 @@ static gboolean valid_focus_target(ObClient *ft,
                                    gboolean dock_windows)
 {
     gboolean ok = FALSE;
-    /* we don't use client_can_focus here, because that doesn't let you
-       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 */
+
+    /* 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)
-        ok = ft->type == OB_CLIENT_TYPE_DOCK;
+        ok = ok && ft->type == OB_CLIENT_TYPE_DOCK;
     else
-        ok = (ft->type == OB_CLIENT_TYPE_NORMAL ||
-              ft->type == OB_CLIENT_TYPE_DIALOG ||
-              ((ft->type == OB_CLIENT_TYPE_TOOLBAR ||
-                ft->type == OB_CLIENT_TYPE_MENU ||
-                ft->type == OB_CLIENT_TYPE_UTILITY) &&
-               /* let alt-tab go to these windows when a window in its group
-                  already has focus ... */
-               ((focus_client && ft->group == focus_client->group) ||
-                /* ... or if there are no application windows in its group */
-                !client_has_application_group_siblings(ft))));
-    ok = ok && (ft->can_focus || ft->focus_notify);
-    if (!dock_windows && /* use dock windows that skip taskbar too */
-        !(ft->type == OB_CLIENT_TYPE_TOOLBAR || /* also, if we actually are */
-          ft->type == OB_CLIENT_TYPE_MENU ||    /* being allowed to target */
-          ft->type == OB_CLIENT_TYPE_UTILITY))  /* one of these, don't let */
-        ok = ok && !ft->skip_taskbar;           /*  skip taskbar stop us */
-    if (!all_desktops)
-        ok = ok && (ft->desktop == screen_desktop ||
-                    ft->desktop == DESKTOP_ALL);
+        ok = ok && (ft->type == OB_CLIENT_TYPE_NORMAL ||
+                    ft->type == OB_CLIENT_TYPE_DIALOG ||
+                    ((ft->type == OB_CLIENT_TYPE_TOOLBAR ||
+                      ft->type == OB_CLIENT_TYPE_MENU ||
+                      ft->type == OB_CLIENT_TYPE_UTILITY) &&
+                     /* let alt-tab go to these windows when a window in its
+                        group already has focus ... */
+                     ((focus_client && ft->group == focus_client->group) ||
+                      /* ... or if there are no application windows in its
+                         group */
+                      !client_has_application_group_siblings(ft))));
+
+    /* 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;
-/*
-    {
-        GSList *it;
-
-        for (it = ft->transients; it; it = g_slist_next(it)) {
-            ObClient *c = it->data;
 
-            if (frame_visible(c->frame))
-                return FALSE;
-        }
-        return TRUE;
-    }
-*/
+    return ok;
 }
 
 void focus_cycle(gboolean forward, gboolean all_desktops,
@@ -557,7 +623,8 @@ void focus_cycle(gboolean forward, gboolean all_desktops,
                     focus_cycle_target = ft;
                     focus_cycle_draw_indicator();
                 }
-                popup_cycle(ft, dialog);
+                /* same arguments as valid_focus_target */
+                popup_cycle(ft, dialog, all_desktops, dock_windows);
                 return;
             } else if (ft != focus_cycle_target) {
                 focus_cycle_target = ft;
@@ -579,14 +646,14 @@ done_cycle:
 
     if (interactive) {
         focus_cycle_draw_indicator();
-        popup_cycle(ft, FALSE);
+        popup_cycle(ft, FALSE, FALSE, FALSE);
     }
 
     return;
 }
 
 /* this be mostly ripped from fvwm */
-ObClient *focus_find_directional(ObClient *c, ObDirection dir,
+static ObClient *focus_find_directional(ObClient *c, ObDirection dir,
                                  gboolean dock_windows) 
 {
     gint my_cx, my_cy, his_cx, his_cy;
@@ -728,7 +795,8 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows,
         }
     }
     if (focus_cycle_target) {
-        popup_cycle(focus_cycle_target, dialog);
+        /* same arguments as valid_focus_target */
+        popup_cycle(focus_cycle_target, dialog, FALSE, dock_windows);
         if (dialog)
             return;
     }
@@ -742,7 +810,7 @@ done_cycle:
     focus_cycle_target = NULL;
 
     focus_cycle_draw_indicator();
-    popup_cycle(ft, FALSE);
+    popup_cycle(ft, FALSE, FALSE, FALSE);
 
     return;
 }
This page took 0.030159 seconds and 4 git commands to generate.