]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
fixes for transients
[chaz/openbox] / openbox / client.c
index eb00e6d60b4a308e9a34d759ce1ea44df4a3ca9e..849d87e36235ef35856b3513c084878662529d62 100644 (file)
@@ -56,10 +56,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);
@@ -272,13 +271,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);
 
@@ -402,9 +402,12 @@ void client_manage(Window window)
     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
            always
@@ -414,8 +417,8 @@ void client_manage(Window window)
         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;
             }
@@ -435,7 +438,7 @@ void client_manage(Window window)
         } else {
             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);
@@ -455,7 +458,7 @@ void client_manage(Window window)
     /* 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_showhide(self);
+    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
@@ -576,34 +579,36 @@ void client_unmanage(ObClient *self)
         self->group = NULL;
     }
 
-    /* give the client its border back */
-    client_toggle_border(self, TRUE);
+    /* restore the window's original geometry so it is not lost */
+    {
+        Rect a = self->area;
+
+        if (self->fullscreen)
+            a = self->pre_fullscreen_area;
+        else if (self->max_horz || self->max_vert) {
+            if (self->max_horz) {
+                a.x = self->pre_max_area.x;
+                a.width = self->pre_max_area.width;
+            }
+            if (self->max_vert) {
+                a.y = self->pre_max_area.y;
+                a.height = self->pre_max_area.height;
+            }
+        }
+
+        /* 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 */
+
+        client_move_resize(self, a.x, a.y, a.width, a.height);
+    }
 
     /* reparent the window out of the frame, and free the frame */
     frame_release_client(self->frame, self);
     self->frame = NULL;
 
-    /* restore the window's original geometry so it is not lost */
-    if (self->fullscreen)
-        XMoveResizeWindow(ob_display, self->window,
-                          self->pre_fullscreen_area.x,
-                          self->pre_fullscreen_area.y,
-                          self->pre_fullscreen_area.width,
-                          self->pre_fullscreen_area.height);
-    else if (self->max_horz || self->max_vert) {
-        Rect a = self->area;
-        if (self->max_horz) {
-            a.x = self->pre_max_area.x;
-            a.width = self->pre_max_area.width;
-        }
-        if (self->max_vert) {
-            a.y = self->pre_max_area.y;
-            a.height = self->pre_max_area.height;
-        }
-        XMoveResizeWindow(ob_display, self->window,
-                          a.x, a.y, a.width, a.height);
-    }
-     
     if (ob_state() != OB_STATE_EXITING) {
         /* these values should not be persisted across a window
            unmapping/mapping */
@@ -616,7 +621,6 @@ void client_unmanage(ObClient *self)
         XMapWindow(ob_display, self->window);
     }
 
-
     ob_debug("Unmanaged window 0x%lx\n", self->window);
 
     /* free all data allocated in the client struct */
@@ -689,7 +693,7 @@ static ObAppSettings *client_get_settings_state(ObClient *self)
 
         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;
@@ -893,10 +897,9 @@ static void client_toggle_border(ObClient *self, gboolean show)
     if (show) {
         XSetWindowBorderWidth(ob_display, self->window, self->border_width);
 
-        /* move the client so it is back it the right spot _with_ its
-           border! */
-        if (x != oldx || y != oldy)
-            XMoveWindow(ob_display, self->window, x, y);
+        /* set border_width to 0 because there is no border to add into
+           calculations anymore */
+        self->border_width = 0;
     } else
         XSetWindowBorderWidth(ob_display, self->window, 0);
 }
@@ -948,7 +951,7 @@ static void client_get_all(ObClient *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)
@@ -968,6 +971,7 @@ static void client_get_area(ObClient *self)
     g_assert(ret != BadWindow);
 
     RECT_SET(self->area, wattrib.x, wattrib.y, wattrib.width, wattrib.height);
+    POINT_SET(self->root_pos, wattrib.x, wattrib.y);
     self->border_width = wattrib.border_width;
 
     ob_debug("client area: %d %d  %d %d\n", wattrib.x, wattrib.y,
@@ -1850,27 +1854,21 @@ void client_update_icons(ObClient *self)
         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);
         */
     }
 }
@@ -2058,6 +2056,33 @@ gboolean client_should_show(ObClient *self)
     return FALSE;
 }
 
