]> Dogcows Code - chaz/openbox/blobdiff - openbox/frame.c
xinerama support like crazy for struts and everything else too. this probably crashes...
[chaz/openbox] / openbox / frame.c
index 51de9321c550f98f234c4747424e1385f76df5a3..6aae7a2a15c8d56738ac80df9973b5bff93eff90 100644 (file)
@@ -31,9 +31,9 @@
 #include "screen.h"
 #include "render/theme.h"
 
-#define PLATE_EVENTMASK (SubstructureRedirectMask | FocusChangeMask)
 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
-                         ButtonPressMask | ButtonReleaseMask)
+                         ButtonPressMask | ButtonReleaseMask | \
+                         SubstructureRedirectMask | FocusChangeMask)
 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
                            ButtonMotionMask | PointerMotionMask | \
                            EnterWindowMask | LeaveWindowMask)
@@ -41,7 +41,7 @@
 #define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */
 #define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 60) /* 60 Hz */
 
-#define FRAME_HANDLE_Y(f) (f->size.top + f->client->area.height + f->cbwidth_y)
+#define FRAME_HANDLE_Y(f) (f->size.top + f->client->area.height + f->cbwidth_b)
 
 static void flash_done(gpointer data);
 static gboolean flash_timeout(gpointer data);
@@ -95,7 +95,7 @@ ObFrame *frame_new(ObClient *client)
 
     /* create the non-visible decor windows */
 
-    mask = CWEventMask;
+    mask = 0;
     if (visual) {
         /* client has a 32-bit visual */
         mask |= CWColormap | CWBackPixel | CWBorderPixel;
@@ -107,21 +107,22 @@ ObFrame *frame_new(ObClient *client)
         attrib.background_pixel = BlackPixel(ob_display, ob_screen);
         attrib.border_pixel = BlackPixel(ob_display, ob_screen);
     }
-    attrib.event_mask = FRAME_EVENTMASK;
     self->window = createWindow(RootWindow(ob_display, ob_screen), visual,
                                 mask, &attrib);
 
-    mask &= ~CWEventMask;
-    self->plate = createWindow(self->window, visual, mask, &attrib);
-
     /* create the visible decor windows */
 
-    mask = CWEventMask;
+    mask = 0;
     if (visual) {
         /* client has a 32-bit visual */
         mask |= CWColormap | CWBackPixel | CWBorderPixel;
         attrib.colormap = RrColormap(ob_rr_inst);
     }
+
+    self->backback = createWindow(self->window, NULL, mask, &attrib);
+    self->backfront = createWindow(self->backback, NULL, mask, &attrib);
+
+    mask |= CWEventMask;
     attrib.event_mask = ELEMENT_EVENTMASK;
     self->title = createWindow(self->window, NULL, mask, &attrib);
     self->titleleft = createWindow(self->window, NULL, mask, &attrib);
@@ -172,8 +173,9 @@ ObFrame *frame_new(ObClient *client)
     self->focused = FALSE;
 
     /* the other stuff is shown based on decor settings */
-    XMapWindow(ob_display, self->plate);
     XMapWindow(ob_display, self->label);
+    XMapWindow(ob_display, self->backback);
+    XMapWindow(ob_display, self->backfront);
 
     self->max_press = self->close_press = self->desk_press = 
         self->iconify_press = self->shade_press = FALSE;
@@ -295,8 +297,7 @@ void frame_adjust_shape(ObFrame *self)
             xrect[0].x = 0;
             xrect[0].y = 0;
             xrect[0].width = self->area.width;
-            xrect[0].height = ob_rr_theme->title_height +
-                self->bwidth + self->rbwidth;
+            xrect[0].height = self->size.top;
             ++num;
         }
 
@@ -334,20 +335,27 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
         self->max_horz = self->client->max_horz;
         self->max_vert = self->client->max_vert;
 
-        if (self->decorations & OB_FRAME_DECOR_BORDER) {
+        if (self->decorations & OB_FRAME_DECOR_BORDER ||
+            (self->client->undecorated && config_theme_keepborder))
             self->bwidth = ob_rr_theme->fbwidth;
-            self->cbwidth_x = ob_rr_theme->cbwidthx;
-            self->cbwidth_y = ob_rr_theme->cbwidthy;
-        } else {
-            self->bwidth = self->cbwidth_x = self->cbwidth_y = 0;
-        }
-        self->rbwidth = self->bwidth;
+        else
+            self->bwidth = 0;
+
+        if (self->decorations & OB_FRAME_DECOR_BORDER) {
+            self->cbwidth_l = self->cbwidth_r = ob_rr_theme->cbwidthx;
+            self->cbwidth_t = self->cbwidth_b = ob_rr_theme->cbwidthy;
+        } else
+            self->cbwidth_l = self->cbwidth_t =
+                self->cbwidth_r = self->cbwidth_b = 0;
 
         if (self->max_horz) {
-            self->cbwidth_x = 0;
+            self->cbwidth_l = self->cbwidth_r = 0;
             self->width = self->client->area.width - self->bwidth * 2;
+            if (self->max_vert)
+                self->cbwidth_b = 0;
         } else
