]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
ignore another type of crossing event, caused when leaving gtk popup menus
[chaz/openbox] / openbox / client.c
index d86e42532bf627e7941d735adbc0fcbee5c5afb2..98f3dea4913b13e3fc693b65f6244e82d9d0e28b 100644 (file)
@@ -1,5 +1,6 @@
 #include "client.h"
 #include "screen.h"
+#include "moveresize.h"
 #include "prop.h"
 #include "extensions.h"
 #include "frame.h"
@@ -152,6 +153,7 @@ void client_manage(Window window)
     XSetWindowAttributes attrib_set;
 /*    XWMHints *wmhint; */
     guint i;
+    Client *parent;
 
     grab_server(TRUE);
 
@@ -223,10 +225,10 @@ void client_manage(Window window)
     /* update the focus lists */
     if (self->desktop == DESKTOP_ALL) {
         for (i = 0; i < screen_num_desktops; ++i)
-            focus_order[i] = g_list_append(focus_order[i], self);
+            focus_order[i] = g_list_insert(focus_order[i], self, 1);
     } else {
         i = self->desktop;
-        focus_order[i] = g_list_append(focus_order[i], self);
+        focus_order[i] = g_list_insert(focus_order[i], self, 1);
     }
 
     stacking_raise(self);
@@ -237,26 +239,30 @@ void client_manage(Window window)
 
     client_showhide(self);
 
-    dispatch_client(Event_Client_Mapped, self, 0, 0);
-
     /* focus the new window? */
     if (ob_state != State_Starting && client_normal(self)) {
-        if (config_focus_new)
-            client_focus(self);
-        else if (self->transient_for) {
+        parent = NULL;
+
+        if (self->transient_for) {
             if (self->transient_for != TRAN_GROUP) {/* transient of a window */
-                if (focus_client == self->transient_for)
-                    client_focus(self);
+                parent = self->transient_for;
             } else { /* transient of a group */
                 GSList *it;
 
                 for (it = self->group->members; it; it = it->next)
-                    if (focus_client == it->data) {
-                        client_focus(self);
-                        break;
-                    }
+                    if (it->data != self &&
+                        ((Client*)it->data)->transient_for != TRAN_GROUP)
+                        parent = it->data;
             }
         }
+        /* note the check against Type_Normal, not client_normal(self), which
+           would also include dialog types. in this case we want more strict
+           rules for focus */
+        if ((config_focus_new && self->type == Type_Normal) ||
+            (parent && (client_focused(parent) ||
+                        search_focus_tree(parent, parent)))) {
+            client_focus(self);
+        }
     }
 
     /* update the list hints */
@@ -265,6 +271,8 @@ void client_manage(Window window)
     /* make sure the window is visible */
     client_move_onscreen(self);
 
+    dispatch_client(Event_Client_Mapped, self, 0, 0);
+
     g_message("Managed window 0x%lx", window);
 }
 
@@ -331,8 +339,17 @@ void client_unmanage(Client *self)
         }
     }
 
-    if (focus_client == self)
+    if (moveresize_client == self)
+        moveresize_end(TRUE);
+
+    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));
         client_unfocus(self);
+    }
 
     /* remove from its group */
     if (self->group) {
@@ -363,6 +380,7 @@ void client_unmanage(Client *self)
            XMapWindow(ob_display, self->window);
     }
 
+
     g_message("Unmanaged window 0x%lx", self->window);
 
     /* free all data allocated in the client struct */
@@ -492,11 +510,12 @@ static void client_get_all(Client *self)
     self->nicons = 0;
 
     client_get_area(self);
+    client_update_transient_for(self);
+    client_update_wmhints(self);
     client_get_desktop(self);
     client_get_state(self);
     client_get_shaped(self);
 
-    client_update_transient_for(self);
     client_get_mwm_hints(self);
     client_get_type(self);/* this can change the mwmhints for special cases */
 
@@ -510,7 +529,6 @@ static void client_get_all(Client *self)
        (min/max sizes), so we're ready to set up the decorations/functions */
     client_setup_decor_and_functions(self);
   
-    client_update_wmhints(self);
     client_update_title(self);
     client_update_icon_title(self);
     client_update_class(self);
@@ -518,14 +536,6 @@ static void client_get_all(Client *self)
     client_update_icons(self);
     client_update_kwm_icon(self);
 
-    /* this makes sure that these windows appear on all desktops */
-    if (self->type == Type_Desktop)
-       self->desktop = DESKTOP_ALL;
-
-    /* set the desktop hint, to make sure that it always exists, and to
-       reflect any changes we've made here */
-    PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
-
     client_change_state(self);
 }
 
@@ -549,9 +559,31 @@ static void client_get_desktop(Client *self)
        if (d >= screen_num_desktops && d != DESKTOP_ALL)
            d = screen_num_desktops - 1;
        self->desktop = d;
-    } else {
-       /* defaults to the current desktop */
-       self->desktop = screen_desktop;
+    } else { 
+        gboolean trdesk = FALSE;
+
+       if (self->transient_for) {
+           if (self->transient_for != TRAN_GROUP) {
+                self->desktop = self->transient_for->desktop;
+                trdesk = TRUE;
+            } else {
+                GSList *it;
+
+                for (it = self->group->members; it; it = it->next)
+                    if (it->data != self &&
+                        ((Client*)it->data)->transient_for != TRAN_GROUP) {
+                        self->desktop = ((Client*)it->data)->desktop;
+                        trdesk = TRUE;
+                        break;
+                    }
+            }
+       }
+       if (!trdesk)
+           /* defaults to the current desktop */
+           self->desktop = screen_desktop;
+
+        /* set the desktop hint, to make sure that it always exists */
+        PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
     }
 }
 
