]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
fix fullscreen windows being stuck in the wrong layer when they come out of
[chaz/openbox] / openbox / client.c
index 7a01e5109bce9b580b32b173f6056b3e0a315088..16c249378c3ec85de487e72b5b1c8b64e817bb25 100644 (file)
@@ -80,7 +80,7 @@ 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, gint x, gint y);
+static void client_apply_startup_state(ObClient *self);
 static void client_restore_session_state(ObClient *self);
 static gboolean client_restore_session_stacking(ObClient *self);
 static ObAppSettings *client_get_settings_state(ObClient *self);
@@ -265,7 +265,6 @@ void client_manage(Window window)
     XWMHints *wmhint;
     gboolean activate = FALSE;
     ObAppSettings *settings;
-    gint newx, newy;
 
     grab_server(TRUE);
 
@@ -383,20 +382,21 @@ void client_manage(Window window)
         activate = TRUE;
     }
 
-    /* get the current position */
-    newx = self->area.x;
-    newy = self->area.y;
-
     /* figure out placement for the window */
     if (ob_state() == OB_STATE_RUNNING) {
         gboolean transient;
 
-        transient = place_client(self, &newx, &newy, settings);
+        ob_debug("Positioned: %s @ %d %d\n",
+                 (!self->positioned ? "no" :
+                  (self->positioned == PPosition ? "program specified" :
+                   (self->positioned == USPosition ? "user specified" :
+                    "BADNESS !?"))), self->area.x, self->area.y);
+
+        transient = place_client(self, &self->area.x, &self->area.y, settings);
 
         /* make sure the window is visible. */
-        client_find_onscreen(self, &newx, &newy,
-                             self->area.width,
-                             self->area.height,
+        client_find_onscreen(self, &self->area.x, &self->area.y,
+                             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
@@ -414,19 +414,32 @@ void client_manage(Window window)
                               !self->session));
     }
 
-    /* do this after the window is placed, so the premax/prefullscreen numbers
-       won't be all wacko!!
-       also, this moves the window to the position where it has been placed
-    */
     ob_debug("placing window 0x%x at %d, %d with size %d x %d\n",
-             self->window, newx, newy, self->area.width, self->area.height);
+             self->window, self->area.x, self->area.y,
+             self->area.width, self->area.height);
     if (self->session)
-        ob_debug("session requested %d %d\n",
+        ob_debug("  but session requested %d %d instead, overriding\n",
                  self->session->x, self->session->y);
 
-    client_apply_startup_state(self, newx, newy);
+    /* adjust the frame to the client's size before showing the window */
+    frame_adjust_area(self->frame, FALSE, TRUE, FALSE);
+    frame_adjust_client_area(self->frame);
 
-    mouse_grab_for_client(self, TRUE);
+
+    /* 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 */
+    client_configure_full(self, self->area.x, self->area.y,
+                          self->area.width, self->area.height,
+                          FALSE, TRUE);
+
+    /* do this after the window is placed, so the premax/prefullscreen numbers
+       won't be all wacko!!
+       also, this moves the window to the position where it has been placed
+    */
+    client_apply_startup_state(self);
 
     if (activate) {
         guint32 last_time = focus_client ?
@@ -494,8 +507,7 @@ 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);
+    mouse_grab_for_client(self, TRUE);
 
     /* 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
@@ -518,7 +530,8 @@ void client_manage(Window window)
     /* update the list hints */
     client_set_list();
 
-    ob_debug("Managed window 0x%lx (%s)\n", window, self->class);
+    ob_debug("Managed window 0x%lx plate 0x%x (%s)\n",
+             window, self->frame->plate, self->class);
 
     return;
 }
@@ -560,7 +573,8 @@ void client_unmanage(ObClient *self)
     guint j;
     GSList *it;
 
-    ob_debug("Unmanaging window: %lx (%s) (%s)\n", self->window,
+    ob_debug("Unmanaging window: 0x%x plate 0x%x (%s) (%s)\n",
+             self->window, self->frame->plate,
              self->class, self->title ? self->title : "");
 
     g_assert(self != NULL);
@@ -1174,7 +1188,7 @@ static void client_get_state(ObClient *self)
                 self->below = TRUE;
             else if (state[i] == prop_atoms.net_wm_state_demands_attention)
                 self->demands_attention = TRUE;
-            else if (state[i] == prop_atoms.openbox_wm_state_undecorated)
+            else if (state[i] == prop_atoms.ob_wm_state_undecorated)
                 self->undecorated = TRUE;
         }
 
