]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
1. remove some old event handling that was not used at all. yay less bandwidth.
[chaz/openbox] / openbox / client.c
index 80bc8a394d91efafbda5a00e8a0b891f15d6c1c9..f5335c79a105e042584ff8c05b753b422db1a13f 100644 (file)
 #include "mouse.h"
 #include "render/render.h"
 
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
 #include <glib.h>
 #include <X11/Xutil.h>
 
@@ -56,10 +60,9 @@ typedef struct
     gpointer data;
 } Destructor;
 
-GList         *client_list           = NULL;
+GList            *client_list        = NULL;
 
 static GSList *client_destructors    = NULL;
-static Time    client_last_user_time = CurrentTime;
 
 static void client_get_all(ObClient *self);
 static void client_toggle_border(ObClient *self, gboolean show);
@@ -71,6 +74,7 @@ static void client_get_layer(ObClient *self);
 static void client_get_shaped(ObClient *self);
 static void client_get_mwm_hints(ObClient *self);
 static void client_get_gravity(ObClient *self);
+static void client_get_client_machine(ObClient *self);
 static void client_change_allowed_actions(ObClient *self);
 static void client_change_state(ObClient *self);
 static void client_change_wm_state(ObClient *self);
@@ -78,7 +82,6 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y);
 static void client_restore_session_state(ObClient *self);
 static void client_restore_session_stacking(ObClient *self);
 static ObAppSettings *client_get_settings_state(ObClient *self);
-static void client_unfocus(ObClient *self);
 
 void client_startup(gboolean reconfig)
 {
@@ -272,13 +275,14 @@ void client_manage(Window window)
     self->wmstate = WithdrawnState; /* make sure it gets updated first time */
     self->layer = -1;
     self->desktop = screen_num_desktops; /* always an invalid value */
-    self->user_time = client_last_user_time;
+    self->user_time = CurrentTime;
 
     client_get_all(self);
-    client_restore_session_state(self);
     /* per-app settings override stuff, and return the settings for other
        uses too */
     settings = client_get_settings_state(self);
+    /* the session should get the last say */
+    client_restore_session_state(self);
 
     client_calc_layer(self);
 
@@ -402,9 +406,12 @@ void client_manage(Window window)
     mouse_grab_for_client(self, TRUE);
 
     if (activate) {
+        guint32 last_time = focus_client ?
+            focus_client->user_time : CurrentTime;
+
         /* This is focus stealing prevention */
         ob_debug("Want to focus new window 0x%x with time %u (last time %u)\n",
-                 self->window, self->user_time, client_last_user_time);
+                 self->window, self->user_time, last_time);
 
         /* If a nothing at all, or a parent was focused, then focus this
            always
@@ -414,8 +421,8 @@ void client_manage(Window window)
         else
         {
             /* If time stamp is old, don't steal focus */
-            if (self->user_time &&
-                !event_time_after(self->user_time, client_last_user_time))
+            if (self->user_time && last_time &&
+                !event_time_after(self->user_time, last_time))
             {
                 activate = FALSE;
             }
@@ -435,7 +442,7 @@ void client_manage(Window window)
         } else {
             ob_debug("Focus stealing prevention activated for %s with time %u "
                      "(last time %u)\n",
-                     self->title, self->user_time, client_last_user_time);
+                     self->title, self->user_time, last_time);
             /* if the client isn't focused, then hilite it so the user
                knows it is there */
             client_hilite(self, TRUE);
@@ -455,7 +462,7 @@ void client_manage(Window window)
     /* this has to happen before we try focus the window, but we want it to
        happen after the client's stacking has been determined or it looks bad
     */
-    client_showhide(self);
+    client_show(self);
 
     /* use client_focus instead of client_activate cuz client_activate does
        stuff like switch desktops etc and I'm not interested in all that when
@@ -469,7 +476,7 @@ void client_manage(Window window)
         client_focus(self);
     }
 
-    /* client_activate does this but we aret using it so we have to do it
+    /* client_activate does this but we aren't using it so we have to do it
        here as well */
     if (screen_showing_desktop)
         screen_show_desktop(FALSE);
