]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
some old changes to grav.c test, it wasn't a valid test before.
[chaz/openbox] / openbox / client.c
index 43a283cdd27926cb22e80ec7c13ed70be85e1fde..4abff4c50984a5296b3ac540ba9e487d558e2304 100644 (file)
 #include "mouse.h"
 #include "render/render.h"
 
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
 #include <glib.h>
 #include <X11/Xutil.h>
 
 /*! The event mask to grab on client windows */
-#define CLIENT_EVENTMASK (PropertyChangeMask | StructureNotifyMask)
+#define CLIENT_EVENTMASK (PropertyChangeMask | StructureNotifyMask | \
+                          ColormapChangeMask)
 
 #define CLIENT_NOPROPAGATEMASK (ButtonPressMask | ButtonReleaseMask | \
                                 ButtonMotionMask)
@@ -56,10 +61,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 +75,8 @@ 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_get_colormap(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 +84,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 +277,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);
 
@@ -314,6 +320,7 @@ void client_manage(Window window)
 
     /* focus the new window? */
     if (ob_state() != OB_STATE_STARTING &&
+        !self->iconic &&
         /* this means focus=true for window is same as config_focus_new=true */
         ((config_focus_new || (settings && settings->focus == 1)) ||
          client_search_focus_parent(self)) &&
@@ -326,37 +333,6 @@ void client_manage(Window window)
          self->type == OB_CLIENT_TYPE_DIALOG))
     {
         activate = TRUE;
-#if 0
-        if (self->desktop != screen_desktop) {
-            /* activate the window */
-            activate = TRUE;
-        } else {
-            gboolean group_foc = FALSE;
-
-            if (self->group) {
-                GSList *it;
-
-                for (it = self->group->members; it; it = g_slist_next(it))
-                {
-                    if (client_focused(it->data))
-                    {
-                        group_foc = TRUE;
-                        break;
-                    }
-                }
-            }
-            if ((group_foc ||
-                 (!self->transient_for && (!self->group ||
-                                           !self->group->members->next))) ||
-                client_search_focus_tree_full(self) ||
-                !focus_client ||
-                !client_normal(focus_client))
-            {
-                /* activate the window */
-                activate = TRUE;
-            }
-        }
-#endif
     }
 
     /* get the current position */
@@ -398,24 +374,34 @@ void client_manage(Window window)
              self->window, newx, newy, self->area.width, self->area.height);
     client_apply_startup_state(self, newx, newy);
 
-    keyboard_grab_for_client(self, TRUE);
     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
+        /* if it's on another desktop */
+        if (!(self->desktop == screen_desktop || self->desktop == DESKTOP_ALL)
+            && /* the timestamp is from before you changed desktops */
+            self->user_time && screen_desktop_user_time &&
+            !event_time_after(self->user_time, screen_desktop_user_time))
+        {
+            activate = FALSE;
+        }
+        /* If nothing is focused, or a parent was focused, then focus this
            always
         */
-        if (!focus_client || client_search_focus_parent(self) != NULL)
+        else if (!focus_client || client_search_focus_parent(self) != NULL)
             activate = TRUE;
         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;
             }
@@ -426,16 +412,10 @@ void client_manage(Window window)
                 activate = FALSE;
         }
 
-        if (activate)
-        {
-            /* since focus can change the stacking orders, if we focus the
-               window then the standard raise it gets is not enough, we need
-               to queue one for after the focus change takes place */
-            client_raise(self);
-        } else {
+        if (!activate) {
             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);
@@ -462,17 +442,8 @@ void client_manage(Window window)
        a window maps since its not based on an action from the user like
        clicking a window to activate it. so keep the new window out of the way
        but do focus it. */
-    if (activate) {
-        /* if using focus_delay, stop the timer now so that focus doesn't
-           go moving on us */
-        event_halt_focus_delay();
-        client_focus(self);
-    }
-
-    /* client_activate does this but we aret using it so we have to do it
-       here as well */
-    if (screen_showing_desktop)
-        screen_show_desktop(FALSE);
+    if (activate)
+        client_activate(self, FALSE, TRUE);
 
     /* add to client list/map */
     client_list = g_list_append(client_list, self);
@@ -504,38 +475,42 @@ 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);
 
-    keyboard_grab_for_client(self, FALSE);
+    /* ignore enter events from the unmap so it doesnt mess with the focus */
+    event_ignore_queued_enters();
+
     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);
