]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
better synthetic configurenotify handling. in particular..
[chaz/openbox] / openbox / client.c
index 6866e8d8da8749cabbd7a5801c65b556b736cd1c..43a283cdd27926cb22e80ec7c13ed70be85e1fde 100644 (file)
@@ -272,7 +272,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 = ~0; /* maximum value, always newer than the real time */
+    self->user_time = client_last_user_time;
 
     client_get_all(self);
     client_restore_session_state(self);
@@ -455,7 +455,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 +576,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 +618,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 */
@@ -893,10 +894,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);
 }
@@ -968,6 +968,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,
@@ -2058,6 +2059,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 +2094,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
@@ -2134,8 +2158,12 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y)
         pos = TRUE;
     }
 
-    /* if the client didn't get positioned yet, then do so now */
-    if (!pos && (ox != x || oy != y)) {
+    /* if the client didn't get positioned yet, then do so now
+       call client_move even if the window is not being moved anywhere, because
+       when we reparent it and decorate it, it is getting moved and we need to
+       be telling it so with a ConfigureNotify event.
+    */
+    if (!pos) {
         /* use the saved position */
         self->area.x = ox;
         self->area.y = oy;
@@ -2163,58 +2191,7 @@ void client_try_configure(ObClient *self, ObCorner anchor,
        the updated frame dimensions. */
     frame_adjust_area(self->frame, TRUE, TRUE, TRUE);
 
-    /* gets the frame's position */
-    frame_client_gravity(self->frame, x, y);
-
-    /* these positions are frame positions, not client positions */
-
-    /* set the size and position if fullscreen */
-    if (self->fullscreen) {
-        Rect *a;
-        guint i;
-
-        i = screen_find_monitor(&desired_area);
-        a = screen_physical_area_monitor(i);
-
-        *x = a->x;
-        *y = a->y;
-        *w = a->width;
-        *h = a->height;
-
-        user = FALSE; /* ignore that increment etc shit when in fullscreen */
-    } else {
-        Rect *a;
-        guint i;
-
-        i = screen_find_monitor(&desired_area);
-        a = screen_area_monitor(self->desktop, i);
-
-        /* set the size and position if maximized */
-        if (self->max_horz) {
-            *x = a->x;
-            *w = a->width - self->frame->size.left - self->frame->size.right;
-        }
-        if (self->max_vert) {
-            *y = a->y;
-            *h = a->height - self->frame->size.top - self->frame->size.bottom;
-        }
-    }
-
-    /* gets the client's position */
-    frame_frame_gravity(self->frame, x, y);
-
-    /* these override the above states! if you cant move you can't move! */
-    if (user) {
-        if (!(self->functions & OB_CLIENT_FUNC_MOVE)) {
-            *x = self->area.x;
-            *y = self->area.y;
-        }
-        if (!(self->functions & OB_CLIENT_FUNC_RESIZE)) {
-            *w = self->area.width;
-            *h = self->area.height;
-        }
-    }
-
+    /* work within the prefered sizes given by the window */
     if (!(*w == self->area.width && *h == self->area.height)) {
         gint basew, baseh, minw, minh;
 
@@ -2297,6 +2274,62 @@ void client_try_configure(ObClient *self, ObCorner anchor,
         *h += self->base_size.height;
     }
 
+    /* gets the frame's position */
+    frame_client_gravity(self->frame, x, y);
+
+    /* these positions are frame positions, not client positions */
+
+    /* set the size and position if fullscreen */
+    if (self->fullscreen) {
+        Rect *a;
+        guint i;
+
+        i = screen_find_monitor(&desired_area);
+        a = screen_physical_area_monitor(i);
+
+        *x = a->x;
+        *y = a->y;
+        *w = a->width;
+        *h = a->height;
+
+        user = FALSE; /* ignore if the client can't be moved/resized when it
+                         is entering fullscreen */
+    } else if (self->max_horz || self->max_vert) {
+        Rect *a;
+        guint i;
+
+        i = screen_find_monitor(&desired_area);
+        a = screen_area_monitor(self->desktop, i);
+
+        /* set the size and position if maximized */
+        if (self->max_horz) {
+            *x = a->x;
+            *w = a->width - self->frame->size.left - self->frame->size.right;
+        }
+        if (self->max_vert) {
+            *y = a->y;
+            *h = a->height - self->frame->size.top - self->frame->size.bottom;
+        }
+
+        /* maximizing is not allowed if the user can't move+resize the window
+         */
+    }
+
+    /* gets the client's position */
+    frame_frame_gravity(self->frame, x, y);
+
+    /* these override the above states! if you cant move you can't move! */
+    if (user) {
+        if (!(self->functions & OB_CLIENT_FUNC_MOVE)) {
+            *x = self->area.x;
+            *y = self->area.y;
+        }
+        if (!(self->functions & OB_CLIENT_FUNC_RESIZE)) {
+            *w = self->area.width;
+            *h = self->area.height;
+        }
+    }
+
     g_assert(*w > 0);
     g_assert(*h > 0);
 
@@ -2322,9 +2355,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;
@@ -2356,35 +2389,45 @@ 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 != (self->frame->area.x + self->frame->size.left -
+                           self->border_width) ||
+                 oldry != (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 */
@@ -2963,11 +3006,6 @@ 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 */
This page took 0.035721 seconds and 4 git commands to generate.