@@ -504,38 +511,28 @@ void client_unmanage(ObClient *self)
 
     g_assert(self != NULL);
 
-    /* update the focus lists */
-    focus_order_remove(self);
-
-    if (focus_client == self) {
-        XEvent e;
-
-        /* focus the last focused window on the desktop, and ignore enter
-           events from the unmap so it doesnt mess with the focus */
-        while (XCheckTypedEvent(ob_display, EnterNotify, &e));
-        /* remove these flags so we don't end up getting focused in the
-           fallback! */
-        self->can_focus = FALSE;
-        self->focus_notify = FALSE;
-        self->modal = FALSE;
-        client_unfocus(self);
-    }
-
-    /* potentially fix focusLast */
-    if (config_focus_last)
-        grab_pointer(TRUE, OB_CURSOR_NONE);
+    /* we dont want events no more. do this before hiding the frame so we
+       don't generate more events */
+    XSelectInput(ob_display, self->window, NoEventMask);
 
     frame_hide(self->frame);
+    /* flush to send the hide to the server quickly */
     XFlush(ob_display);
 
+    if (focus_client == self) {
+        /* ignore enter events from the unmap so it doesnt mess with the focus
+         */
+        event_ignore_queued_enters();
+    }
+
     keyboard_grab_for_client(self, FALSE);
     mouse_grab_for_client(self, FALSE);
 
     /* remove the window from our save set */
     XChangeSaveSet(ob_display, self->window, SetModeDelete);
 
-    /* we dont want events no more */
-    XSelectInput(ob_display, self->window, NoEventMask);
+    /* update the focus lists */
+    focus_order_remove(self);
 
     client_list = g_list_remove(client_list, self);
     stacking_remove(self);
@@ -576,34 +573,36 @@ void client_unmanage(ObClient *self)
         self->group = NULL;
     }
 
-    /* give the client its border back */
-    client_toggle_border(self, TRUE);
+    /* restore the window's original geometry so it is not lost */
+    {
+        Rect a = self->area;
+
+        if (self->fullscreen)
+            a = self->pre_fullscreen_area;
+        else if (self->max_horz || self->max_vert) {
+            if (self->max_horz) {
+                a.x = self->pre_max_area.x;
+                a.width = self->pre_max_area.width;
+            }
+            if (self->max_vert) {
+                a.y = self->pre_max_area.y;
+                a.height = self->pre_max_area.height;
+            }
+        }
+
+        /* give the client its border back */
+        client_toggle_border(self, TRUE);
+
+        self->fullscreen = self->max_horz = self->max_vert = FALSE;
+        self->decorations = 0; /* unmanaged windows have no decor */
+
+        client_move_resize(self, a.x, a.y, a.width, a.height);
+    }
 
     /* reparent the window out of the frame, and free the frame */
     frame_release_client(self->frame, self);
     self->frame = NULL;
 
-    /* restore the window's original geometry so it is not lost */
-    if (self->fullscreen)
-        XMoveResizeWindow(ob_display, self->window,
-                          self->pre_fullscreen_area.x,
-                          self->pre_fullscreen_area.y,
-                          self->pre_fullscreen_area.width,
-                          self->pre_fullscreen_area.height);
-    else if (self->max_horz || self->max_vert) {
-        Rect a = self->area;
-        if (self->max_horz) {
-            a.x = self->pre_max_area.x;
-            a.width = self->pre_max_area.width;
-        }
-        if (self->max_vert) {
-            a.y = self->pre_max_area.y;
-            a.height = self->pre_max_area.height;
-        }
-        XMoveResizeWindow(ob_display, self->window,
-                          a.x, a.y, a.width, a.height);
-    }
-     
     if (ob_state() != OB_STATE_EXITING) {
         /* these values should not be persisted across a window
            unmapping/mapping */
@@ -616,7 +615,6 @@ void client_unmanage(ObClient *self)
         XMapWindow(ob_display, self->window);
     }
 
-
     ob_debug("Unmanaged window 0x%lx\n", self->window);
 
     /* free all data allocated in the client struct */
@@ -630,14 +628,12 @@ void client_unmanage(ObClient *self)
     g_free(self->name);
     g_free(self->class);
     g_free(self->role);
