a better ordering for mapping window configure events
authorDana Jansens <danakj@orodu.net>
Mon, 28 May 2007 21:08:28 +0000 (21:08 +0000)
committerDana Jansens <danakj@orodu.net>
Mon, 28 May 2007 21:08:28 +0000 (21:08 +0000)
configure the window to find where it will actually be, with all the startup states off. then apply the startup states to those dimensions

openbox/client.c

index 3456c5f..9bed250 100644 (file)
@@ -78,7 +78,8 @@ static void client_get_colormap(ObClient *self);
 static void client_change_allowed_actions(ObClient *self);
 static void client_change_state(ObClient *self);
 static void client_change_wm_state(ObClient *self);
-static void client_apply_startup_state(ObClient *self);
+static void client_apply_startup_state(ObClient *self,
+                                       gint x, gint y, gint w, gint h);
 static void client_restore_session_state(ObClient *self);
 static gboolean client_restore_session_stacking(ObClient *self);
 static ObAppSettings *client_get_settings_state(ObClient *self);
@@ -240,7 +241,8 @@ void client_manage(Window window)
     XWMHints *wmhint;
     gboolean activate = FALSE;
     ObAppSettings *settings;
-    gint placex, placey;
+    gint placex, placey, placew, placeh;
+    gboolean transient = FALSE;
 
     grab_server(TRUE);
 
@@ -364,18 +366,18 @@ void client_manage(Window window)
     /* where the frame was placed is where the window was originally */
     placex = self->area.x;
     placey = self->area.y;
+    placew = self->area.width;
+    placeh = self->area.height;
 
     /* figure out placement for the window if the window is new */
     if (ob_state() == OB_STATE_RUNNING) {
-        gboolean transient;
-
         ob_debug("Positioned: %s @ %d %d\n",
                  (!self->positioned ? "no" :
                   (self->positioned == PPosition ? "program specified" :
                    (self->positioned == USPosition ? "user specified" :
                     (self->positioned == (PPosition | USPosition) ?
                      "program + user specified" :
-                     "BADNESS !?")))), self->area.x, self->area.y);
+                     "BADNESS !?")))), placex, placey);
 
         ob_debug("Sized: %s @ %d %d\n",
                  (!self->sized ? "no" :
@@ -383,39 +385,12 @@ void client_manage(Window window)
                    (self->sized == USSize ? "user specified" :
                     (self->sized == (PSize | USSize) ?
                      "program + user specified" :
-                     "BADNESS !?")))), self->area.width, self->area.height);
+                     "BADNESS !?")))), placew, placeh);
 
         transient = place_client(self, &placex, &placey, settings);
 
-        /* if the window isn't user-positioned, then make it fit inside
-           the visible screen area on its monitor.
-
-           the monitor is chosen by place_client! */
-        if (!(self->sized & USSize)) {
-            /* make a copy to modify */
-            Rect a = *screen_area_monitor(self->desktop, client_monitor(self));
-
-            /* shrink by the frame's area */
-            a.width -= self->frame->size.left + self->frame->size.right;
-            a.height -= self->frame->size.top + self->frame->size.bottom;
-
-            /* fit the window inside the area */
-            if (self->area.width > a.width || self->area.height > a.height) {
-                self->area.width = MIN(self->area.width, a.width);
-                self->area.height = MIN(self->area.height, a.height);
-
-                ob_debug("setting window size to %dx%d\n",
-                         self->area.width, self->area.height);
-
-                /* adjust the frame to the client's new size */
-                frame_adjust_area(self->frame, FALSE, TRUE, FALSE);
-                frame_adjust_client_area(self->frame);
-            }
-        }
-
         /* make sure the window is visible. */