@@ -1593,7 +1607,9 @@ void client_setup_decor_and_functions(ObClient *self)
          OB_CLIENT_FUNC_ICONIFY |
          OB_CLIENT_FUNC_MAXIMIZE |
          OB_CLIENT_FUNC_SHADE |
-         OB_CLIENT_FUNC_CLOSE);
+         OB_CLIENT_FUNC_CLOSE |
+         OB_CLIENT_FUNC_BELOW |
+         OB_CLIENT_FUNC_ABOVE);
 
     if (!(self->min_size.width < self->max_size.width ||
           self->min_size.height < self->max_size.height))
@@ -1625,10 +1641,15 @@ void client_setup_decor_and_functions(ObClient *self)
         self->functions = OB_CLIENT_FUNC_MOVE;
 
     case OB_CLIENT_TYPE_DESKTOP:
-    case OB_CLIENT_TYPE_DOCK:
         /* these windows are not manipulated by the window manager */
         self->decorations = 0;
         self->functions = 0;
+
+    case OB_CLIENT_TYPE_DOCK:
+        /* these windows are not manipulated by the window manager, but they
+           can set below layer which has a special meaning */
+        self->decorations = 0;
+        self->functions = OB_CLIENT_FUNC_BELOW;
         break;
     }
 
@@ -1718,7 +1739,7 @@ void client_setup_decor_and_functions(ObClient *self)
 
 static void client_change_allowed_actions(ObClient *self)
 {
-    gulong actions[9];
+    gulong actions[11];
     gint num = 0;
 
     /* desktop windows are kept on all desktops */
@@ -1741,6 +1762,10 @@ static void client_change_allowed_actions(ObClient *self)
         actions[num++] = prop_atoms.net_wm_action_maximize_horz;
         actions[num++] = prop_atoms.net_wm_action_maximize_vert;
     }
+    if (self->functions & OB_CLIENT_FUNC_ABOVE)
+        actions[num++] = prop_atoms.net_wm_action_above;
+    if (self->functions & OB_CLIENT_FUNC_BELOW)
+        actions[num++] = prop_atoms.net_wm_action_below;
 
     PROP_SETA32(self->window, net_wm_allowed_actions, atom, actions, num);
 
@@ -2278,7 +2303,7 @@ static void client_change_state(ObClient *self)
     if (self->demands_attention)
         netstate[num++] = prop_atoms.net_wm_state_demands_attention;
     if (self->undecorated)
-        netstate[num++] = prop_atoms.openbox_wm_state_undecorated;
+        netstate[num++] = prop_atoms.ob_wm_state_undecorated;
     PROP_SETA32(self->window, net_wm_state, atom, netstate, num);
 
     if (self->frame)
@@ -2342,9 +2367,12 @@ static ObStackingLayer calc_layer(ObClient *self)
                 self->frame->size.bottom == 0 && self->frame->size.top == 0 &&
                 RECT_EQUAL(self->area,
                            *screen_physical_area_monitor
-                           (client_monitor(self)))))) &&
-             (client_focused(self) || client_search_focus_tree(self)))
-        l = OB_STACKING_LAYER_FULLSCREEN;
+                           (client_monitor(self))))))) {
+        if (client_focused(self) || client_search_focus_tree(self))
+            l = OB_STACKING_LAYER_FULLSCREEN;
+        else
+            l = OB_STACKING_LAYER_FULLSCREEN_BELOW;
+    }
     else if (self->above) l = OB_STACKING_LAYER_ABOVE;
     else if (self->below) l = OB_STACKING_LAYER_BELOW;
     else l = OB_STACKING_LAYER_NORMAL;
@@ -2475,17 +2503,8 @@ gboolean client_enter_focusable(ObClient *self)
 }
 
 
-static void client_apply_startup_state(ObClient *self, gint x, gint y)
+static void client_apply_startup_state(ObClient *self)
 {
-    gboolean pos = FALSE; /* has the window's position been configured? */
-    gint ox, oy;
-
-    /* save the position, and set self->area for these to use */
-    ox = self->area.x;
-    oy = self->area.y;
-    self->area.x = x;
-    self->area.y = y;
-
     /* set the desktop hint, to make sure that it always exists */
     PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
 
@@ -2498,7 +2517,6 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y)
     if (self->fullscreen) {
         self->fullscreen = FALSE;
         client_fullscreen(self, TRUE);
-        pos = TRUE;
     }
     if (self->undecorated) {
         self->undecorated = FALSE;
@@ -2516,27 +2534,12 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y)
     if (self->max_vert && self->max_horz) {
         self->max_vert = self->max_horz = FALSE;
         client_maximize(self, TRUE, 0);
-        pos = TRUE;
     } else if (self->max_vert) {
         self->max_vert = FALSE;
         client_maximize(self, TRUE, 2);
-        pos = TRUE;
     } else if (self->max_horz) {
         self->max_horz = FALSE;
         client_maximize(self, TRUE, 1);
-        pos = TRUE;
-    }
-
-    /* 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;
-        client_move(self, x, y);
     }
 
     /* nothing to do for the other states:
@@ -2750,8 +2753,9 @@ void client_configure_full(ObClient *self, gint x, gint y, gint w, gint h,
                                     (resized && config_resize_redraw))));
 
     /* if the client is enlarging, then resize the client before the frame */
