]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
remove event_lastttime. use CurrentTime when handling events without a timestamp...
[chaz/openbox] / openbox / client.c
index dfc44a9b6418edb0d7622f9d502119e3546499c9..b561f4e2a801b2b54e61b8cbb99255270dcec8b6 100644 (file)
@@ -2,7 +2,7 @@
    
    client.c for the Openbox window manager
    Copyright (c) 2006        Mikael Magnusson
-   Copyright (c) 2003        Ben Jansens
+   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
@@ -45,8 +45,7 @@
 #include <X11/Xutil.h>
 
 /*! The event mask to grab on client windows */
-#define CLIENT_EVENTMASK (PropertyChangeMask | FocusChangeMask | \
-                          StructureNotifyMask)
+#define CLIENT_EVENTMASK (PropertyChangeMask | StructureNotifyMask)
 
 #define CLIENT_NOPROPAGATEMASK (ButtonPressMask | ButtonReleaseMask | \
                                 ButtonMotionMask)
@@ -461,11 +460,28 @@ void client_manage(Window window)
     mouse_grab_for_client(self, TRUE);
 
     if (activate) {
-        /* This is focus stealing prevention, if a user_time has been set */
+        /* 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);
-        if (!self->user_time || self->user_time >= client_last_user_time ||
-            client_search_focus_parent(self) != NULL)
+
+        /* If a nothing at all, or a parent was focused, then focus this
+           always
+        */
+        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 && self->user_time < client_last_user_time)
+                activate = FALSE;
+            /* Don't steal focus from globally active clients.
+               I stole this idea from KWin. It seems nice.
+             */
+            if (!focus_client->can_focus && focus_client->focus_notify)
+                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
@@ -478,9 +494,6 @@ void client_manage(Window window)
             /* if the client isn't focused, then hilite it so the user
                knows it is there */
             client_hilite(self, TRUE);
-
-            /* don't focus it ! (focus stealing prevention) */
-            activate = FALSE;
         }
     }
     else {
@@ -541,7 +554,8 @@ void client_unmanage(ObClient *self)
     guint j;
     GSList *it;
 
-    ob_debug("Unmanaging window: %lx (%s)\n", self->window, self->class);
+    ob_debug("Unmanaging window: %lx (%s) (%s)\n", self->window, self->class,
+             self->title ? self->title : "");
 
     g_assert(self != NULL);
 
@@ -1103,9 +1117,15 @@ void client_update_transient_for(ObClient *self)
                 }
             }
         }
-    } else if (self->type == OB_CLIENT_TYPE_DIALOG && self->group) {
-        self->transient = TRUE;
-        target = OB_TRAN_GROUP;
+    } else if (self->group) {
+        if (self->type == OB_CLIENT_TYPE_DIALOG ||
+            self->type == OB_CLIENT_TYPE_TOOLBAR ||
+            self->type == OB_CLIENT_TYPE_MENU ||
+            self->type == OB_CLIENT_TYPE_UTILITY)
+        {
+            self->transient = TRUE;
+            target = OB_TRAN_GROUP;
+        }
     } else
         self->transient = FALSE;
 