-            self->width = self->client->area.width + self->cbwidth_x * 2;
+            self->width = self->client->area.width +
+                self->cbwidth_l + self->cbwidth_r;
 
         /* some elements are sized based of the width, so don't let them have
            negative values */
@@ -355,13 +363,13 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                           (ob_rr_theme->grip_width + self->bwidth) * 2 + 1);
 
         STRUT_SET(self->size,
-                  self->cbwidth_x + (!self->max_horz ? self->bwidth : 0),
-                  self->cbwidth_y + self->bwidth,
-                  self->cbwidth_x + (!self->max_horz ? self->bwidth : 0),
-                  self->cbwidth_y + self->bwidth);
+                  self->cbwidth_l + (!self->max_horz ? self->bwidth : 0),
+                  self->cbwidth_t + self->bwidth,
+                  self->cbwidth_r + (!self->max_horz ? self->bwidth : 0),
+                  self->cbwidth_b + (!self->max_horz || !self->max_vert ? self->bwidth : 0));
 
         if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
-            self->size.top += ob_rr_theme->title_height + self->rbwidth;
+            self->size.top += ob_rr_theme->title_height + self->bwidth;
         if (self->decorations & OB_FRAME_DECOR_HANDLE &&
             ob_rr_theme->handle_height > 0)
         {
@@ -371,41 +379,49 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
         /* position/size and map/unmap all the windows */
 
         if (!fake) {
-            if (self->cbwidth_x) {
+            if (self->cbwidth_l) {
                 XMoveResizeWindow(ob_display, self->innerleft,
-                                  self->size.left - self->cbwidth_x,
+                                  self->size.left - self->cbwidth_l,
                                   self->size.top,
-                                  self->cbwidth_x, self->client->area.height);
+                                  self->cbwidth_l, self->client->area.height);
+
+                XMapWindow(ob_display, self->innerleft);
+            } else
+                XUnmapWindow(ob_display, self->innerleft);
+
+            if (self->cbwidth_r) {
                 XMoveResizeWindow(ob_display, self->innerright,
                                   self->size.left + self->client->area.width,
                                   self->size.top,
-                                  self->cbwidth_x, self->client->area.height);
+                                  self->cbwidth_r, self->client->area.height);
 
-                XMapWindow(ob_display, self->innerleft);
                 XMapWindow(ob_display, self->innerright);
-            } else {
-                XUnmapWindow(ob_display, self->innerleft);
+            } else
                 XUnmapWindow(ob_display, self->innerright);
-            }
 
-            if (self->cbwidth_y) {
+            if (self->cbwidth_t) {
                 XMoveResizeWindow(ob_display, self->innertop,
-                                  self->size.left - self->cbwidth_x,
-                                  self->size.top - self->cbwidth_y,
+                                  self->size.left - self->cbwidth_l,
+                                  self->size.top - self->cbwidth_t,
                                   self->client->area.width +
-                                  self->cbwidth_x * 2, self->cbwidth_y);
+                                  self->cbwidth_l + self->cbwidth_r,
+                                  self->cbwidth_t);
+
+                XMapWindow(ob_display, self->innertop);
+            } else
+                XUnmapWindow(ob_display, self->innertop);
+
+            if (self->cbwidth_b) {
                 XMoveResizeWindow(ob_display, self->innerbottom,
-                                  self->size.left - self->cbwidth_x,
+                                  self->size.left - self->cbwidth_l,
                                   self->size.top + self->client->area.height,
                                   self->client->area.width +
-                                  self->cbwidth_x * 2, self->cbwidth_y);
+                                  self->cbwidth_l + self->cbwidth_r,
+                                  self->cbwidth_b);
 
-                XMapWindow(ob_display, self->innertop);
                 XMapWindow(ob_display, self->innerbottom);
-            } else {
-                XUnmapWindow(ob_display, self->innertop);
+            } else
                 XUnmapWindow(ob_display, self->innerbottom);