@@ -735,6 +767,10 @@ void client_get_type(Client *self)
        else
            self->type = Type_Normal;
     }
+
+    /* this makes sure that these windows appear on all desktops */
+    if (self->type == Type_Desktop)
+       self->desktop = DESKTOP_ALL;
 }
 
 void client_update_protocols(Client *self)
@@ -1034,9 +1070,11 @@ void client_update_wmhints(Client *self)
            ur = TRUE;
 
        if (!(hints->flags & WindowGroupHint))
-            hints->window_group = None; /* no group */
+            hints->window_group = None;
+
         /* did the group state change? */
-        if (hints->window_group != (self->group ? self->group->leader : None)){
+        if (hints->window_group !=
+            (self->group ? self->group->leader : None)) {
             /* remove from the old group if there was one */
             if (self->group != NULL) {
                 /* remove transients of the group */
@@ -1049,36 +1087,40 @@ void client_update_wmhints(Client *self)
                 group_remove(self->group, self);
                 self->group = NULL;
             }
-            if (hints->window_group != None)
+            if (hints->window_group != None) {
                 self->group = group_add(hints->window_group, self);
 
-            /* add other transients of the group that are already set up */
-            for (it = self->group->members; it; it = it->next)
-                if (it->data != self &&
-                    ((Client*)it->data)->transient_for == TRAN_GROUP)
-                    self->transients = g_slist_append(self->transients,
-                                                      it->data);
+                /* add other transients of the group that are already
+                   set up */
+                for (it = self->group->members; it; it = it->next)
+                    if (it->data != self &&
+                        ((Client*)it->data)->transient_for == TRAN_GROUP)
+                        self->transients = g_slist_append(self->transients,
+                                                          it->data);
+            }
 
             /* because the self->transient flag wont change from this call,
                we don't need to update the window's type and such, only its
-               transient_for, and the transients lists of other windows in the
-               group may be affected */
+               transient_for, and the transients lists of other windows in
+               the group may be affected */
             client_update_transient_for(self);
         }
 
-       if (hints->flags & IconPixmapHint) {
-           client_update_kwm_icon(self);
-           /* try get the kwm icon first, this is a fallback only */
-           if (self->pixmap_icon == None) {
-               self->pixmap_icon = hints->icon_pixmap;
-               if (hints->flags & IconMaskHint)
-                   self->pixmap_icon_mask = hints->icon_mask;
-               else
-                   self->pixmap_icon_mask = None;
-
-               if (self->frame)
-                   frame_adjust_icon(self->frame);
-           }
+        client_update_kwm_icon(self);
+        /* try get the kwm icon first, this is a fallback only */
+        if (self->pixmap_icon == None) {
+            if (hints->flags & IconPixmapHint) {
+                if (self->pixmap_icon == None) {
+                    self->pixmap_icon = hints->icon_pixmap;
+                    if (hints->flags & IconMaskHint)
+                        self->pixmap_icon_mask = hints->icon_mask;
+                    else
+                        self->pixmap_icon_mask = None;
+
+                    if (self->frame)
+                        frame_adjust_icon(self->frame);
+                }
+            }
        }
 
        XFree(hints);
@@ -2081,10 +2123,26 @@ gboolean client_focusable(Client *self)
 gboolean client_focus(Client *self)
 {
     XEvent ev;
+    guint i;
 
     /* choose the correct target */
     self = client_focus_target(self);
 
+    if (self->desktop != DESKTOP_ALL && self->desktop != screen_desktop) {
+        /* update the focus lists */
+        if (self->desktop == DESKTOP_ALL) {
+            for (i = 0; i < screen_num_desktops; ++i) {
+                focus_order[i] = g_list_remove(focus_order[i], self);
+                focus_order[i] = g_list_prepend(focus_order[i], self);
+            }
+        } else {
+            i = self->desktop;
+            focus_order[i] = g_list_remove(focus_order[i], self);
+            focus_order[i] = g_list_prepend(focus_order[i], self);
+        }
+        return FALSE;
+    }
+
     if (!client_focusable(self))
        return FALSE;
 
@@ -2107,7 +2165,7 @@ gboolean client_focus(Client *self)
     }
 
     if (self->can_focus)
-        /* RevertToPointerRoot causes much more headache than TevertToNone, so
+        /* RevertToPointerRoot causes much more headache than RevertToNone, so
            I choose to use it always, hopefully to find errors quicker, if any
            are left. (I hate X. I hate focus events.) */
        XSetInputFocus(ob_display, self->window, RevertToPointerRoot,
@@ -2129,7 +2187,9 @@ gboolean client_focus(Client *self)
     }
 
 #ifdef DEBUG_FOCUS
-    g_message("focusing %lx", self->window);
+    g_message("%sively focusing %lx at %d", (self->can_focus ? "act" : "pass"),
+              self->window, (int)
+              event_lasttime);
 #endif
 
     /* Cause the FocusIn to come back to us. Important for desktop switches,
@@ -2143,7 +2203,7 @@ void client_unfocus(Client *self)
 {
     g_assert(focus_client == self);
 #ifdef DEBUG_FOCUS
-    g_message("client_unfocus");
+    g_message("client_unfocus for %lx", self->window);
 #endif
     focus_fallback(Fallback_Unfocusing);
 }
This page took 0.027876 seconds and 4 git commands to generate.