Index: openbox/client.c =================================================================== RCS file: /cvs/cvsroot/openbox/openbox/client.c,v retrieving revision 1.313 diff -u -r1.313 client.c --- openbox/client.c 25 Feb 2004 19:07:40 -0000 1.313 +++ openbox/client.c 14 Mar 2004 15:20:12 -0000 @@ -649,6 +649,64 @@ return ox != *x || oy != *y; } +void client_move_onmonitor (ObClient *self) +{ + gint x = self->area.x; + gint y = self->area.y; + if (screen_num_monitors > 1 && + client_find_onmonitor(self, &x, &y, + self->frame->area.width, + self->frame->area.height)) { + client_move(self, x, y); + } +} + +gboolean client_find_onmonitor(ObClient *self, gint *x, gint *y, gint w, gint h) +{ + Rect *a; + Size s; + gint ox = *x, oy = *y; + + if (! screen_num_monitors > 1 ) + return FALSE; + + frame_client_gravity(self->frame, x, y); /* get where the frame + would be */ + + a = screen_physical_area_monitor(client_monitor(self)); + + /* Get the difference between monitor size and client size + We use this to not place the client right on the edge + of the monitor as that looks lame. This way we place it + 10% of the difference of the client and monitor sizes away + from the monitor edge.*/ + RECT_DIFF(s, *a, self->area); + + /* only move clients onto a monitor if they are not wider than + the monitor itself. If they are wider, then there's really + not a lot we can do about them being placed on the monitor + divide*/ + if (w <= a->width) { + if (*x < a->x) + *x = a->x + (s.width * 0.1); + if (*x + w > a->x + a->width) + *x = a->x + a->width - w - (s.width * 0.1); + } + /* and for all you freaks who stack your monitors vertically */ + if (h <= a->height) { + if (*y < a->y) + *y = a->y + (s.height * 0.1); + if (*y + h > a->y + a->height) + *y = a->y + a->height - h - (s.height * 0.1); + } + + frame_frame_gravity(self->frame, x, y); /* get where the self + should be */ + + return ox != *x || oy != *y; +} + + static void client_toggle_border(ObClient *self, gboolean show) { /* adjust our idea of where the client is, based on its border. When the @@ -2979,6 +3037,9 @@ } } +/* Determines which physical monitor a client is on by calculating the + area of the part of the client on each monitor. The number of the + monitor containing the greatest area of the client is returned.*/ guint client_monitor(ObClient *self) { guint i; Index: openbox/client.h =================================================================== RCS file: /cvs/cvsroot/openbox/openbox/client.h,v retrieving revision 1.78 diff -u -r1.78 client.h --- openbox/client.h 15 Oct 2003 03:59:35 -0000 1.78 +++ openbox/client.h 14 Mar 2004 15:20:12 -0000 @@ -362,6 +362,23 @@ */ void client_move_onscreen(ObClient *self, gboolean rude); +/*! Finds coordinates to keep a client on one xinerama monitor. + @param self The client + @param x The x coord of the client, may be changed. + @param y The y coord of the client, may be changed. + @param w The width of the client. + @param w The height of the client. + @return true if the client was moved to be on-monitor; false if not. +*/ +gboolean client_find_onmonitor(ObClient *self, gint *x, gint *y, gint w, gint h); + + +/*! Moves a client so that it is on one monitor if it is straddling the monitor + divide in xinerama + @param self The client to move +*/ +void client_move_onmonitor(ObClient *self); + /*! Fullscreen's or unfullscreen's the client window @param fs true if the window should be made fullscreen; false if it should be returned to normal state. Index: openbox/geom.h =================================================================== RCS file: /cvs/cvsroot/openbox/openbox/geom.h,v retrieving revision 1.15 diff -u -r1.15 geom.h --- openbox/geom.h 24 Sep 2003 17:16:16 -0000 1.15 +++ openbox/geom.h 14 Mar 2004 15:20:14 -0000 @@ -40,6 +40,10 @@ int height; } Rect; +/* defines sz as the differences of the height and width of r and o */ +#define RECT_DIFF(sz, r, o) ((sz).width = (r).width - (o).width, \ + (sz).height = (r).height - (o).height) + #define RECT_LEFT(r) ((r).x) #define RECT_TOP(r) ((r).y) #define RECT_RIGHT(r) ((r).x + (r).width - 1) @@ -62,10 +66,13 @@ #define RECT_CONTAINS_RECT(r, o) \ ((o).x >= (r).x && (o).x + (o).width <= (r).x + (r).width && \ (o).y >= (r).y && (o).y + (o).height <= (r).y + (r).height) + +/* Returns true if Rect r and o intersect */ #define RECT_INTERSECTS_RECT(r, o) \ ((o).x < (r).x + (r).width && (o).x + (o).width > (r).x && \ (o).y < (r).y + (r).height && (o).y + (o).height > (r).y) +/* Sets Rect r to be the intersection of Rect a and b. */ #define RECT_SET_INTERSECTION(r, a, b) \ ((r).x = MAX((a).x, (b).x), \ (r).y = MAX((a).y, (b).y), \ Index: openbox/place.c =================================================================== RCS file: /cvs/cvsroot/openbox/openbox/place.c,v retrieving revision 1.30 diff -u -r1.30 place.c --- openbox/place.c 25 Oct 2003 19:27:09 -0000 1.30 +++ openbox/place.c 14 Mar 2004 15:20:16 -0000 @@ -22,6 +22,7 @@ #include "frame.h" #include "focus.h" #include "config.h" +#include "debug.h" static Rect* pick_head(ObClient *c) { @@ -306,7 +307,7 @@ guint i; gint l, r, t, b; gint px, py; - Rect *area; + Rect *area = NULL; screen_pointer_pos(&px, &py); @@ -345,7 +346,7 @@ } else { GSList *it; gboolean first = TRUE; - gint l, r, t, b; + gint l = 0, r = 0, t = 0, b = 0; for (it = client->group->members; it; it = g_slist_next(it)) { ObClient *m = it->data; if (!(m == client || m->transient_for)) { @@ -376,7 +377,13 @@ void place_client(ObClient *client, gint *x, gint *y) { if (client->positioned) + { + /* As far as I can tell, clients that go through the other placement + functions don't get placed on the divide, so we only need to + do this if the client thinks it knows better*/ + client_move_onmonitor(client); return; + } if (place_transient(client, x, y) || ((config_place_policy == OB_PLACE_POLICY_MOUSE) ? place_under_mouse(client, x, y) :