-        client_find_onscreen(self, &placex, &placey,
-                             self->area.width, self->area.height,
+        client_find_onscreen(self, &placex, &placey, placew, placeh,
                              /* non-normal clients has less rules, and
                                 windows that are being restored from a
                                 session do also. we can assume you want
@@ -432,33 +407,53 @@ void client_manage(Window window)
                               !self->session));
     }
 
-    ob_debug("placing window 0x%x at %d, %d with size %d x %d\n",
-             self->window, placex, placey,
-             self->area.width, self->area.height);
+    /* if the window isn't user-sized, then make it fit inside
+       the visible screen area on its monitor. Use basically the same rules
+       for forcing the window on screen in the client_find_onscreen call.
+
+       do this after place_client, it chooses the monitor! */
+    if (transient ||
+        (!(self->sized & USSize) &&
+         client_normal(self) &&
+         !self->session))
+    {
+        /* make a copy to modify */
+        Rect a = *screen_area_monitor(self->desktop, client_monitor(self));
+
+        /* shrink by the frame's area */
+        a.width -= self->frame->size.left + self->frame->size.right;
+        a.height -= self->frame->size.top + self->frame->size.bottom;
+
+        /* fit the window inside the area */
+        if (placew > a.width || self->area.height > a.height) {
+            placew = MAX(MIN(MIN(self->area.width, a.width),
+                             self->max_size.width),
+                         self->min_size.width);
+            placeh = MAX(MIN(MIN(self->area.height, a.height),
+                             self->max_size.height),
+                         self->min_size.height);
+
+            ob_debug("setting window size to %dx%d\n",
+                     self->area.width, self->area.height);
+        }
+    }
+
+
+    ob_debug("placing window 0x%x at %d, %d with size %d x %d. "
+             "some restrictions may apply\n",
+             self->window, placex, placey, placew, placeh);
     if (self->session)
-        ob_debug("  but session requested %d %d instead, overriding\n",
-                 self->session->x, self->session->y);
+        ob_debug("  but session requested %d, %d  %d x %d instead, "
+                 "overriding\n",
+                 self->session->x, self->session->y,
+                 self->session->w, self->session->h);
 
     /* do this after the window is placed, so the premax/prefullscreen numbers
        won't be all wacko!!
-    */
-    client_apply_startup_state(self);
-
-    /* move the client to its placed position, or it it's already there,
-       generate a ConfigureNotify telling the client where it is.
 
-       do this after adjusting the frame. otherwise it gets all weird and
-       clients don't work right
-
-       also do this after applying the startup state so maximize and fullscreen
-       will get the right sizes and positions if the client is starting with
-       those states
+       this also places the window
     */
-    client_configure(self, placex, placey,
-                     self->area.width, self->area.height,
-                     self->border_width,
-                     FALSE, TRUE);
-
+    client_apply_startup_state(self, placex, placey, placew, placeh);
 
     if (activate) {
         guint32 last_time = focus_client ?
@@ -2547,44 +2542,59 @@ gboolean client_enter_focusable(ObClient *self)
 }
 
 
-static void client_apply_startup_state(ObClient *self)
+static void client_apply_startup_state(ObClient *self,
+                                       gint x, gint y, gint w, gint h)
 {
-    /* set the desktop hint, to make sure that it always exists */
-    PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
+    /* save the states that we are going to apply */
+    gboolean iconic = self->iconic;
+    gboolean fullscreen = self->fullscreen;
+    gboolean undecorated = self->undecorated;
+    gboolean shaded = self->shaded;
+    gboolean demands_attention = self->demands_attention;
+    gboolean max_horz = self->max_horz;
+    gboolean max_vert = self->max_vert;
 
-    /* these are in a carefully crafted order.. */
+    /* turn them all off in the client, so they won't affect the window
+       being placed */
+    self->iconic = self->fullscreen = self->undecorated = self->shaded =
+        self->demands_attention = self->max_horz = self->max_vert = FALSE;
 
-    if (self->iconic) {
-        self->iconic = FALSE;
+    /* move the client to its placed position, or it it's already there,
+       generate a ConfigureNotify telling the client where it is.
+
+       do this after adjusting the frame. otherwise it gets all weird and
+       clients don't work right
+
+       do this before applying the states so they have the correct
+       pre-max/pre-fullscreen values
+    */
+    client_configure(self, x, y, w, h, self->border_width, FALSE, TRUE);
+    ob_debug("placed window 0x%x at %d, %d with size %d x %d\n",
+             self->window, self->area.x, self->area.y,
+             self->area.width, self->area.height);
+
+    /* apply the states. these are in a carefully crafted order.. */
+
+    if (iconic)
         client_iconify(self, TRUE, FALSE, TRUE);
-    }
-    if (self->fullscreen) {
-        self->fullscreen = FALSE;
+    if (fullscreen)
         client_fullscreen(self, TRUE);
-    }
-    if (self->undecorated) {
-        self->undecorated = FALSE;
+    if (undecorated)
         client_set_undecorated(self, TRUE);
-    }
-    if (self->shaded) {
-        self->shaded = FALSE;
+    if (shaded)
         client_shade(self, TRUE);
-    }
-    if (self->demands_attention) {
-        self->demands_attention = FALSE;
+    if (demands_attention)
         client_hilite(self, TRUE);
-    }
   
-    if (self->max_vert && self->max_horz) {
-        self->max_vert = self->max_horz = FALSE;
+    if (max_vert && max_horz)
         client_maximize(self, TRUE, 0);
-    } else if (self->max_vert) {
-        self->max_vert = FALSE;
+    else if (max_vert)
         client_maximize(self, TRUE, 2);
-    } else if (self->max_horz) {
-        self->max_horz = FALSE;
+    else if (max_horz)
         client_maximize(self, TRUE, 1);
-    }
+
+    /* set the desktop hint, to make sure that it always exists */
+    PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
 
     /* nothing to do for the other states:
        skip_taskbar
@@ -3490,6 +3500,8 @@ gboolean client_focus(ObClient *self)
             /* update the focus lists */
             focus_order_to_top(self);
         }
+        ob_debug_type(OB_DEBUG_FOCUS,
+                      "Client %s can't be focused\n", self->title);
         return FALSE;
     }