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 16 Mar 2004 01:58:24 -0000 @@ -355,9 +355,13 @@ if (x != ox || y != oy) client_move(self, x, y); - } - client_showhide(self); + /* 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(self); + } + client_showhide(self); /* use client_focus instead of client_activate cuz client_activate does stuff like switch desktops etc and I'm not interested in all that when @@ -645,6 +649,62 @@ frame_frame_gravity(self->frame, x, y); /* get where the client should be */ + 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; } @@ -2979,6 +3039,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; @@ -3105,7 +3168,7 @@ */ gint client_directional_edge_search(ObClient *c, ObDirection dir) { - gint dest; + gint dest = 0; gint my_edge_start, my_edge_end, my_offset; GList *it; Rect *a; 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 16 Mar 2004 01:58:24 -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 16 Mar 2004 01:58:24 -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/event.c =================================================================== RCS file: /cvs/cvsroot/openbox/openbox/event.c,v retrieving revision 1.225 diff -u -r1.225 event.c --- openbox/event.c 15 Oct 2003 17:04:27 -0000 1.225 +++ openbox/event.c 16 Mar 2004 01:58:25 -0000 @@ -775,6 +781,7 @@ client->frame->size.top + client->frame->size.bottom; client_find_onscreen(client, &newx, &newy, fw, fh, client_normal(client)); + client_find_onmonitor(client, &newx, &newy, fw, fh); if (e->xconfigurerequest.value_mask & CWX) x = newx; if (e->xconfigurerequest.value_mask & CWY) @@ -973,6 +980,7 @@ client->frame->size.top + client->frame->size.bottom; client_find_onscreen(client, &newx, &newy, fw, fh, client_normal(client)); + client_find_onmonitor(client, &newx, &newy, fw, fh); if (e->xclient.data.l[0] & 1 << 8) x = newx; if (e->xclient.data.l[0] & 1 << 9)