]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
xinerama support like crazy for struts and everything else too. this probably crashes...
[chaz/openbox] / openbox / client.c
index 89b7024ce0fab5529c573bae53556d0b2fd6e146..d10134023e6e42ad783c62ebf3061a64825677ff 100644 (file)
@@ -398,21 +398,26 @@ void client_manage(Window window)
           client_normal(self) &&
           !self->session)))
     {
-        /* make a copy to modify */
-        Rect a = *screen_area_monitor(self->desktop, client_monitor(self));
+        Rect placer;
+
+        RECT_SET(placer, placex, placey, placew, placeh);
+        frame_rect_to_frame(self->frame, &placer);
+
+        Rect *a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &placer);
 
         /* 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;
+        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 = MIN(self->area.width, a.width);
-            placeh = MIN(self->area.height, a.height);
+        if (placew > a->width || self->area.height > a->height) {
+            placew = MIN(self->area.width, a->width);
+            placeh = MIN(self->area.height, a->height);
 
             ob_debug("setting window size to %dx%d\n",
                      self->area.width, self->area.height);
         }
+        g_free(a);
     }
 
 
@@ -917,15 +922,14 @@ void client_move_onscreen(ObClient *self, gboolean rude)
 gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
                               gboolean rude)
 {
-    Rect *mon_a, *all_a;
     gint ox = *x, oy = *y;
     gboolean rudel = rude, ruder = rude, rudet = rude, rudeb = rude;
     gint fw, fh;
     Rect desired;
+    guint i;
 
     RECT_SET(desired, *x, *y, w, h);
-    all_a = screen_area(self->desktop);
-    mon_a = screen_area_monitor(self->desktop, screen_find_monitor(&desired));
+    frame_rect_to_frame(self->frame, &desired);
 
     /* get where the frame would be */
     frame_client_gravity(self->frame, x, y, w, h);
@@ -934,30 +938,8 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
     fw = self->frame->size.left + w + self->frame->size.right;
     fh = self->frame->size.top + h + self->frame->size.bottom;
 
-    /* This makes sure windows aren't entirely outside of the screen so you
-       can't see them at all.
-       It makes sure 10% of the window is on the screen at least. At don't let
-       it move itself off the top of the screen, which would hide the titlebar
-       on you. (The user can still do this if they want too, it's only limiting
-       the application.
-
-       XXX watch for xinerama dead areas...
-    */
-    if (client_normal(self)) {
-        if (!self->strut.right && *x + fw/10 >= all_a->x + all_a->width - 1)
-            *x = all_a->x + all_a->width - fw/10;
-        if (!self->strut.bottom && *y + fh/10 >= all_a->y + all_a->height - 1)
-            *y = all_a->y + all_a->height - fh/10;
-        if (!self->strut.left && *x + fw*9/10 - 1 < all_a->x)
-            *x = all_a->x - fw*9/10;
-        if (!self->strut.top && *y + fh*9/10 - 1 < all_a->y)
-            *y = all_a->y - fw*9/10;
-    }
-
-    /* If rudeness wasn't requested, then figure out of the client is currently
-       entirely on the screen. If it is, and the position isn't changing by
-       request, and it is enlarging, then be rude even though it wasn't
-       requested */
+    /* If rudeness wasn't requested, then still be rude in a given direction
+       if the client is not moving, only resizing in that direction */
     if (!rude) {
         Point oldtl, oldtr, oldbl, oldbr;
         Point newtl, newtr, newbl, newbr;
@@ -994,19 +976,48 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
             rudeb = TRUE;
     }
 
-    /* This here doesn't let windows even a pixel outside the struts/screen.
-     * When called from client_manage, programs placing themselves are
-     * forced completely onscreen, while things like
-     * xterm -geometry resolution-width/2 will work fine. Trying to
-     * place it completely offscreen will be handled in the above code.
-     * Sorry for this confused comment, i am tired. */
-    if (rudel && !self->strut.left && *x < mon_a->x) *x = mon_a->x;
-    if (ruder && !self->strut.right && *x + fw > mon_a->x + mon_a->width)
-        *x = mon_a->x + MAX(0, mon_a->width - fw);
+    for (i = 0; i < screen_num_monitors; ++i) {
+        Rect *a;
+
+        if (!screen_physical_area_monitor_contains(i, &desired))
+            continue;
+
+        a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &desired);
 