-            }
 
             if (self->bwidth) {
                 gint titlesides;
@@ -456,14 +472,12 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                 XMapWindow(ob_display, self->titletopleft);
                 XMapWindow(ob_display, self->titletopright);
 
-                if (self->decorations & OB_FRAME_DECOR_TITLEBAR &&
-                    self->rbwidth)
-                {
+                if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
                     XMoveResizeWindow(ob_display, self->titlebottom,
                                       self->bwidth,
                                       ob_rr_theme->title_height + self->bwidth,
                                       self->width,
-                                      self->rbwidth);
+                                      self->bwidth);
 
                     XMapWindow(ob_display, self->titlebottom);
                 } else
@@ -520,7 +534,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
             layout_title(self);
 
         if (!fake) {
-            if (self->bwidth) {
+            if (self->bwidth && self->size.bottom) {
                 XMoveResizeWindow(ob_display, self->handlebottom,
                                   ob_rr_theme->grip_width +
                                   self->bwidth * 2,
@@ -536,11 +550,11 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                   self->size.bottom -
                                   (!self->max_horz ?
                                    ob_rr_theme->grip_width :
-                                   self->size.bottom),
+                                   self->size.bottom - self->cbwidth_b),
                                   self->bwidth,
                                   (!self->max_horz ?
                                    ob_rr_theme->grip_width :
-                                   self->size.bottom));
+                                   self->size.bottom - self->cbwidth_b));
                 XMoveResizeWindow(ob_display, self->rgripright,
                                   self->size.left + self->client->area.width +
                                   self->size.right - self->bwidth,
@@ -548,11 +562,11 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                   self->size.bottom -
                                   (!self->max_horz ?
                                    ob_rr_theme->grip_width :
-                                   self->size.bottom),
+                                   self->size.bottom - self->cbwidth_b),
                                   self->bwidth,
                                   (!self->max_horz ?
                                    ob_rr_theme->grip_width :
-                                   self->size.bottom));
+                                   self->size.bottom - self->cbwidth_b));
 
                 XMoveResizeWindow(ob_display, self->lgripbottom,
                                   self->bwidth,
@@ -699,7 +713,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
             if (self->bwidth && !self->max_horz) {
                 XMoveResizeWindow(ob_display, self->right,
                                   self->client->area.width +
-                                  self->cbwidth_x * 2 + self->bwidth,
+                                  self->cbwidth_l + self->cbwidth_r + self->bwidth,
                                   self->bwidth + ob_rr_theme->grip_width,
                                   self->bwidth,
                                   self->client->area.height +
@@ -710,14 +724,10 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
             } else
                 XUnmapWindow(ob_display, self->right);
 
-            /* move the plate */
-            XMoveWindow(ob_display, self->plate,
-                        self->size.left, self->size.top);
-
-            /* when the client has StaticGravity, it likes to move around. */
-            XMoveWindow(ob_display, self->client->window,
-                        -self->client->border_width,
-                        -self->client->border_width);
+            XMoveResizeWindow(ob_display, self->backback,
+                              self->size.left, self->size.top,
+                              self->client->area.width,
+                              self->client->area.height);
         }
     }
 
@@ -754,6 +764,13 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                               self->area.width,
                               self->area.height);
 