+void client_show(ObClient *self)
+{
+
+    if (client_should_show(self)) {
+        frame_show(self->frame);
+    }
+
+    /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
+       needs to be in IconicState. This includes when it is on another
+       desktop!
+    */
+    client_change_wm_state(self);
+}
+
+void client_hide(ObClient *self)
+{
+    if (!client_should_show(self)) {
+        frame_hide(self->frame);
+    }
+
+    /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
+       needs to be in IconicState. This includes when it is on another
+       desktop!
+    */
+    client_change_wm_state(self);
+}
+
 void client_showhide(ObClient *self)
 {
 
@@ -2066,10 +2091,6 @@ void client_showhide(ObClient *self)
     }
     else {
         frame_hide(self->frame);
-
-        /* Fall back focus since we're disappearing */
-        if (focus_client == self)
-            client_unfocus(self);
     }
 
     /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
@@ -2331,9 +2352,9 @@ void client_configure_full(ObClient *self, ObCorner anchor,
                            gboolean user, gboolean final,
                            gboolean force_reply)
 {
-    gint oldw, oldh;
+    gint oldw, oldh, oldrx, oldry;
     gboolean send_resize_client;
-    gboolean moved = FALSE, resized = FALSE;
+    gboolean moved = FALSE, resized = FALSE, rootmoved = FALSE;
     guint fdecor = self->frame->decorations;
     gboolean fhorz = self->frame->max_horz;
     gint logicalw, logicalh;
@@ -2365,35 +2386,47 @@ void client_configure_full(ObClient *self, ObCorner anchor,
     if (send_resize_client && user && (w > oldw || h > oldh))
         XResizeWindow(ob_display, self->window, MAX(w, oldw), MAX(h, oldh));
 
-    /* move/resize the frame to match the request */
-    if (self->frame) {
-        if (self->decorations != fdecor || self->max_horz != fhorz)
-            moved = resized = TRUE;
-
-        if (moved || resized)
-            frame_adjust_area(self->frame, moved, resized, FALSE);
-
-        if (!resized && (force_reply || ((!user && moved) || (user && final))))
-        {
-            XEvent event;
-            event.type = ConfigureNotify;
-            event.xconfigure.display = ob_display;
-            event.xconfigure.event = self->window;
-            event.xconfigure.window = self->window;
-
-            /* root window real coords */
-            event.xconfigure.x = self->frame->area.x + self->frame->size.left -
-                self->border_width;
-            event.xconfigure.y = self->frame->area.y + self->frame->size.top -
-                self->border_width;
-            event.xconfigure.width = w;
-            event.xconfigure.height = h;
-            event.xconfigure.border_width = 0;
-            event.xconfigure.above = self->frame->plate;
-            event.xconfigure.override_redirect = FALSE;
-            XSendEvent(event.xconfigure.display, event.xconfigure.window,
-                       FALSE, StructureNotifyMask, &event);
-        }
+    /* find the frame's dimensions and move/resize it */
+    if (self->decorations != fdecor || self->max_horz != fhorz)
+        moved = resized = TRUE;
+    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))
+    {
+        XEvent event;
+
+        POINT_SET(self->root_pos,
+                  self->frame->area.x + self->frame->size.left -
+                  self->border_width,
+                  self->frame->area.y + self->frame->size.top -
+                  self->border_width);
+
+        event.type = ConfigureNotify;
+        event.xconfigure.display = ob_display;
+        event.xconfigure.event = self->window;
+        event.xconfigure.window = self->window;
+
+        /* root window real coords */
+        event.xconfigure.x = self->root_pos.x;
+        event.xconfigure.y = self->root_pos.y;
+        event.xconfigure.width = w;
+        event.xconfigure.height = h;
+        event.xconfigure.border_width = 0;
+        event.xconfigure.above = self->frame->plate;
+        event.xconfigure.override_redirect = FALSE;
+        XSendEvent(event.xconfigure.display, event.xconfigure.window,
+                   FALSE, StructureNotifyMask, &event);
     }
 
     /* if the client is shrinking, then resize the frame before the client */
@@ -3030,16 +3063,19 @@ static void client_unfocus(ObClient *self)
 
 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,
+             self->window, event_curtime, last_time,
              (user ? "user" : "application"));
-    if (!user && event_curtime &&
-        !event_time_after(event_curtime, client_last_user_time))
+
+    if (!user && event_curtime && last_time &&
+        !event_time_after(event_curtime, last_time))
     {
         client_hilite(self, TRUE);
     } else {
@@ -3305,7 +3341,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.029636 seconds and 4 git commands to generate.