-    if (rudet && !self->strut.top && *y < mon_a->y) *y = mon_a->y;
-    if (rudeb && !self->strut.bottom && *y + fh > mon_a->y + mon_a->height)
-        *y = mon_a->y + MAX(0, mon_a->height - fh);
+        /* This makes sure windows aren't entirely outside of the screen so you
+           can't see them at all.
+           It makes sure 10% of the window is on the screen at least. At don't
+           let it move itself off the top of the screen, which would hide the
+           titlebar on you. (The user can still do this if they want too, it's
+           only limiting the application.
+        */
+        if (client_normal(self)) {
+            if (!self->strut.right && *x + fw/10 >= a->x + a->width - 1)
+                *x = a->x + a->width - fw/10;
+            if (!self->strut.bottom && *y + fh/10 >= a->y + a->height - 1)
+                *y = a->y + a->height - fh/10;
+            if (!self->strut.left && *x + fw*9/10 - 1 < a->x)
+                *x = a->x - fw*9/10;
+            if (!self->strut.top && *y + fh*9/10 - 1 < a->y)
+                *y = a->y - fw*9/10;
+        }
+
+        /* This here doesn't let windows even a pixel outside the
+           struts/screen. When called from client_manage, programs placing
+           themselves are forced completely onscreen, while things like
+           xterm -geometry resolution-width/2 will work fine. Trying to
+           place it completely offscreen will be handled in the above code.
+           Sorry for this confused comment, i am tired. */
+        if (rudel && !self->strut.left && *x < a->x) *x = a->x;
+        if (ruder && !self->strut.right && *x + fw > a->x + a->width)
+            *x = a->x + MAX(0, a->width - fw);
+
+        if (rudet && !self->strut.top && *y < a->y) *y = a->y;
+        if (rudeb && !self->strut.bottom && *y + fh > a->y + a->height)
+            *y = a->y + MAX(0, a->height - fh);
+
+        g_free(a);
+    }
 
     /* get where the client should be */
     frame_frame_gravity(self->frame, x, y, w, h);
@@ -1968,12 +1979,12 @@ void client_update_strut(ObClient *self)
     if (!got &&
         PROP_GETA32(self->window, net_wm_strut, cardinal, &data, &num)) {
         if (num == 4) {
-            const Rect *a;
+            Rect *a;
 
             got = TRUE;
 
             /* use the screen's width/height */
-            a = screen_physical_area();
+            a = screen_physical_area_all_monitors();
 
             STRUT_PARTIAL_SET(strut,
                               data[0], data[2], data[1], data[3],
@@ -1981,6 +1992,7 @@ void client_update_strut(ObClient *self)
                               a->x, a->x + a->width - 1,
                               a->y, a->y + a->height - 1,
                               a->x, a->x + a->width - 1);
+            g_free(a);
         }
         g_free(data);
     }
@@ -2381,6 +2393,9 @@ gboolean client_has_parent(ObClient *self)
 static ObStackingLayer calc_layer(ObClient *self)
 {
     ObStackingLayer l;
+    Rect *monitor;
+
+    monitor = screen_physical_area_monitor(client_monitor(self));
 
     if (self->type == OB_CLIENT_TYPE_DESKTOP)
         l = OB_STACKING_LAYER_DESKTOP;
@@ -2394,15 +2409,15 @@ static ObStackingLayer calc_layer(ObClient *self)
               */
               (self->decorations == 0 &&
                !(self->max_horz && self->max_vert) &&
-               RECT_EQUAL(self->area,
-                          *screen_physical_area_monitor
-                          (client_monitor(self))))) &&
+               RECT_EQUAL(self->area, *monitor))) &&
              (client_focused(self) || client_search_focus_tree(self)))
         l = OB_STACKING_LAYER_FULLSCREEN;
     else if (self->above) l = OB_STACKING_LAYER_ABOVE;
     else if (self->below) l = OB_STACKING_LAYER_BELOW;
     else l = OB_STACKING_LAYER_NORMAL;
 
