]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
some changes to focus handling.
[chaz/openbox] / openbox / client.c
index 6bc2b630f00046ccf5b7f9d10e7bb0c13d971a0e..208024cf92ebf1c8eeb8629ec776bf34182d89fe 100644 (file)
@@ -282,30 +282,13 @@ void client_manage(Window window)
 
     /* non-zero defaults */
     self->wmstate = WithdrawnState; /* make sure it gets updated first time */
+    self->gravity = NorthWestGravity;
     self->desktop = screen_num_desktops; /* always an invalid value */
     self->user_time = focus_client ? focus_client->user_time : CurrentTime;
 
+    /* get all the stuff off the window */
     client_get_all(self, TRUE);
-    /* 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_setup_decor_and_functions(self);
-
-    {
-        Time t = sn_app_started(self->startup_id, self->class);
-        if (t) self->user_time = t;
-    }
 
-    /* update the focus lists, do this before the call to change_state or
-       it can end up in the list twice! */
-    focus_order_add_new(self);
-
-    /* remove the client's border (and adjust re gravity) */
-    client_toggle_border(self, FALSE);
-     
     /* specify that if we exit, the window should not be destroyed and
        should be reparented back to root automatically */
     XChangeSaveSet(ob_display, window, SetModeInsert);
@@ -315,11 +298,33 @@ void client_manage(Window window)
 
     frame_grab_client(self->frame);
 
+    /* we've grabbed everything and set everything that we need to at mapping
+       time now */
+    grab_server(FALSE);
+
+    /* per-app settings override stuff from client_get_all, and return the
+       settings for other uses too */
+    settings = client_get_settings_state(self);
+    /* the session should get the last say thought */
+    client_restore_session_state(self);
+
+    /* now we have all of the window's information so we can set this up */
+    client_setup_decor_and_functions(self);
+
+    /* remove the client's border (and adjust re gravity) */
+    client_toggle_border(self, FALSE);
+     
+    {
+        Time t = sn_app_started(self->startup_id, self->class);
+        if (t) self->user_time = t;
+    }
+
     /* do this after we have a frame.. it uses the frame to help determine the
        WM_STATE to apply. */
     client_change_state(self);
 
-    grab_server(FALSE);
+    /* add ourselves to the focus order */
+    focus_order_add_new(self);
 
     /* do this to add ourselves to the stacking list in a non-intrusive way */
     client_calc_layer(self);
@@ -453,16 +458,14 @@ void client_manage(Window window)
             stacking_raise(CLIENT_AS_WINDOW(self));
     }
 
+    /* adjust the frame to the client's size before showing the window */
+    frame_adjust_area(self->frame, FALSE, TRUE, FALSE);
+
     /* 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_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
-       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) {
         gboolean stacked = client_restore_session_stacking(self);
         client_present(self, FALSE, !stacked);
@@ -594,7 +597,12 @@ void client_unmanage(ObClient *self)
 
     /* restore the window's original geometry so it is not lost */
     {
-        Rect a = self->area;
+        Rect a;
+
+        /* give the client its border back */
+        client_toggle_border(self, TRUE);
+
+        a = self->area;
 
         if (self->fullscreen)
             a = self->pre_fullscreen_area;
@@ -609,9 +617,6 @@ void client_unmanage(ObClient *self)
             }
         }
 
-        /* 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 */
 
@@ -1005,6 +1010,9 @@ static void client_get_all(ObClient *self, gboolean real)
     if (!real)
         return;
 
+    /* get this early so we have it for debugging */
+    client_update_title(self);
+
     client_update_protocols(self);
 
     client_update_wmhints(self);
@@ -1030,7 +1038,6 @@ static void client_get_all(ObClient *self, gboolean real)
 #endif
 
     client_get_colormap(self);
-    client_update_title(self);
     client_update_strut(self);
     client_update_icons(self);
     client_update_user_time_window(self);
