]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
drop the DoNotPropogate thing. metacity doesn't set it at all, and i cant tell any...
[chaz/openbox] / openbox / client.c
index 5e1a78513992929a178fb871bfbffa0b89a1b3b2..256190b97ff7ed74a670daadfe466807384d9274 100644 (file)
@@ -262,9 +262,7 @@ void client_manage(Window window)
 
     /* choose the events we want to receive on the CLIENT window */
     attrib_set.event_mask = CLIENT_EVENTMASK;
-    attrib_set.do_not_propagate_mask = CLIENT_NOPROPAGATEMASK;
-    XChangeWindowAttributes(ob_display, window,
-                            CWEventMask|CWDontPropagate, &attrib_set);
+    XChangeWindowAttributes(ob_display, window, CWEventMask, &attrib_set);
 
 
     /* create the ObClient struct, and populate it from the hints on the
@@ -277,7 +275,7 @@ 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 = CurrentTime;
+    self->user_time = focus_client ? focus_client->user_time : CurrentTime;
 
     client_get_all(self);
     /* per-app settings override stuff, and return the settings for other
@@ -347,8 +345,8 @@ void client_manage(Window window)
 
         /* make sure the window is visible. */
         client_find_onscreen(self, &newx, &newy,
-                             self->frame->area.width,
-                             self->frame->area.height,
+                             self->area.width,
+                             self->area.height,
                              /* non-normal clients has less rules, and
                                 windows that are being restored from a
                                 session do also. we can assume you want
@@ -381,8 +379,10 @@ void client_manage(Window window)
             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, last_time);
+        ob_debug_type(OB_DEBUG_FOCUS,
+                      "Want to focus new window 0x%x with time %u "
+                      "(last time %u)\n",
+                      self->window, self->user_time, last_time);
 
         /* if it's on another desktop */
         if (!(self->desktop == screen_desktop || self->desktop == DESKTOP_ALL)
@@ -391,31 +391,38 @@ void client_manage(Window window)
             !event_time_after(self->user_time, screen_desktop_user_time))
         {
             activate = FALSE;
+            ob_debug_type(OB_DEBUG_FOCUS,
+                          "Not focusing the window because its on another "
+                          "desktop\n");
         }
-        /* If nothing is focused, or a parent was focused, then focus this
-           always
-        */
-        else if (!focus_client || client_search_focus_parent(self) != NULL)
-            activate = TRUE;
-        else
+        /* If something is focused, and it's not our parent... */
+        else if (focus_client && client_search_focus_parent(self) == NULL)
         {
             /* If time stamp is old, don't steal focus */
             if (self->user_time && last_time &&
                 !event_time_after(self->user_time, last_time))
             {
                 activate = FALSE;
+                ob_debug_type(OB_DEBUG_FOCUS,
+                              "Not focusing the window because the time is "
+                              "too old\n");
             }
             /* 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))
+            if (!(focus_client->can_focus || focus_client->focus_notify)) {
                 activate = FALSE;
+                ob_debug_type(OB_DEBUG_FOCUS,
+                              "Not focusing the window because a globally "
+                              "active client has focus\n");
+            }
         }
 
         if (!activate) {
-            ob_debug("Focus stealing prevention activated for %s with time %u "
-                     "(last time %u)\n",
-                     self->title, self->user_time, last_time);
+            ob_debug_type(OB_DEBUG_FOCUS,
+                          "Focus stealing prevention activated for %s with "
+                          "time %u (last time %u)\n",
+                          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);
@@ -494,22 +501,8 @@ void client_unmanage(ObClient *self)
     /* 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);
+        /* don't leave an invalid focus_client */
+        focus_client = NULL;
     }
 
     client_list = g_list_remove(client_list, self);
@@ -742,8 +735,8 @@ void client_move_onscreen(ObClient *self, gboolean rude)
     gint x = self->area.x;
     gint y = self->area.y;
     if (client_find_onscreen(self, &x, &y,
-                             self->frame->area.width,
-                             self->frame->area.height, rude)) {
+                             self->area.width,
+                             self->area.height, rude)) {
         client_move(self, x, y);
     }
 }
@@ -920,7 +913,10 @@ static void client_get_all(ObClient *self)
     /* The transient hint is used to pick a type, but the type can also affect
        transiency (dialogs are always made transients of their group if they
        have one). This is Havoc's idea, but it is needed to make some apps
-       work right (eg tsclient). */
+       work right (eg tsclient).
+       I also have made non-application type windows be transients based on
+       their type, like dialogs.
+    */
     client_update_transient_for(self);
     client_get_type(self);/* this can change the mwmhints for special cases */
     client_get_state(self);
@@ -1206,18 +1202,6 @@ void client_update_transient_for(ObClient *self)
                                   c->transient_for != OB_TRAN_GROUP))
                     c->transients = g_slist_append(c->transients, self);
             }