+        /* when the client has StaticGravity, it likes to move around.
+           also this correctly positions the client when it maps.
+           this also needs to be run when the frame's decorations sizes change!
+        */
+        XMoveWindow(ob_display, self->client->window,
+                    self->size.left, self->size.top);
+
         if (resized) {
             framerender_frame(self);
             frame_adjust_shape(self);
@@ -838,9 +855,10 @@ static void frame_adjust_cursors(ObFrame *self)
 
 void frame_adjust_client_area(ObFrame *self)
 {
-    /* resize the plate */
-    XResizeWindow(ob_display, self->plate,
-                  self->client->area.width, self->client->area.height);
+    /* adjust the window which is there to prevent flashing on unmap */
+    XMoveResizeWindow(ob_display, self->backfront, 0, 0,
+                      self->client->area.width,
+                      self->client->area.height);
 }
 
 void frame_adjust_state(ObFrame *self)
@@ -873,8 +891,7 @@ void frame_grab_client(ObFrame *self)
     */
 
     /* reparent the client to the frame */
-    XReparentWindow(ob_display, self->client->window, self->plate,
-                    -self->client->border_width, -self->client->border_width);
+    XReparentWindow(ob_display, self->client->window, self->window, 0, 0);
 
     /*
       When reparenting the client window, it is usually not mapped yet, since
@@ -887,11 +904,12 @@ void frame_grab_client(ObFrame *self)
 
     /* select the event mask on the client's parent (to receive config/map
        req's) the ButtonPress is to catch clicks on the client border */
-    XSelectInput(ob_display, self->plate, PLATE_EVENTMASK);
+    XSelectInput(ob_display, self->window, FRAME_EVENTMASK);
 
     /* set all the windows for the frame in the window_map */
     g_hash_table_insert(window_map, &self->window, self->client);
-    g_hash_table_insert(window_map, &self->plate, self->client);
+    g_hash_table_insert(window_map, &self->backback, self->client);
+    g_hash_table_insert(window_map, &self->backfront, self->client);
     g_hash_table_insert(window_map, &self->innerleft, self->client);
     g_hash_table_insert(window_map, &self->innertop, self->client);
     g_hash_table_insert(window_map, &self->innerright, self->client);
@@ -952,7 +970,7 @@ void frame_release_client(ObFrame *self)
            Reparent events that are generated by us are just discarded here.
            They are of no consequence to us anyhow.
         */
-        if (ev.xreparent.parent != self->plate) {
+        if (ev.xreparent.parent != self->window) {
             reparent = FALSE;
             XPutBackEvent(ob_display, &ev);
             break;
@@ -970,7 +988,8 @@ void frame_release_client(ObFrame *self)
 
     /* remove all the windows for the frame from the window_map */
     g_hash_table_remove(window_map, &self->window);
-    g_hash_table_remove(window_map, &self->plate);
+    g_hash_table_remove(window_map, &self->backback);
+    g_hash_table_remove(window_map, &self->backfront);
     g_hash_table_remove(window_map, &self->innerleft);
     g_hash_table_remove(window_map, &self->innertop);
     g_hash_table_remove(window_map, &self->innerright);
@@ -1250,13 +1269,6 @@ ObFrameContext frame_context(ObClient *client, Window win, gint x, gint y)
     }
 
     self = client->frame;
-    if (win == self->plate) {
-        /* conceptually, this is the desktop, as far as users are
-           concerned */
-        if (client->type == OB_CLIENT_TYPE_DESKTOP)
-            return OB_FRAME_CONTEXT_DESKTOP;
-        return OB_FRAME_CONTEXT_CLIENT;
-    }
 
     /* when the user clicks in the corners of the titlebar and the client
        is fully maximized, then treat it like they clicked in the
@@ -1480,6 +1492,13 @@ void frame_frame_gravity(ObFrame *self, gint *x, gint *y, gint w, gint h)
     }
 }
 
+void frame_rect_to_frame(ObFrame *self, Rect *r)
+{
+    r->width += self->size.left + self->size.right;
+    r->height += self->size.top + self->size.bottom;
+    frame_client_gravity(self, &r->x, &r->y, r->width, r->height);
+}
+
 static void flash_done(gpointer data)
 {
     ObFrame *self = data;
@@ -1558,10 +1577,12 @@ static gboolean frame_animate_iconify(gpointer p)
 
     if (self->client->icon_geometry.width == 0) {
         /* there is no icon geometry set so just go straight down */
-        Rect *a = screen_physical_area();
+        Rect *a = screen_physical_area_monitor
+            (screen_find_monitor(&self->area));
         iconx = self->area.x + self->area.width / 2 + 32;
         icony = a->y + a->width;
         iconw = 64;
+        g_free(a);
     } else {
         iconx = self->client->icon_geometry.x;
         icony = self->client->icon_geometry.y;
@@ -1622,10 +1643,11 @@ void frame_end_iconify_animation(ObFrame *self)
 
     if (!self->visible)
         XUnmapWindow(ob_display, self->window);
-    else
+    else {
         /* Send a ConfigureNotify when the animation is done, this fixes
            KDE's pager showing the window in the wrong place. */
         client_reconfigure(self->client);
+    }
 
     /* we're not animating any more ! */
     self->iconify_animation_going = 0;
@@ -1633,6 +1655,8 @@ void frame_end_iconify_animation(ObFrame *self)
     XMoveResizeWindow(ob_display, self->window,
                       self->area.x, self->area.y,
                       self->area.width, self->area.height);
+    /* we delay re-rendering until after we're done animating */
+    framerender_frame(self);
     XFlush(ob_display);
 }
 
This page took 0.034532 seconds and 4 git commands to generate.