@@ -1220,19 +1227,34 @@ static void client_update_transient_tree(ObClient *self,
     GSList *it, *next;
     ObClient *c;
 
+    /* * *
+      Group transient windows are not allowed to have other group
+      transient windows as their children.
+      * * */
+
+
     /* No change has occured */
     if (oldgroup == newgroup && oldparent == newparent) return;
 
     /** Remove the client from the transient tree wherever it has changed **/
 
     /* If the window is becoming a direct transient for a window in its group
-       then that window can't be a child of this window anymore */
+       then any group transients which were our children and are now becoming
+       our parents need to stop being our children.
+
+       Group transients can't be children of group transients already, but
+       we could have any number of direct parents above up, any of which could
+       be transient for the group, and we need to remove it from our children.
+    */
     if (oldparent != newparent &&
         newparent != NULL && newparent != OB_TRAN_GROUP &&
-        newparent->transient_for == OB_TRAN_GROUP &&
         newgroup != NULL && newgroup == oldgroup)
     {
-        self->transients = g_slist_remove(self->transients, newparent);
+        ObClient *look = newparent;
+        do {
+            self->transients = g_slist_remove(self->transients, look);
+            look = look->transient_for;
+        } while (look != NULL && look != OB_TRAN_GROUP);
     }
             
 
@@ -1304,7 +1326,9 @@ static void client_update_transient_tree(ObClient *self,
 
        WARNING: Cyclical transient-ness is possible. For e.g. if:
        A is transient for the group
-       B is a member of the group and transient for A
+       B is transient for A
+       C is transient for B
+       A can't be transient for C or we have a cycle
     */
     if (oldgroup != newgroup && newgroup != NULL &&
         newparent != OB_TRAN_GROUP)
@@ -1616,7 +1640,7 @@ void client_setup_decor_and_functions(ObClient *self)
     if (!(self->functions & OB_CLIENT_FUNC_ICONIFY))
         self->decorations &= ~OB_FRAME_DECOR_ICONIFY;
     if (!(self->functions & OB_CLIENT_FUNC_RESIZE))
-        self->decorations &= ~OB_FRAME_DECOR_GRIPS;
+        self->decorations &= ~(OB_FRAME_DECOR_GRIPS | OB_FRAME_DECOR_HANDLE);
 
     /* can't maximize without moving/resizing */
     if (!((self->functions & OB_CLIENT_FUNC_MAXIMIZE) &&
@@ -1694,7 +1718,7 @@ static void client_change_allowed_actions(ObClient *self)
         else self->shaded = FALSE;
     }
     if (!(self->functions & OB_CLIENT_FUNC_ICONIFY) && self->iconic) {
-        if (self->frame) client_iconify(self, FALSE, TRUE);
+        if (self->frame) client_iconify(self, FALSE, TRUE, FALSE);
         else self->iconic = FALSE;
     }
     if (!(self->functions & OB_CLIENT_FUNC_FULLSCREEN) && self->fullscreen) {
@@ -2432,7 +2456,7 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y)
 
     if (self->iconic) {
         self->iconic = FALSE;
-        client_iconify(self, TRUE, FALSE);
+        client_iconify(self, TRUE, FALSE, TRUE);
     }
     if (self->fullscreen) {
         self->fullscreen = FALSE;
@@ -2657,12 +2681,11 @@ void client_try_configure(ObClient *self, 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)
+                           gboolean user, gboolean final)
 {
-    gint oldw, oldh, oldrx, oldry;
+    gint oldw, oldh;
     gboolean send_resize_client;
-    gboolean moved = FALSE, resized = FALSE, rootmoved = FALSE;
+    gboolean moved = FALSE, resized = FALSE;
     guint fdecor = self->frame->decorations;
     gboolean fhorz = self->frame->max_horz;
     gint logicalw, logicalh;
@@ -2702,17 +2725,7 @@ void client_configure_full(ObClient *self, gint x, gint y, gint w, gint h,
     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))
+    if ((!user || (user && final)) && !resized)
     {
         XEvent event;
 
@@ -2727,6 +2740,9 @@ void client_configure_full(ObClient *self, gint x, gint y, gint w, gint h,
         event.xconfigure.event = self->window;
         event.xconfigure.window = self->window;
 
+        ob_debug("Sending ConfigureNotify to %s for %d,%d %dx%d\n",
+                 self->title, self->root_pos.x, self->root_pos.y, w, h);
+
         /* root window real coords */
         event.xconfigure.x = self->root_pos.x;
         event.xconfigure.y = self->root_pos.y;
@@ -2807,7 +2823,8 @@ void client_fullscreen(ObClient *self, gboolean fs)
 }
 
 static void client_iconify_recursive(ObClient *self,
-                                     gboolean iconic, gboolean curdesk)
+                                     gboolean iconic, gboolean curdesk,
+                                     gboolean hide_animation)
 {
     GSList *it;
     gboolean changed = FALSE;
@@ -2847,7 +2864,7 @@ static void client_iconify_recursive(ObClient *self,
 
     if (changed) {
         client_change_state(self);
-        if (ob_state() != OB_STATE_STARTING && config_animate_iconify)
+        if (config_animate_iconify && !hide_animation)
             frame_begin_iconify_animation(self->frame, iconic);
         /* do this after starting the animation so it doesn't flash */
         client_showhide(self);
@@ -2858,15 +2875,17 @@ static void client_iconify_recursive(ObClient *self,
     for (it = self->transients; it; it = g_slist_next(it))
         if (it->data != self)
             if (client_is_direct_child(self, it->data) || !iconic)
-                client_iconify_recursive(it->data, iconic, curdesk);
+                client_iconify_recursive(it->data, iconic, curdesk,
+                                         hide_animation);
 }
 
-void client_iconify(ObClient *self, gboolean iconic, gboolean curdesk)
+void client_iconify(ObClient *self, gboolean iconic, gboolean curdesk,
+                    gboolean hide_animation)
 {
     if (self->functions & OB_CLIENT_FUNC_ICONIFY || !iconic) {
         /* move up the transient chain as far as possible first */
         self = client_search_top_normal_parent(self);
-        client_iconify_recursive(self, iconic, curdesk);
+        client_iconify_recursive(self, iconic, curdesk, hide_animation);
     }
 }
 
@@ -3100,10 +3119,10 @@ void client_set_wm_state(ObClient *self, glong state)
   
     switch (state) {
     case IconicState:
-        client_iconify(self, TRUE, TRUE);
+        client_iconify(self, TRUE, TRUE, FALSE);
         break;
     case NormalState:
-        client_iconify(self, FALSE, TRUE);
+        client_iconify(self, FALSE, TRUE, FALSE);
         break;
     }
 }
@@ -3267,7 +3286,7 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
         stacking_raise(CLIENT_AS_WINDOW(self));
     }
     if (iconic != self->iconic)
-        client_iconify(self, iconic, FALSE);
+        client_iconify(self, iconic, FALSE, FALSE);
 
     if (demands_attention != self->demands_attention)
         client_hilite(self, demands_attention);
@@ -3390,9 +3409,9 @@ static void client_present(ObClient *self, gboolean here, gboolean raise)
     event_halt_focus_delay();
 
     if (client_normal(self) && screen_showing_desktop)
-        screen_show_desktop(FALSE, FALSE);
+        screen_show_desktop(FALSE, self);
     if (self->iconic)
-        client_iconify(self, FALSE, here);
+        client_iconify(self, FALSE, here, FALSE);
     if (self->desktop != DESKTOP_ALL &&
         self->desktop != screen_desktop)
     {
@@ -3473,9 +3492,7 @@ gboolean client_focused(ObClient *self)
 static ObClientIcon* client_icon_recursive(ObClient *self, gint w, gint h)
 {
     guint i;
-    /* si is the smallest image >= req */
-    /* li is the largest image < req */
-    gulong size, smallest = 0xffffffff, largest = 0, si = 0, li = 0;
+    gulong min_diff, min_i;
 
     if (!self->nicons) {
         ObClientIcon *parent = NULL;
@@ -3498,20 +3515,23 @@ static ObClientIcon* client_icon_recursive(ObClient *self, gint w, gint h)
         return parent;
     }
 
-    for (i = 0; i < self->nicons; ++i) {
-        size = self->icons[i].width * self->icons[i].height;
-        if (size < smallest && size >= (unsigned)(w * h)) {
-            smallest = size;
-            si = i;
-        }
-        if (size > largest && size <= (unsigned)(w * h)) {
-            largest = size;
-            li = i;
+    /* some kind of crappy approximation to find the icon closest in size to
+       what we requested, but icons are generally all the same ratio as
+       eachother so it's good enough. */
+
+    min_diff = ABS(self->icons[0].width - w) + ABS(self->icons[0].height - h);
+    min_i = 0;
+
+    for (i = 1; i < self->nicons; ++i) {
+        gulong diff;
+
+        diff = ABS(self->icons[0].width - w) + ABS(self->icons[0].height - h);
+        if (diff < min_diff) {
+            min_diff = diff;
+            min_i = i;
         }
     }
-    if (largest == 0) /* didnt find one smaller than the requested size */
-        return &self->icons[si];
-    return &self->icons[li];
+    return &self->icons[min_i];
 }
 
 const ObClientIcon* client_icon(ObClient *self, gint w, gint h)
@@ -3685,7 +3705,7 @@ ObClient *client_search_transient(ObClient *self, ObClient *search)
                 continue;                                                     \
             if(cur->iconic)                                                   \
                 continue;                                                     \
-            if(cur->layer < c->layer && !config_resist_layers_below)          \
+            if(cur->layer == c->layer)                                        \
                 continue;
 
 #define HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end) \
This page took 0.031597 seconds and 4 git commands to generate.