-
-            /* remove all transients which are in the group, that causes
-               circlular pointer hell of doom */
-            for (it = self->group->members; it; it = g_slist_next(it)) {
-                GSList *sit, *next;
-                for (sit = self->transients; sit; sit = next) {
-                    next = g_slist_next(sit);
-                    if (sit->data == it->data)
-                        self->transients =
-                            g_slist_delete_link(self->transients, sit);
-                }
-            }
         } else if (self->transient_for != NULL) { /* transient of window */
             /* add to new parent */
             self->transient_for->transients =
@@ -1622,6 +1606,8 @@ void client_update_wmhints(ObClient *self)
     self->can_focus = TRUE;
   
     if ((hints = XGetWMHints(ob_display, self->window)) != NULL) {
+        gboolean ur;
+
         if (hints->flags & InputHint)
             self->can_focus = hints->input;
 
@@ -1631,6 +1617,13 @@ void client_update_wmhints(ObClient *self)
             if (hints->flags & StateHint)
                 self->iconic = hints->initial_state == IconicState;
 
+        ur = self->urgent;
+        self->urgent = (hints->flags & XUrgencyHint);
+        if (self->urgent && !ur)
+            client_hilite(self, TRUE);
+        else if (!self->urgent && ur && self->demands_attention)
+            client_hilite(self, FALSE);
+
         if (!(hints->flags & WindowGroupHint))
             hints->window_group = None;
 
@@ -1651,7 +1644,8 @@ void client_update_wmhints(ObClient *self)
                     {
                         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);
                     }
@@ -1660,12 +1654,23 @@ void client_update_wmhints(ObClient *self)
                 group_remove(self->group, self);
                 self->group = NULL;
             }
+
+            /* 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
+
+               do this before adding transients from the group so we know if
+               we are actually transient for the group or not.
+            */
+            client_update_transient_for(self);
+
             if (hints->window_group != None) {
                 self->group = group_add(hints->window_group, self);
 
                 /* i can only have transients from the group if i am not
-                   transient myself */
-                if (!self->transient_for) {
+                   transient for the group myself */
+                if (self->transient_for != OB_TRAN_GROUP) {
                     /* add other transients of the group that are already
                        set up */
                     for (it = self->group->members; it;
@@ -1678,12 +1683,6 @@ void client_update_wmhints(ObClient *self)
                     }
                 }
             }
-
-            /* 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 */
-            client_update_transient_for(self);
         }
 
         /* the WM_HINTS can contain an icon */
@@ -2189,6 +2188,12 @@ gboolean client_normal(ObClient *self) {
               self->type == OB_CLIENT_TYPE_SPLASH);
 }
 
+gboolean client_application(ObClient *self)
+{
+    return (self->type == OB_CLIENT_TYPE_NORMAL ||
+            self->type == OB_CLIENT_TYPE_DIALOG);
+}
+
 static void client_apply_startup_state(ObClient *self, gint x, gint y)
 {
     gboolean pos = FALSE; /* has the window's position been configured? */
@@ -2624,10 +2629,11 @@ static void client_iconify_recursive(ObClient *self,
             screen_update_areas();
     }
 
-    /* iconify all direct transients */
+    /* iconify all direct transients, and deiconify all transients
+       (non-direct too) */
     for (it = self->transients; it; it = g_slist_next(it))
         if (it->data != self)
-            if (client_is_direct_child(self, it->data))
+            if (client_is_direct_child(self, it->data) || !iconic)
                 client_iconify_recursive(it->data, iconic, curdesk);
 }
 
@@ -2775,11 +2781,13 @@ void client_hilite(ObClient *self, gboolean hilite)
 
     /* don't allow focused windows to hilite */
     self->demands_attention = hilite && !client_focused(self);
-    if (self->demands_attention)
-        frame_flash_start(self->frame);
-    else
-        frame_flash_stop(self->frame);
-    client_change_state(self);
+    if (self->frame != NULL) { /* if we're mapping, just set the state */
+        if (self->demands_attention)
+            frame_flash_start(self->frame);
+        else
+            frame_flash_stop(self->frame);
+        client_change_state(self);
+    }
 }
 
 void client_set_desktop_recursive(ObClient *self,
@@ -3621,3 +3629,17 @@ gboolean client_has_group_siblings(ObClient *self)
 {
     return self->group && self->group->members->next;
 }
+
+gboolean client_has_application_group_siblings(ObClient *self)
+{
+    GSList *it;
+
+    if (!self->group) return FALSE;
+
+    for (it = self->group->members; it; it = g_slist_next(it)) {
+        ObClient *c = it->data;
+        if (c != self && client_application(c))
+            return TRUE;
+    }
+    return FALSE;
+}
This page took 0.028073 seconds and 4 git commands to generate.