+    g_free(self->client_machine);
     g_free(self->sm_client_id);
     g_free(self);
      
     /* update the list hints */
     client_set_list();
-
-    if (config_focus_last)
-        grab_pointer(FALSE, OB_CURSOR_NONE);
 }
 
 static ObAppSettings *client_get_settings_state(ObClient *self)
@@ -689,7 +685,7 @@ static ObAppSettings *client_get_settings_state(ObClient *self)
 
         if (settings->desktop < screen_num_desktops
             || settings->desktop == DESKTOP_ALL)
-            client_set_desktop(self, settings->desktop, TRUE);
+            self->desktop = settings->desktop;
 
         if (settings->layer == -1) {
             self->below = TRUE;
@@ -893,10 +889,9 @@ static void client_toggle_border(ObClient *self, gboolean show)
     if (show) {
         XSetWindowBorderWidth(ob_display, self->window, self->border_width);
 
-        /* move the client so it is back it the right spot _with_ its
-           border! */
-        if (x != oldx || y != oldy)
-            XMoveWindow(ob_display, self->window, x, y);
+        /* set border_width to 0 because there is no border to add into
+           calculations anymore */
+        self->border_width = 0;
     } else
         XSetWindowBorderWidth(ob_display, self->window, 0);
 }
@@ -943,12 +938,13 @@ static void client_get_all(ObClient *self)
        (min/max sizes), so we're ready to set up the decorations/functions */
     client_setup_decor_and_functions(self);
   
+    client_get_client_machine(self);
     client_update_title(self);
     client_update_class(self);
     client_update_sm_client_id(self);
     client_update_strut(self);
     client_update_icons(self);
-    client_update_user_time(self, FALSE);
+    client_update_user_time(self);
 }
 
 static void client_get_startup_id(ObClient *self)
@@ -968,6 +964,7 @@ static void client_get_area(ObClient *self)
     g_assert(ret != BadWindow);
 
     RECT_SET(self->area, wattrib.x, wattrib.y, wattrib.width, wattrib.height);
+    POINT_SET(self->root_pos, wattrib.x, wattrib.y);
     self->border_width = wattrib.border_width;
 
     ob_debug("client area: %d %d  %d %d\n", wattrib.x, wattrib.y,
@@ -1650,6 +1647,7 @@ void client_update_wmhints(ObClient *self)
 void client_update_title(ObClient *self)
 {
     gchar *data = NULL;
+    gchar *visible = NULL;
 
     g_free(self->title);
      
@@ -1669,8 +1667,14 @@ void client_update_title(ObClient *self)
         }
     }
 
-    PROP_SETS(self->window, net_wm_visible_name, data);
-    self->title = data;
+    if (self->client_machine) {
+        visible = g_strdup_printf("%s (%s)", data, self->client_machine);
+        g_free(data);
+    } else
+        visible = data;
+
+    PROP_SETS(self->window, net_wm_visible_name, visible);
+    self->title = visible;
 
     if (self->frame)
         frame_adjust_title(self->frame);
@@ -1850,31 +1854,40 @@ void client_update_icons(ObClient *self)
         frame_adjust_icon(self->frame);
 }
 
-void client_update_user_time(ObClient *self, gboolean new_event)
+void client_update_user_time(ObClient *self)
 {
     guint32 time;
 
     if (PROP_GET32(self->window, net_wm_user_time, cardinal, &time)) {
-        self->user_time = time;
         /* we set this every time, not just when it grows, because in practice
            sometimes time goes backwards! (ntpdate.. yay....) so.. if it goes
            backward we don't want all windows to stop focusing. we'll just
            assume noone is setting times older than the last one, cuz that
            would be pretty stupid anyways
-           However! This is called when a window is mapped to get its user time
-           but it's an old number, it's not changing it from new user
-           interaction, so in that case, don't change the last user time.
         */
-        if (new_event)
-            client_last_user_time = time;
+        self->user_time = time;
 
         /*
         ob_debug("window %s user time %u\n", self->title, time);
-        ob_debug("last user time %u\n", client_last_user_time);
         */
     }
 }
 