-    if (send_resize_client && user && (w > oldw || h > oldh)) {
-        XResizeWindow(ob_display, self->window, MAX(w, oldw), MAX(h, oldh));
+    if (send_resize_client && (w > oldw || h > oldh)) {
+        XResizeWindow(ob_display, self->window,
+                      MAX(w, oldw), MAX(h, oldh));
         /* resize the plate to show the client padding color underneath */
         frame_adjust_client_area(self->frame);
     }
@@ -2793,11 +2797,12 @@ void client_configure_full(ObClient *self, gint x, gint y, gint w, gint h,
     }
 
     /* if the client is shrinking, then resize the frame before the client */
-    if (send_resize_client && (!user || (w <= oldw || h <= oldh))) {
+    if (send_resize_client && (w <= oldw || h <= oldh)) {
         /* resize the plate to show the client padding color underneath */
         frame_adjust_client_area(self->frame);
 
-        XResizeWindow(ob_display, self->window, w, h);
+        if (send_resize_client)
+            XResizeWindow(ob_display, self->window, w, h);
     }
 
     XFlush(ob_display);
@@ -2812,7 +2817,6 @@ void client_fullscreen(ObClient *self, gboolean fs)
 
     self->fullscreen = fs;
     client_change_state(self); /* change the state hints on the client */
-    client_calc_layer(self);   /* and adjust out layer/stacking */
 
     if (fs) {
         self->pre_fullscreen_area = self->area;
@@ -2827,36 +2831,36 @@ void client_fullscreen(ObClient *self, gboolean fs)
             self->pre_fullscreen_area.height = self->pre_max_area.height;
         }
 
-        /* these are not actually used cuz client_configure will set them
-           as appropriate when the window is fullscreened */
-        x = y = w = h = 0;
+        /* these will help configure_full figure out where to fullscreen
+           the window */
+        x = self->area.x;
+        y = self->area.y;
+        w = self->area.width;
+        h = self->area.height;
     } else {
-        Rect *a;
+        g_assert(self->pre_fullscreen_area.width > 0 &&
+                 self->pre_fullscreen_area.height > 0);
 
-        if (self->pre_fullscreen_area.width > 0 &&
-            self->pre_fullscreen_area.height > 0)
-        {
-            x = self->pre_fullscreen_area.x;
-            y = self->pre_fullscreen_area.y;
-            w = self->pre_fullscreen_area.width;
-            h = self->pre_fullscreen_area.height;
-            RECT_SET(self->pre_fullscreen_area, 0, 0, 0, 0);
-        } else {
-            /* pick some fallbacks... */
-            a = screen_area_monitor(self->desktop, 0);
-            x = a->x + a->width / 4;
-            y = a->y + a->height / 4;
-            w = a->width / 2;
-            h = a->height / 2;
-        }
+        x = self->pre_fullscreen_area.x;
+        y = self->pre_fullscreen_area.y;
+        w = self->pre_fullscreen_area.width;
+        h = self->pre_fullscreen_area.height;
+        RECT_SET(self->pre_fullscreen_area, 0, 0, 0, 0);
     }
 
     client_setup_decor_and_functions(self);
 
     client_move_resize(self, x, y, w, h);
 
-    /* try focus us when we go into fullscreen mode */
-    client_focus(self);
+    /* and adjust our layer/stacking. do this after resizing the window,
+       and applying decorations, because windows which fill the screen are
+       considered "fullscreen" and it affects their layer */
+    client_calc_layer(self);
+
+    if (fs) {
+        /* try focus us when we go into fullscreen mode */
+        client_focus(self);
+    }
 }
 
 static void client_iconify_recursive(ObClient *self,
@@ -2944,8 +2948,8 @@ void client_maximize(ObClient *self, gboolean max, gint dir)
         if (dir == 2 && !self->max_vert) return;
     }
 