+    if (client_focused(self)) {
+        /* we have to fall back here because we might not get a focus out.
+           1. we need to xselectinput off the window before we unmap it because
+           otherwise we end up getting unmapnotifies we don't want and they
+           can mess up mapping it again quickly
+           2. this means that if we unmanage from a synthetic unmapnotify, we
+              are the ones unmapped it, and causing the focusout. so we won't
+              get the focusout event.
+           3. we can't handle focusin events on the root window because they
+              come from all screens, so the focus change gets lost
+
+           if this ever gets removed in the future MAKE SURE to replace it
+           with:
+           /- don't leave an invalid focus_client -/
+           focus_client = NULL;
+        */
+        focus_fallback(FALSE);
+    }
 
     client_list = g_list_remove(client_list, self);
     stacking_remove(self);
@@ -631,14 +606,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)
@@ -683,14 +656,14 @@ static ObAppSettings *client_get_settings_state(ObClient *self)
         if (settings->max_vert != -1)
             self->max_vert = !!settings->max_vert;
         if (settings->max_horz != -1)
-            self->max_vert = !!settings->max_horz;
+            self->max_horz = !!settings->max_horz;
 
         if (settings->fullscreen != -1)
             self->fullscreen = !!settings->fullscreen;
 
         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;
@@ -781,8 +754,8 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
     Rect *a;
     gint ox = *x, oy = *y;
 
-    frame_client_gravity(self->frame, x, y); /* get where the frame
-                                                would be */
+    /* get where the frame would be */
+    frame_client_gravity(self->frame, x, y, w, h);
 
     /* XXX watch for xinerama dead areas */
     /* This makes sure windows aren't entirely outside of the screen so you
@@ -806,6 +779,15 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
             *y = a->y - self->frame->area.width*9/10;
     }
 
+    /* If rudeness wasn't requested, then figure out of the client is currently
+       entirely on the screen. If it is, then be rude even though it wasn't
+       requested */
+    if (!rude) {
+        a = screen_area_monitor(self->desktop, client_monitor(self));
+        if (RECT_CONTAINS_RECT(*a, self->area))
+            rude = TRUE;
+    }
+
     /* This here doesn't let windows even a pixel outside the screen,
      * when called from client_manage, programs placing themselves are
      * forced completely onscreen, while things like
@@ -831,8 +813,8 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
         }
     }
 
-    frame_frame_gravity(self->frame, x, y); /* get where the client
-                                               should be */
+    /* get where the client should be */
+    frame_frame_gravity(self->frame, x, y, w, h);
 
     return ox != *x || oy != *y;
 }
@@ -943,12 +925,17 @@ 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);
   
+#ifdef SYNC
+    client_update_sync_request_counter(self);
+#endif
+    client_get_client_machine(self);
+    client_get_colormap(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)
@@ -1014,10 +1001,6 @@ static void client_get_desktop(ObClient *self)
                 self->desktop = screen_desktop;
         }
     }
-    if (self->desktop != d) {
-        /* set the desktop hint, to make sure that it always exists */
-        PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
-    }
 }
 
 static void client_get_layer(ObClient *self)