+static void client_get_client_machine(ObClient *self)
+{
+    gchar *data = NULL;
+    gchar localhost[128];
+
+    g_free(self->client_machine);
+
+    if (PROP_GETS(self->window, wm_client_machine, locale, &data)) {
+        gethostname(localhost, 127);
+        localhost[127] = '\0';
+        if (strcmp(localhost, data))
+            self->client_machine = data;
+    }
+}
+
 static void client_change_wm_state(ObClient *self)
 {
     gulong state[2];
@@ -2058,6 +2071,33 @@ gboolean client_should_show(ObClient *self)
     return FALSE;
 }
 
+void client_show(ObClient *self)
+{
+
+    if (client_should_show(self)) {
+        frame_show(self->frame);
+    }
+
+    /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
+       needs to be in IconicState. This includes when it is on another
+       desktop!
+    */
+    client_change_wm_state(self);
+}
+
+void client_hide(ObClient *self)
+{
+    if (!client_should_show(self)) {
+        frame_hide(self->frame);
+    }
+
+    /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
+       needs to be in IconicState. This includes when it is on another
+       desktop!
+    */
+    client_change_wm_state(self);
+}
+
 void client_showhide(ObClient *self)
 {
 
@@ -2066,10 +2106,6 @@ void client_showhide(ObClient *self)
     }
     else {
         frame_hide(self->frame);
-
-        /* Fall back focus since we're disappearing */
-        if (focus_client == self)
-            client_unfocus(self);
     }
 
     /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
@@ -2134,8 +2170,12 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y)
         pos = TRUE;
     }
 
-    /* if the client didn't get positioned yet, then do so now */
-    if (!pos && (ox != x || oy != y)) {
+    /* if the client didn't get positioned yet, then do so now
+       call client_move even if the window is not being moved anywhere, because
+       when we reparent it and decorate it, it is getting moved and we need to
+       be telling it so with a ConfigureNotify event.
+    */
+    if (!pos) {
         /* use the saved position */
         self->area.x = ox;
         self->area.y = oy;
@@ -2327,9 +2367,9 @@ void client_configure_full(ObClient *self, ObCorner anchor,
                            gboolean user, gboolean final,
                            gboolean force_reply)
 {
-    gint oldw, oldh;
+    gint oldw, oldh, oldrx, oldry;
     gboolean send_resize_client;
-    gboolean moved = FALSE, resized = FALSE;
+    gboolean moved = FALSE, resized = FALSE, rootmoved = FALSE;
     guint fdecor = self->frame->decorations;
     gboolean fhorz = self->frame->max_horz;
     gint logicalw, logicalh;
@@ -2358,43 +2398,59 @@ void client_configure_full(ObClient *self, ObCorner anchor,
                                     (resized && config_resize_redraw))));
 
     /* if the client is enlarging, then resize the client before the frame */
-    if (send_resize_client && user && (w > oldw || h > oldh))
+    if (send_resize_client && user && (w > oldw || h > oldh)) {
         XResizeWindow(ob_display, self->window, MAX(w, oldw), MAX(h, oldh));
-
-    /* move/resize the frame to match the request */
-    if (self->frame) {
-        if (self->decorations != fdecor || self->max_horz != fhorz)
-            moved = resized = TRUE;
-
-        if (moved || resized)
-            frame_adjust_area(self->frame, moved, resized, FALSE);
-
-        if (!resized && (force_reply || ((!user && moved) || (user && final))))
-        {
-            XEvent event;
-            event.type = ConfigureNotify;
-            event.xconfigure.display = ob_display;
-            event.xconfigure.event = self->window;
-            event.xconfigure.window = self->window;
-
-            /* root window real coords */
-            event.xconfigure.x = self->frame->area.x + self->frame->size.left -
-                self->border_width;
-            event.xconfigure.y = self->frame->area.y + self->frame->size.top -
-                self->border_width;
-            event.xconfigure.width = w;
-            event.xconfigure.height = h;
-            event.xconfigure.border_width = 0;
-            event.xconfigure.above = self->frame->plate;
-            event.xconfigure.override_redirect = FALSE;
-            XSendEvent(event.xconfigure.display, event.xconfigure.window,
-                       FALSE, StructureNotifyMask, &event);
-        }
+        frame_adjust_client_area(self->frame);
+    }
+
+    /* find the frame's dimensions and move/resize it */
+    if (self->decorations != fdecor || self->max_horz != fhorz)
+        moved = resized = TRUE;
+    if (moved || resized)
+        frame_adjust_area(self->frame, moved, resized, FALSE);
+
+    /* find the client's position relative to the root window */
+    oldrx = self->root_pos.x;
+    oldry = self->root_pos.y;
+    rootmoved = (oldrx != (signed)(self->frame->area.x +
+                                   self->frame->size.left -
+                                   self->border_width) ||
+                 oldry != (signed)(self->frame->area.y +
+                                   self->frame->size.top -
+                                   self->border_width));
+
+    if (force_reply || ((!user || (user && final)) && rootmoved))
+    {
+        XEvent event;
+
+        POINT_SET(self->root_pos,
+                  self->frame->area.x + self->frame->size.left -
+                  self->border_width,
+                  self->frame->area.y + self->frame->size.top -
+                  self->border_width);
+
+        event.type = ConfigureNotify;
+        event.xconfigure.display = ob_display;
+        event.xconfigure.event = self->window;
+        event.xconfigure.window = self->window;
+
+        /* root window real coords */
+        event.xconfigure.x = self->root_pos.x;
+        event.xconfigure.y = self->root_pos.y;
+        event.xconfigure.width = w;
+        event.xconfigure.height = h;
+        event.xconfigure.border_width = 0;
+        event.xconfigure.above = self->frame->plate;
+        event.xconfigure.override_redirect = FALSE;
+        XSendEvent(event.xconfigure.display, event.xconfigure.window,
+                   FALSE, StructureNotifyMask, &event);
     }
 
     /* if the client is shrinking, then resize the frame before the client */
-    if (send_resize_client && (!user || (w <= oldw || h <= oldh)))
+    if (send_resize_client && (!user || (w <= oldw || h <= oldh))) {
         XResizeWindow(ob_display, self->window, w, h);
+        frame_adjust_client_area(self->frame);
+    }
 
     XFlush(ob_display);
 }
@@ -2976,11 +3032,17 @@ gboolean client_focus(ObClient *self)
         return FALSE;
     }
 