-    /* we just tell it to configure in the same place and client_configure
-       worries about filling the screen with the window */
+    /* these will help configure_full figure out which screen to fill with
+       the window */
     x = self->area.x;
     y = self->area.y;
     w = self->area.width;
@@ -2963,34 +2967,23 @@ void client_maximize(ObClient *self, gboolean max, gint dir)
                      self->pre_max_area.width, self->area.height);
         }
     } else {
-        Rect *a;
-
-        a = screen_area_monitor(self->desktop, 0);
         if ((dir == 0 || dir == 1) && self->max_horz) { /* horz */
-            if (self->pre_max_area.width > 0) {
-                x = self->pre_max_area.x;
-                w = self->pre_max_area.width;
+            g_assert(self->pre_max_area.width > 0);
 
-                RECT_SET(self->pre_max_area, 0, self->pre_max_area.y,
-                         0, self->pre_max_area.height);
-            } else {
-                /* pick some fallbacks... */
-                x = a->x + a->width / 4;
-                w = a->width / 2;
-            }
+            x = self->pre_max_area.x;
+            w = self->pre_max_area.width;
+
+            RECT_SET(self->pre_max_area, 0, self->pre_max_area.y,
+                     0, self->pre_max_area.height);
         }
         if ((dir == 0 || dir == 2) && self->max_vert) { /* vert */
-            if (self->pre_max_area.height > 0) {
-                y = self->pre_max_area.y;
-                h = self->pre_max_area.height;
+            g_assert(self->pre_max_area.height > 0);
 
-                RECT_SET(self->pre_max_area, self->pre_max_area.x, 0,
-                         self->pre_max_area.width, 0);
-            } else {
-                /* pick some fallbacks... */
-                y = a->y + a->height / 4;
-                h = a->height / 2;
-            }
+            y = self->pre_max_area.y;
+            h = self->pre_max_area.height;
+
+            RECT_SET(self->pre_max_area, self->pre_max_area.x, 0,
+                     self->pre_max_area.width, 0);
         }
     }
 
@@ -3229,7 +3222,7 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
                 action = self->demands_attention ?
                     prop_atoms.net_wm_state_remove :
                     prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.openbox_wm_state_undecorated)
+            else if (state == prop_atoms.ob_wm_state_undecorated)
                 action = undecorated ? prop_atoms.net_wm_state_remove :
                     prop_atoms.net_wm_state_add;
         }
@@ -3259,7 +3252,7 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
                 below = TRUE;
             } else if (state == prop_atoms.net_wm_state_demands_attention) {
                 demands_attention = TRUE;
-            } else if (state == prop_atoms.openbox_wm_state_undecorated) {
+            } else if (state == prop_atoms.ob_wm_state_undecorated) {
                 undecorated = TRUE;
             }
 
@@ -3286,7 +3279,7 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
                 below = FALSE;
             } else if (state == prop_atoms.net_wm_state_demands_attention) {
                 demands_attention = FALSE;
-            } else if (state == prop_atoms.openbox_wm_state_undecorated) {
+            } else if (state == prop_atoms.ob_wm_state_undecorated) {
                 undecorated = FALSE;
             }
         }
@@ -3348,8 +3341,6 @@ ObClient *client_focus_target(ObClient *self)
 
 gboolean client_can_focus(ObClient *self)
 {
-    XEvent ev;
-
     /* choose the correct target */
     self = client_focus_target(self);
 
@@ -3359,24 +3350,6 @@ gboolean client_can_focus(ObClient *self)
     if (!(self->can_focus || self->focus_notify))
         return FALSE;
 
-    /* do a check to see if the window has already been unmapped or destroyed
-       do this intelligently while watching out for unmaps we've generated
-       (ignore_unmaps > 0) */
-    if (XCheckTypedWindowEvent(ob_display, self->window,
-                               DestroyNotify, &ev)) {
-        XPutBackEvent(ob_display, &ev);
-        return FALSE;
-    }
-    while (XCheckTypedWindowEvent(ob_display, self->window,
-                                  UnmapNotify, &ev)) {
-        if (self->ignore_unmaps) {
-            self->ignore_unmaps--;
-        } else {
-            XPutBackEvent(ob_display, &ev);
-            return FALSE;
-        }
-    }
-
     return TRUE;
 }
 
@@ -3751,8 +3724,6 @@ ObClient *client_search_transient(ObClient *self, ObClient *search)
             if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL) \
                 continue;                                                     \
             if(cur->iconic)                                                   \
-                continue;                                                     \
-            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.032409 seconds and 4 git commands to generate.