+    g_free(monitor);
+
     return l;
 }
 
@@ -2680,7 +2695,8 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
                           gint *logicalw, gint *logicalh,
                           gboolean user)
 {
-    Rect desired_area = {*x, *y, *w, *h};
+    Rect desired = {*x, *y, *w, *h};
+    frame_rect_to_frame(self->frame, &desired);
 
     /* make the frame recalculate its dimentions n shit without changing
        anything visible for real, this way the constraints below can work with
@@ -2697,7 +2713,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
         Rect *a;
         guint i;
 
-        i = screen_find_monitor(&desired_area);
+        i = screen_find_monitor(&desired);
         a = screen_physical_area_monitor(i);
 
         *x = a->x;
@@ -2707,12 +2723,16 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
 
         user = FALSE; /* ignore if the client can't be moved/resized when it
                          is fullscreening */
+
+        g_free(a);
     } 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);
+        /* use all possible struts when maximizing to the full screen */
+        i = screen_find_monitor(&desired);
+        a = screen_area(self->desktop, i,
+                        (self->max_horz && self->max_vert ? NULL : &desired));
 
         /* set the size and position if maximized */
         if (self->max_horz) {
@@ -2726,6 +2746,8 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
 
         user = FALSE; /* ignore if the client can't be moved/resized when it
                          is maximizing */
+
+        g_free(a);
     }
 
     /* gets the client's position */
@@ -3852,13 +3874,13 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
     gint dest, monitor_dest;
     gint my_edge_start, my_edge_end, my_offset;
     GList *it;
-    Rect *a, *monitor;
+    Rect *a, *mon;
     
     if(!client_list)
         return -1;
 
-    a = screen_area(c->desktop);
-    monitor = screen_area_monitor(c->desktop, client_monitor(c));
+    a = screen_area(c->desktop, SCREEN_AREA_ALL_MONITORS, &c->frame->area);
+    mon = screen_area(c->desktop, SCREEN_AREA_ONE_MONITOR, &c->frame->area);
 
     switch(dir) {
     case OB_DIRECTION_NORTH:
@@ -3868,7 +3890,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
         
         /* default: top of screen */
         dest = a->y + (hang ? c->frame->area.height : 0);
-        monitor_dest = monitor->y + (hang ? c->frame->area.height : 0);
+        monitor_dest = mon->y + (hang ? c->frame->area.height : 0);
         /* if the monitor edge comes before the screen edge, */
         /* use that as the destination instead. (For xinerama) */
         if (monitor_dest != dest && my_offset > monitor_dest)
@@ -3901,7 +3923,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
 
         /* default: bottom of screen */
         dest = a->y + a->height - (hang ? c->frame->area.height : 0);
-        monitor_dest = monitor->y + monitor->height -
+        monitor_dest = mon->y + mon->height -
                        (hang ? c->frame->area.height : 0);
         /* if the monitor edge comes before the screen edge, */
         /* use that as the destination instead. (For xinerama) */
@@ -3936,7 +3958,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
 
         /* default: leftmost egde of screen */
         dest = a->x + (hang ? c->frame->area.width : 0);
-        monitor_dest = monitor->x + (hang ? c->frame->area.width : 0);
+        monitor_dest = mon->x + (hang ? c->frame->area.width : 0);
         /* if the monitor edge comes before the screen edge, */
         /* use that as the destination instead. (For xinerama) */
         if (monitor_dest != dest && my_offset > monitor_dest)
@@ -3969,7 +3991,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
         
         /* default: rightmost edge of screen */
         dest = a->x + a->width - (hang ? c->frame->area.width : 0);
-        monitor_dest = monitor->x + monitor->width -
+        monitor_dest = mon->x + mon->width -
                        (hang ? c->frame->area.width : 0);
         /* if the monitor edge comes before the screen edge, */
         /* use that as the destination instead. (For xinerama) */
@@ -4005,6 +4027,9 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
         g_assert_not_reached();
         dest = 0; /* suppress warning */
     }
+
+    g_free(a);
+    g_free(mon);
     return dest;
 }
 
This page took 0.031703 seconds and 4 git commands to generate.