-    ob_debug("Focusing client \"%s\" at time %u\n", self->title, event_curtime);
+    ob_debug_type(OB_DEBUG_FOCUS,
+                  "Focusing client \"%s\" at time %u\n",
+                  self->title, event_curtime);
 
     if (self->can_focus) {
+        /* This can cause a BadMatch error with CurrentTime, or if an app
+           passed in a bad time for _NET_WM_ACTIVE_WINDOW. */
+        xerror_set_ignore(TRUE);
         XSetInputFocus(ob_display, self->window, RevertToPointerRoot,
                        event_curtime);
+        xerror_set_ignore(FALSE);
     }
 
     if (self->focus_notify) {
@@ -3011,31 +3073,21 @@ gboolean client_focus(ObClient *self)
     return TRUE;
 }
 
-/* Used when the current client is closed or otherwise hidden, focus_last will
-   then prevent focus from going to the mouse pointer
-*/
-static void client_unfocus(ObClient *self)
-{
-    if (focus_client == self) {
-#ifdef DEBUG_FOCUS
-        ob_debug("client_unfocus for %lx\n", self->window);
-#endif
-        focus_fallback(FALSE);
-    }
-}
-
 void client_activate(ObClient *self, gboolean here, gboolean user)
 {
+    guint32 last_time = focus_client ? focus_client->user_time : CurrentTime;
+
     /* XXX do some stuff here if user is false to determine if we really want
        to activate it or not (a parent or group member is currently
        active)?
     */
     ob_debug("Want to activate window 0x%x with time %u (last time %u), "
              "source=%s\n",
-             self->window, event_curtime, client_last_user_time,
+             self->window, event_curtime, last_time,
              (user ? "user" : "application"));
-    if (!user && event_curtime &&
-        !event_time_after(event_curtime, client_last_user_time))
+
+    if (!user && event_curtime && last_time &&
+        !event_time_after(event_curtime, last_time))
     {
         client_hilite(self, TRUE);
     } else {
@@ -3139,107 +3191,6 @@ const ObClientIcon* client_icon(ObClient *self, gint w, gint h)
     return ret;
 }
 
-/* this be mostly ripped from fvwm */
-ObClient *client_find_directional(ObClient *c, ObDirection dir) 
-{
-    gint my_cx, my_cy, his_cx, his_cy;
-    gint offset = 0;
-    gint distance = 0;
-    gint score, best_score;
-    ObClient *best_client, *cur;
-    GList *it;
-
-    if(!client_list)
-        return NULL;
-
-    /* first, find the centre coords of the currently focused window */
-    my_cx = c->frame->area.x + c->frame->area.width / 2;
-    my_cy = c->frame->area.y + c->frame->area.height / 2;
-
-    best_score = -1;
-    best_client = NULL;
-
-    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)
-            continue;
-        if (!client_normal(cur))
-            continue;
-        /* using c->desktop instead of screen_desktop doesn't work if the
-         * current window was omnipresent, hope this doesn't have any other
-         * side effects */
-        if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
-            continue;
-        if(cur->iconic)
-            continue;
-        if(!(client_focus_target(cur) == cur &&
-             client_can_focus(cur)))
-            continue;
-
-        /* find the centre coords of this window, from the
-         * currently focused window's point of view */
-        his_cx = (cur->frame->area.x - my_cx)
-            + cur->frame->area.width / 2;
-        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) {
-            gint tx;
-            /* Rotate the diagonals 45 degrees counterclockwise.
-             * To do this, multiply the matrix /+h +h\ with the
-             * vector (x y).                   \-h +h/
-             * h = sqrt(0.5). We can set h := 1 since absolute
-             * distance doesn't matter here. */
-            tx = his_cx + his_cy;
-            his_cy = -his_cx + his_cy;
-            his_cx = tx;
-        }
-
-        switch(dir) {
-        case OB_DIRECTION_NORTH:
-        case OB_DIRECTION_SOUTH:
-        case OB_DIRECTION_NORTHEAST:
-        case OB_DIRECTION_SOUTHWEST:
-            offset = (his_cx < 0) ? -his_cx : his_cx;
-            distance = ((dir == OB_DIRECTION_NORTH ||
-                         dir == OB_DIRECTION_NORTHEAST) ?
-                        -his_cy : his_cy);
-            break;
-        case OB_DIRECTION_EAST:
-        case OB_DIRECTION_WEST:
-        case OB_DIRECTION_SOUTHEAST:
-        case OB_DIRECTION_NORTHWEST:
-            offset = (his_cy < 0) ? -his_cy : his_cy;
-            distance = ((dir == OB_DIRECTION_WEST ||
-                         dir == OB_DIRECTION_NORTHWEST) ?
-                        -his_cx : his_cx);
-            break;
-        }
-
-        /* the target must be in the requested direction */
-        if(distance <= 0)
-            continue;
-
-        /* Calculate score for this window.  The smaller the better. */
-        score = distance + offset;
-
-        /* 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)
-            score += 1000000;
-
-        if(best_score == -1 || score < best_score)
-            best_client = cur,
-                best_score = score;
-    }
-
-    return best_client;
-}
-
 void client_set_layer(ObClient *self, gint layer)
 {
     if (layer < 0) {
@@ -3278,7 +3229,8 @@ guint client_monitor(ObClient *self)
 
 ObClient *client_search_top_parent(ObClient *self)
 {
-    while (self->transient_for && self->transient_for != OB_TRAN_GROUP)
+    while (self->transient_for && self->transient_for != OB_TRAN_GROUP &&
+           client_normal(self))
         self = self->transient_for;
     return self;
 }
@@ -3301,7 +3253,7 @@ GSList *client_search_all_top_parents(ObClient *self)
             for (it = self->group->members; it; it = g_slist_next(it)) {
                 ObClient *c = it->data;
 
-                if (!c->transient_for)
+                if (!c->transient_for && client_normal(c))
                     ret = g_slist_prepend(ret, c);
             }
 
This page took 0.038526 seconds and 4 git commands to generate.