@@ -1175,7 +1158,8 @@ void client_update_transient_for(ObClient *self)
             /* remove from old parents */
             for (it = self->group->members; it; it = g_slist_next(it)) {
                 ObClient *c = it->data;
-                if (c != self && !c->transient_for)
+                if (c != self && (!c->transient_for ||
+                                  c->transient_for != OB_TRAN_GROUP))
                     c->transients = g_slist_remove(c->transients, self);
             }
         } else if (self->transient_for != NULL) { /* transient of window */
@@ -1190,7 +1174,8 @@ void client_update_transient_for(ObClient *self)
             /* add to new parents */
             for (it = self->group->members; it; it = g_slist_next(it)) {
                 ObClient *c = it->data;
-                if (c != self && !c->transient_for)
+                if (c != self && (!c->transient_for ||
+                                  c->transient_for != OB_TRAN_GROUP))
                     c->transients = g_slist_append(c->transients, self);
             }
 
@@ -1292,18 +1277,37 @@ void client_update_protocols(ObClient *self)
 
     if (PROP_GETA32(self->window, wm_protocols, atom, &proto, &num_return)) {
         for (i = 0; i < num_return; ++i) {
-            if (proto[i] == prop_atoms.wm_delete_window) {
+            if (proto[i] == prop_atoms.wm_delete_window)
                 /* this means we can request the window to close */
                 self->delete_window = TRUE;
-            else if (proto[i] == prop_atoms.wm_take_focus)
+            else if (proto[i] == prop_atoms.wm_take_focus)
                 /* if this protocol is requested, then the window will be
                    notified whenever we want it to receive focus */
                 self->focus_notify = TRUE;
+#ifdef SYNC
+            else if (proto[i] == prop_atoms.net_wm_sync_request) 
+                /* if this protocol is requested, then resizing the
+                   window will be synchronized between the frame and the
+                   client */
+                self->sync_request = TRUE;
+#endif
         }
         g_free(proto);
     }
 }
 
+#ifdef SYNC
+void client_update_sync_request_counter(ObClient *self)
+{
+    guint32 i;
+
+    if (PROP_GET32(self->window, net_wm_sync_request_counter, cardinal, &i)) {
+        self->sync_counter = i;
+    } else
+        self->sync_counter = None;
+}
+#endif
+
 static void client_get_gravity(ObClient *self)
 {
     XWindowAttributes wattrib;
@@ -1314,6 +1318,19 @@ static void client_get_gravity(ObClient *self)
     self->gravity = wattrib.win_gravity;
 }
 
+void client_get_colormap(ObClient *self)
+{
+    XWindowAttributes wa;
+
+    if (XGetWindowAttributes(ob_display, self->window, &wa))
+        client_update_colormap(self, wa.colormap);
+}
+
+void client_update_colormap(ObClient *self, Colormap colormap)
+{
+    self->colormap = colormap;
+}
+
 void client_update_normal_hints(ObClient *self)
 {
     XSizeHints size;
@@ -1343,9 +1360,9 @@ void client_update_normal_hints(ObClient *self)
             if (self->frame && self->gravity != oldgravity) {
                 /* move our idea of the client's position based on its new
                    gravity */
-                self->area.x = self->frame->area.x;
-                self->area.y = self->frame->area.y;
-                frame_frame_gravity(self->frame, &self->area.x, &self->area.y);
+                client_convert_gravity(self, oldgravity,
+                                       &self->area.x, &self->area.y,
+                                       self->area.width, self->area.height);
             }
         }
 
@@ -1564,7 +1581,7 @@ void client_reconfigure(ObClient *self)
     /* by making this pass FALSE for user, we avoid the emacs event storm where
        every configurenotify causes an update in its normal hints, i think this
        is generally what we want anyways... */
-    client_configure(self, OB_CORNER_TOPLEFT, self->area.x, self->area.y,
+    client_configure(self, self->area.x, self->area.y,
                      self->area.width, self->area.height, FALSE, TRUE);
 }
 
@@ -1651,6 +1668,7 @@ void client_update_wmhints(ObClient *self)
 void client_update_title(ObClient *self)
 {
     gchar *data = NULL;
+    gchar *visible = NULL;
 
     g_free(self->title);
      
@@ -1670,8 +1688,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);
@@ -1847,35 +1871,63 @@ void client_update_icons(ObClient *self)
         }
     }
 
-    if (self->frame)
+    /* set the default icon onto the window
+       in theory, this could be a race, but if a window doesn't set an icon
+       or removes it entirely, it's not very likely it is going to set one
+       right away afterwards */
+    if (self->nicons == 0) {
+        RrPixel32 *icon = ob_rr_theme->def_win_icon;
+        gulong *data;
+
+        data = g_new(gulong, 48*48+2);
+        data[0] = data[1] =  48;
+        for (i = 0; i < 48*48; ++i)
+            data[i+2] = (((icon[i] >> RrDefaultAlphaOffset) & 0xff) << 24) +
+                (((icon[i] >> RrDefaultRedOffset) & 0xff) << 16) +
+                (((icon[i] >> RrDefaultGreenOffset) & 0xff) << 8) +
+                (((icon[i] >> RrDefaultBlueOffset) & 0xff) << 0);
+        PROP_SETA32(self->window, net_wm_icon, cardinal, data, 48*48+2);
+        g_free(data);
+    } else if (self->frame)
+        /* don't draw the icon empty if we're just setting one now anyways,
+           we'll get the property change any second */
         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];
@@ -2120,6 +2172,9 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y)
     self->area.x = x;
     self->area.y = y;
 
+    /* set the desktop hint, to make sure that it always exists */
+    PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
+
     /* these are in a carefully crafted order.. */
 
     if (self->iconic) {
@@ -2179,8 +2234,21 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y)
     */
 }
 