@@ -1990,8 +2010,6 @@ static void client_calc_layer_recursive(ObClient *self, ObClient *orig,
     own = calc_layer(self);
     self->layer = MAX(own, min);
 
-    ob_debug("layer for %s: %d\n", self->title, self->layer);
-
     for (it = self->transients; it; it = g_slist_next(it))
         client_calc_layer_recursive(it->data, orig,
                                     self->layer,
@@ -2012,7 +2030,7 @@ void client_calc_layer(ObClient *self)
     orig = self;
 
     /* transients take on the layer of their parents */
-    it = client_search_top_transients(self);
+    it = client_search_all_top_parents(self);
 
     for (; it; it = g_slist_next(it))
         client_calc_layer_recursive(it->data, orig, 0, FALSE);
@@ -2408,6 +2426,10 @@ static void client_iconify_recursive(ObClient *self,
                    bottom'. */
                 focus_order_to_top(self);
 
+                /* Fall back focus since we're disappearing */
+                if (focus_client == self)
+                    client_unfocus(self);
+
                 changed = TRUE;
             }
         } else {
@@ -2437,21 +2459,18 @@ static void client_iconify_recursive(ObClient *self,
             screen_update_areas();
     }
 
-    /* iconify all transients */
+    /* iconify all direct transients */
     for (it = self->transients; it; it = g_slist_next(it))
-        if (it->data != self) client_iconify_recursive(it->data,
-                                                       iconic, curdesk);
+        if (it->data != self)
+            if (client_is_direct_child(self, it->data))
+                client_iconify_recursive(it->data, iconic, curdesk);
 }
 
 void client_iconify(ObClient *self, gboolean iconic, gboolean curdesk)
 {
-    GSList *it;
-
     /* move up the transient chain as far as possible first */
-    it = client_search_top_transients(self);
-
-    for (; it; it = g_slist_next(it))
-    client_iconify_recursive(it->data, iconic, curdesk);
+    self = client_search_top_parent(self);
+    client_iconify_recursive(self, iconic, curdesk);
 }
 
 void client_maximize(ObClient *self, gboolean max, gint dir, gboolean savearea)
@@ -2598,6 +2617,9 @@ void client_kill(ObClient *self)
 
 void client_hilite(ObClient *self, gboolean hilite)
 {
+    if (self->demands_attention == hilite)
+        return; /* no change */
+
     /* don't allow focused windows to hilite */
     self->demands_attention = hilite && !client_focused(self);
     if (self->demands_attention)
@@ -2645,18 +2667,23 @@ void client_set_desktop_recursive(ObClient *self,
 
     /* move all transients */
     for (it = self->transients; it; it = g_slist_next(it))
-        if (it->data != self) client_set_desktop_recursive(it->data,
-                                                           target, donthide);
+        if (it->data != self)
+            if (client_is_direct_child(self, it->data))
+                client_set_desktop_recursive(it->data, target, donthide);
 }
 
 void client_set_desktop(ObClient *self, guint target, gboolean donthide)
 {
-    GSList *it;
-
-    it = client_search_top_transients(self);
+    self = client_search_top_parent(self);
+    client_set_desktop_recursive(self, target, donthide);
+}
 
-    for(; it; it = g_slist_next(it))
-        client_set_desktop_recursive(it->data, target, donthide);
+gboolean client_is_direct_child(ObClient *parent, ObClient *child)
+{
+    while (child != parent &&
+           child->transient_for && child->transient_for != OB_TRAN_GROUP)
+        child = child->transient_for;
+    return child == parent;
 }
 
 ObClient *client_search_modal_child(ObClient *self)
@@ -2914,6 +2941,11 @@ gboolean client_focus(ObClient *self)
     /* choose the correct target */
     self = client_focus_target(self);
 
+#if 0
+    if (!client_validate(self))
+        return FALSE;
+#endif
+
     if (!client_can_focus(self)) {
         if (!self->frame->visible) {
             /* update the focus lists */
@@ -2922,6 +2954,8 @@ gboolean client_focus(ObClient *self)
         return FALSE;
     }
 
+    ob_debug("Focusing client \"%s\" at time %u\n", self->title, event_curtime);
+
     if (self->can_focus) {
         /* RevertToPointerRoot causes much more headache than RevertToNone, so
            I choose to use it always, hopefully to find errors quicker, if any
@@ -2962,8 +2996,9 @@ gboolean client_focus(ObClient *self)
     return TRUE;
 }
 
-/* Used when the current client is closed, focus_last will then prevent
- * focus from going to the mouse pointer */
+/* Used when the current client is closed or otherwise hidden, focus_last will
+   then prevent focus from going to the mouse pointer
+*/
 void client_unfocus(ObClient *self)
 {
     if (focus_client == self) {
@@ -3224,7 +3259,14 @@ guint client_monitor(ObClient *self)
     return screen_find_monitor(&self->frame->area);
 }
 
-GSList *client_search_top_transients(ObClient *self)
+ObClient *client_search_top_parent(ObClient *self)
+{
+    while (self->transient_for && self->transient_for != OB_TRAN_GROUP)
+        self = self->transient_for;
+    return self;
+}
+
+GSList *client_search_all_top_parents(ObClient *self)
 {
     GSList *ret = NULL;
 
This page took 0.03014 seconds and 4 git commands to generate.