-void client_try_configure(ObClient *self, ObCorner anchor,
-                          gint *x, gint *y, gint *w, gint *h,
+void client_convert_gravity(ObClient *self, gint gravity, gint *x, gint *y,
+                            gint w, gint h)
+{
+    gint oldg = self->gravity;
+
+    /* get the frame's position from the requested stuff */
+    self->gravity = gravity;
+    frame_client_gravity(self->frame, x, y, w, h);
+    self->gravity = oldg;
+
+    /* get the client's position in its true gravity from that */
+    frame_frame_gravity(self->frame, x, y, w, h);
+}
+
+void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
                           gint *logicalw, gint *logicalh,
                           gboolean user)
 {
@@ -2275,7 +2343,7 @@ void client_try_configure(ObClient *self, ObCorner anchor,
     }
 
     /* gets the frame's position */
-    frame_client_gravity(self->frame, x, y);
+    frame_client_gravity(self->frame, x, y, *w, *h);
 
     /* these positions are frame positions, not client positions */
 
@@ -2316,7 +2384,7 @@ void client_try_configure(ObClient *self, ObCorner anchor,
     }
 
     /* gets the client's position */
-    frame_frame_gravity(self->frame, x, y);
+    frame_frame_gravity(self->frame, x, y, *w, *h);
 
     /* these override the above states! if you cant move you can't move! */
     if (user) {
@@ -2332,26 +2400,10 @@ void client_try_configure(ObClient *self, ObCorner anchor,
 
     g_assert(*w > 0);
     g_assert(*h > 0);
-
-    switch (anchor) {
-    case OB_CORNER_TOPLEFT:
-        break;
-    case OB_CORNER_TOPRIGHT:
-        *x -= *w - self->area.width;
-        break;
-    case OB_CORNER_BOTTOMLEFT:
-        *y -= *h - self->area.height;
-        break;
-    case OB_CORNER_BOTTOMRIGHT:
-        *x -= *w - self->area.width;
-        *y -= *h - self->area.height;
-        break;
-    }
 }
 
 
-void client_configure_full(ObClient *self, ObCorner anchor,
-                           gint x, gint y, gint w, gint h,
+void client_configure_full(ObClient *self, gint x, gint y, gint w, gint h,
                            gboolean user, gboolean final,
                            gboolean force_reply)
 {
@@ -2363,8 +2415,7 @@ void client_configure_full(ObClient *self, ObCorner anchor,
     gint logicalw, logicalh;
 
     /* find the new x, y, width, and height (and logical size) */
-    client_try_configure(self, anchor, &x, &y, &w, &h,
-                         &logicalw, &logicalh, user);
+    client_try_configure(self, &x, &y, &w, &h, &logicalw, &logicalh, user);
 
     /* set the logical size if things changed */
     if (!(w == self->area.width && h == self->area.height))
@@ -2398,10 +2449,12 @@ void client_configure_full(ObClient *self, ObCorner anchor,
     /* find the client's position relative to the root window */
     oldrx = self->root_pos.x;
     oldry = self->root_pos.y;
-    rootmoved = (oldrx != (self->frame->area.x + self->frame->size.left -
-                           self->border_width) ||
-                 oldry != (self->frame->area.y + self->frame->size.top -
-                           self->border_width));
+    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))
     {
@@ -3014,11 +3067,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) {
@@ -3049,34 +3108,32 @@ 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,
-             (user ? "user" : "application"));
-    if (!user && event_curtime &&
-        !event_time_after(event_curtime, client_last_user_time))
+    ob_debug_type(OB_DEBUG_FOCUS,
+                  "Want to activate window 0x%x with time %u (last time %u), "
+                  "source=%s\n",
+                  self->window, event_curtime, last_time,
+                  (user ? "user" : "application"));
+
+    if (!user && event_curtime && last_time &&
+        !event_time_after(event_curtime, last_time))
     {
         client_hilite(self, TRUE);
     } else {
+        if (event_curtime != CurrentTime)
+            self->user_time = event_curtime;
+
+        /* if using focus_delay, stop the timer now so that focus doesn't
+           go moving on us */
+        event_halt_focus_delay();
+
         if (client_normal(self) && screen_showing_desktop)
             screen_show_desktop(FALSE);
         if (self->iconic)
@@ -3096,11 +3153,11 @@ void client_activate(ObClient *self, gboolean here, gboolean user)
 
         client_focus(self);
 
-        /* we do this an action here. this is rather important. this is because
-           we want the results from the focus change to take place BEFORE we go
-           about raising the window. when a fullscreen window loses focus, we
-           need this or else the raise wont be able to raise above the
-           to-lose-focus fullscreen window. */
+        /* we do this as an action here. this is rather important. this is
+           because we want the results from the focus change to take place 
+           BEFORE we go about raising the window. when a fullscreen window 
+           loses focus, we need this or else the raise wont be able to raise 
+           above the to-lose-focus fullscreen window. */
         client_raise(self);
     }
 }
@@ -3177,107 +3234,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) {
@@ -3303,7 +3259,7 @@ void client_set_undecorated(ObClient *self, gboolean undecorated)
          * since 125 of these are sent per second when moving the window (with
          * user = FALSE) i doubt it matters much.
          */
-        client_configure(self, OB_CORNER_TOPLEFT, self->area.x, self->area.y,
+        client_configure(self, self->area.x, self->area.y,
                          self->area.width, self->area.height, TRUE, TRUE);
         client_change_state(self); /* reflect this in the state hints */
     }
@@ -3316,7 +3272,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;
 }
@@ -3339,7 +3296,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.046117 seconds and 4 git commands to generate.