very cool struts. partial struts actually are partial struts now. possibly way broken with xinerama?

This commit is contained in:
Dana Jansens 2007-06-13 01:50:01 +00:00
parent 739606e39c
commit 7a6a516b8e
9 changed files with 265 additions and 217 deletions

View file

@ -1430,11 +1430,12 @@ void action_move_to_center(union ActionData *data)
{ {
ObClient *c = data->client.any.c; ObClient *c = data->client.any.c;
Rect *area; Rect *area;
area = screen_area_monitor(c->desktop, 0); area = screen_area_monitor(c->desktop, 0, NULL);
client_action_start(data); client_action_start(data);
client_move(c, area->width / 2 - c->area.width / 2, client_move(c, area->width / 2 - c->area.width / 2,
area->height / 2 - c->area.height / 2); area->height / 2 - c->area.height / 2);
client_action_end(data, FALSE); client_action_end(data, FALSE);
g_free(area);
} }
void action_resize_relative_horz(union ActionData *data) void action_resize_relative_horz(union ActionData *data)
@ -1897,7 +1898,7 @@ void action_growtoedge(union ActionData *data)
ObClient *c = data->diraction.any.c; ObClient *c = data->diraction.any.c;
Rect *a; Rect *a;
a = screen_area(c->desktop); a = screen_area(c->desktop, NULL);
x = c->frame->area.x; x = c->frame->area.x;
y = c->frame->area.y; y = c->frame->area.y;
/* get the unshaded frame's dimensions..if it is shaded */ /* get the unshaded frame's dimensions..if it is shaded */
@ -1956,6 +1957,7 @@ void action_growtoedge(union ActionData *data)
client_action_start(data); client_action_start(data);
client_move_resize(c, x, y, width, height); client_move_resize(c, x, y, width, height);
client_action_end(data, FALSE); client_action_end(data, FALSE);
g_free(a);
} }
void action_send_to_layer(union ActionData *data) void action_send_to_layer(union ActionData *data)

View file

@ -398,21 +398,27 @@ void client_manage(Window window)
client_normal(self) && client_normal(self) &&
!self->session))) !self->session)))
{ {
/* make a copy to modify */ Rect placer;
Rect a = *screen_area_monitor(self->desktop, client_monitor(self));
RECT_SET(placer, placex, placey, placew, placeh);
frame_rect_to_frame(self->frame, &placer);
Rect *a = screen_area_monitor(self->desktop, client_monitor(self),
&placer);
/* shrink by the frame's area */ /* shrink by the frame's area */
a.width -= self->frame->size.left + self->frame->size.right; a->width -= self->frame->size.left + self->frame->size.right;
a.height -= self->frame->size.top + self->frame->size.bottom; a->height -= self->frame->size.top + self->frame->size.bottom;
/* fit the window inside the area */ /* fit the window inside the area */
if (placew > a.width || self->area.height > a.height) { if (placew > a->width || self->area.height > a->height) {
placew = MIN(self->area.width, a.width); placew = MIN(self->area.width, a->width);
placeh = MIN(self->area.height, a.height); placeh = MIN(self->area.height, a->height);
ob_debug("setting window size to %dx%d\n", ob_debug("setting window size to %dx%d\n",
self->area.width, self->area.height); self->area.width, self->area.height);
} }
g_free(a);
} }
@ -924,8 +930,11 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
Rect desired; Rect desired;
RECT_SET(desired, *x, *y, w, h); RECT_SET(desired, *x, *y, w, h);
all_a = screen_area(self->desktop); frame_rect_to_frame(self->frame, &desired);
mon_a = screen_area_monitor(self->desktop, screen_find_monitor(&desired));
all_a = screen_area(self->desktop, &desired);
mon_a = screen_area_monitor(self->desktop, screen_find_monitor(&desired),
&desired);
/* get where the frame would be */ /* get where the frame would be */
frame_client_gravity(self->frame, x, y, w, h); frame_client_gravity(self->frame, x, y, w, h);
@ -1011,6 +1020,9 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
/* get where the client should be */ /* get where the client should be */
frame_frame_gravity(self->frame, x, y, w, h); frame_frame_gravity(self->frame, x, y, w, h);
g_free(all_a);
g_free(mon_a);
return ox != *x || oy != *y; return ox != *x || oy != *y;
} }
@ -2680,7 +2692,8 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
gint *logicalw, gint *logicalh, gint *logicalw, gint *logicalh,
gboolean user) 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 /* make the frame recalculate its dimentions n shit without changing
anything visible for real, this way the constraints below can work with anything visible for real, this way the constraints below can work with
@ -2697,7 +2710,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
Rect *a; Rect *a;
guint i; guint i;
i = screen_find_monitor(&desired_area); i = screen_find_monitor(&desired);
a = screen_physical_area_monitor(i); a = screen_physical_area_monitor(i);
*x = a->x; *x = a->x;
@ -2711,8 +2724,8 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
Rect *a; Rect *a;
guint i; guint i;
i = screen_find_monitor(&desired_area); i = screen_find_monitor(&desired);
a = screen_area_monitor(self->desktop, i); a = screen_area_monitor(self->desktop, i, &desired);
/* set the size and position if maximized */ /* set the size and position if maximized */
if (self->max_horz) { if (self->max_horz) {
@ -2726,6 +2739,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 user = FALSE; /* ignore if the client can't be moved/resized when it
is maximizing */ is maximizing */
g_free(a);
} }
/* gets the client's position */ /* gets the client's position */
@ -3857,8 +3872,9 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
if(!client_list) if(!client_list)
return -1; return -1;
a = screen_area(c->desktop); a = screen_area(c->desktop, &c->frame->area);
monitor = screen_area_monitor(c->desktop, client_monitor(c)); monitor = screen_area_monitor(c->desktop, client_monitor(c),
&c->frame->area);
switch(dir) { switch(dir) {
case OB_DIRECTION_NORTH: case OB_DIRECTION_NORTH:
@ -4005,6 +4021,9 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
g_assert_not_reached(); g_assert_not_reached();
dest = 0; /* suppress warning */ dest = 0; /* suppress warning */
} }
g_free(a);
g_free(monitor);
return dest; return dest;
} }

View file

@ -1492,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) static void flash_done(gpointer data)
{ {
ObFrame *self = data; ObFrame *self = data;

View file

@ -231,6 +231,10 @@ void frame_client_gravity(ObFrame *self, gint *x, gint *y, gint w, gint h);
*/ */
void frame_frame_gravity(ObFrame *self, gint *x, gint *y, gint w, gint h); void frame_frame_gravity(ObFrame *self, gint *x, gint *y, gint w, gint h);
/*! Convert a rectangle in client coordinates/sizes to what it would be
for the frame, given its current decorations sizes */
void frame_rect_to_frame(ObFrame *self, Rect *r);
void frame_flash_start(ObFrame *self); void frame_flash_start(ObFrame *self);
void frame_flash_stop(ObFrame *self); void frame_flash_stop(ObFrame *self);

View file

@ -142,4 +142,7 @@ typedef struct _StrutPartial {
(s1).bottom_start == (s2).bottom_start && \ (s1).bottom_start == (s2).bottom_start && \
(s1).bottom_end == (s2).bottom_end) (s1).bottom_end == (s2).bottom_end)
#define RANGE_INTERSECT(r1x, r1w, r2x, r2w) \
(r1x < r2x + r2w && r1x + r1w > r2x)
#endif #endif

View file

@ -47,15 +47,13 @@ static Rect *pick_pointer_head(ObClient *c)
for (i = 0; i < screen_num_monitors; ++i) { for (i = 0; i < screen_num_monitors; ++i) {
if (RECT_CONTAINS(*screen_physical_area_monitor(i), px, py)) { if (RECT_CONTAINS(*screen_physical_area_monitor(i), px, py)) {
return screen_area_monitor(c->desktop, i); return screen_area_monitor(c->desktop, i, NULL);
} }
} }
g_assert_not_reached(); g_assert_not_reached();
} }
/*! Pick a monitor to place a window on. /*! Pick a monitor to place a window on. */
The returned array value should be freed with g_free. The areas within the
array should not be freed. */
static Rect **pick_head(ObClient *c) static Rect **pick_head(ObClient *c)
{ {
Rect **area; Rect **area;
@ -124,7 +122,7 @@ static Rect **pick_head(ObClient *c)
add_choice(choice, i); add_choice(choice, i);
for (i = 0; i < screen_num_monitors; ++i) for (i = 0; i < screen_num_monitors; ++i)
area[i] = screen_area_monitor(c->desktop, choice[i]); area[i] = screen_area_monitor(c->desktop, choice[i], NULL);
return area; return area;
} }
@ -148,6 +146,8 @@ static gboolean place_random(ObClient *client, gint *x, gint *y)
if (b > t) *y = g_random_int_range(t, b + 1); if (b > t) *y = g_random_int_range(t, b + 1);
else *y = areas[i]->y; else *y = areas[i]->y;
for (i = 0; i < screen_num_monitors; ++i)
g_free(areas[i]);
g_free(areas); g_free(areas);
return TRUE; return TRUE;
@ -231,6 +231,7 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y)
gboolean ret; gboolean ret;
gint maxsize; gint maxsize;
GSList *spaces = NULL, *sit, *maxit; GSList *spaces = NULL, *sit, *maxit;
guint i;
areas = pick_head(c); areas = pick_head(c);
ret = FALSE; ret = FALSE;
@ -320,6 +321,8 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y)
} }
} }
for (i = 0; i < screen_num_monitors; ++i)
g_free(areas[i]);
g_free(areas); g_free(areas);
return ret; return ret;
} }
@ -361,12 +364,17 @@ static gboolean place_per_app_setting(ObClient *client, gint *x, gint *y,
else if (settings->monitor > 0 && else if (settings->monitor > 0 &&
(guint)settings->monitor <= screen_num_monitors) (guint)settings->monitor <= screen_num_monitors)
screen = screen_area_monitor(client->desktop, screen = screen_area_monitor(client->desktop,
(guint)settings->monitor - 1); (guint)settings->monitor - 1, NULL);
else { else {
Rect **all = NULL; Rect **areas;
all = pick_head(client); guint i;
screen = all[0];
g_free(all); /* the areas themselves don't need to be freed */ areas = pick_head(client);
screen = areas[0];
for (i = 0; i < screen_num_monitors; ++i)
g_free(areas[i]);
g_free(areas);
} }
if (settings->center_x) if (settings->center_x)
@ -422,12 +430,15 @@ static gboolean place_transient_splash(ObClient *client, gint *x, gint *y)
client->type == OB_CLIENT_TYPE_SPLASH) client->type == OB_CLIENT_TYPE_SPLASH)
{ {
Rect **areas; Rect **areas;
guint i;
areas = pick_head(client); areas = pick_head(client);
*x = (areas[0]->width - client->frame->area.width) / 2 + areas[0]->x; *x = (areas[0]->width - client->frame->area.width) / 2 + areas[0]->x;
*y = (areas[0]->height - client->frame->area.height) / 2 + areas[0]->y; *y = (areas[0]->height - client->frame->area.height) / 2 + areas[0]->y;
for (i = 0; i < screen_num_monitors; ++i)
g_free(areas[i]);
g_free(areas); g_free(areas);
return TRUE; return TRUE;
} }

View file

@ -123,6 +123,7 @@ void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y)
gint pl, pt, pr, pb; /* physical screen area edges */ gint pl, pt, pr, pb; /* physical screen area edges */
gint cl, ct, cr, cb; /* current edges */ gint cl, ct, cr, cb; /* current edges */
gint w, h; /* current size */ gint w, h; /* current size */
Rect desired_area;
if (!resist) return; if (!resist) return;
@ -140,13 +141,18 @@ void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y)
ct = RECT_TOP(c->frame->area); ct = RECT_TOP(c->frame->area);
cr = RECT_RIGHT(c->frame->area); cr = RECT_RIGHT(c->frame->area);
cb = RECT_BOTTOM(c->frame->area); cb = RECT_BOTTOM(c->frame->area);
RECT_SET(desired_area, *x, *y, c->area.width, c->area.height);
for (i = 0; i < screen_num_monitors; ++i) { for (i = 0; i < screen_num_monitors; ++i) {
area = screen_area_monitor(c->desktop, i);
parea = screen_physical_area_monitor(i); parea = screen_physical_area_monitor(i);
if (!RECT_INTERSECTS_RECT(*parea, c->frame->area)) if (!RECT_INTERSECTS_RECT(*parea, c->frame->area)) {
g_free(parea);
continue; continue;
}
area = screen_area_monitor(c->desktop, i, &desired_area);
al = RECT_LEFT(*area); al = RECT_LEFT(*area);
at = RECT_TOP(*area); at = RECT_TOP(*area);
@ -174,6 +180,9 @@ void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y)
*y = pt; *y = pt;
else if (cb <= pb && b > pb && b < pb + resist) else if (cb <= pb && b > pb && b < pb + resist)
*y = pb - h + 1; *y = pb - h + 1;
g_free(area);
g_free(parea);
} }
frame_frame_gravity(c->frame, x, y, c->area.width, c->area.height); frame_frame_gravity(c->frame, x, y, c->area.width, c->area.height);
@ -276,6 +285,7 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h,
gint pl, pt, pr, pb; /* physical screen boundaries */ gint pl, pt, pr, pb; /* physical screen boundaries */
gint incw, inch; gint incw, inch;
guint i; guint i;
Rect desired_area;
if (!resist) return; if (!resist) return;
@ -287,12 +297,17 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h,
incw = c->size_inc.width; incw = c->size_inc.width;
inch = c->size_inc.height; inch = c->size_inc.height;
RECT_SET(desired_area, c->area.x, c->area.y, *w, *h);
for (i = 0; i < screen_num_monitors; ++i) { for (i = 0; i < screen_num_monitors; ++i) {
area = screen_area_monitor(c->desktop, i);
parea = screen_physical_area_monitor(i); parea = screen_physical_area_monitor(i);
if (!RECT_INTERSECTS_RECT(*parea, c->frame->area)) if (!RECT_INTERSECTS_RECT(*parea, c->frame->area)) {
g_free(parea);
continue; continue;
}
area = screen_area_monitor(c->desktop, i, &desired_area);
/* get the screen boundaries */ /* get the screen boundaries */
al = RECT_LEFT(*area); al = RECT_LEFT(*area);
@ -347,5 +362,8 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h,
*h = b - pt + 1; *h = b - pt + 1;
break; break;
} }
g_free(area);
g_free(parea);
} }
} }

View file

@ -65,8 +65,12 @@ gchar **screen_desktop_names;
Window screen_support_win; Window screen_support_win;
Time screen_desktop_user_time = CurrentTime; Time screen_desktop_user_time = CurrentTime;
static Rect **area; /* array of desktop holding array of xinerama areas */ /*! An array of desktops, holding array of areas per monitor */
static Rect *monitor_area; static Rect *monitor_area;
static GSList *struts_top;
static GSList *struts_left;
static GSList *struts_right;
static GSList *struts_bottom;
static ObPagerPopup *desktop_cycle_popup; static ObPagerPopup *desktop_cycle_popup;
@ -436,8 +440,6 @@ void screen_startup(gboolean reconfig)
void screen_shutdown(gboolean reconfig) void screen_shutdown(gboolean reconfig)
{ {
Rect **r;
pager_popup_free(desktop_cycle_popup); pager_popup_free(desktop_cycle_popup);
if (reconfig) if (reconfig)
@ -457,11 +459,6 @@ void screen_shutdown(gboolean reconfig)
g_strfreev(screen_desktop_names); g_strfreev(screen_desktop_names);
screen_desktop_names = NULL; screen_desktop_names = NULL;
for (r = area; *r; ++r)
g_free(*r);
g_free(area);
area = NULL;
} }
void screen_resize() void screen_resize()
@ -1132,203 +1129,185 @@ screen_area_add_strut_bottom(const StrutPartial *s, const Rect *monitor_area,
void screen_update_areas() void screen_update_areas()
{ {
guint i, x; guint i, j;
gulong *dims; gulong *dims;
GList *it; GList *it;
gint o; GSList *sit;
ob_debug("updating screen areas\n");
g_free(monitor_area); g_free(monitor_area);
extensions_xinerama_screens(&monitor_area, &screen_num_monitors); extensions_xinerama_screens(&monitor_area, &screen_num_monitors);
if (area) { dims = g_new(gulong, 4 * screen_num_desktops * screen_num_monitors);
for (i = 0; area[i]; ++i)
g_free(area[i]); g_slist_free(struts_left); struts_left = NULL;
g_free(area); g_slist_free(struts_top); struts_top = NULL;
g_slist_free(struts_right); struts_right = NULL;
g_slist_free(struts_bottom); struts_bottom = NULL;
/* collect the struts */
for (it = client_list; it; it = g_list_next(it)) {
ObClient *c = it->data;
if (c->strut.left)
struts_left = g_slist_prepend(struts_left, &c->strut);
if (c->strut.top)
struts_top = g_slist_prepend(struts_top, &c->strut);
if (c->strut.right)
struts_right = g_slist_prepend(struts_right, &c->strut);
if (c->strut.bottom)
struts_bottom = g_slist_prepend(struts_bottom, &c->strut);
} }
area = g_new(Rect*, screen_num_desktops + 2); /* set up the work areas to be full screen */
for (i = 0; i < screen_num_desktops + 1; ++i) for (i = 0; i < screen_num_monitors; ++i)
area[i] = g_new0(Rect, screen_num_monitors + 1); for (j = 0; j < screen_num_desktops; ++j) {
area[i] = NULL; dims[i * j + 0] = monitor_area[i].x;
dims[i * j + 1] = monitor_area[i].y;
dims = g_new(gulong, 4 * screen_num_desktops); dims[i * j + 2] = monitor_area[i].width;
dims[i * j + 3] = monitor_area[i].height;
}
for (i = 0; i < screen_num_desktops + 1; ++i) { /* calculate the work areas from the struts */
Strut *struts; for (i = 0; i < screen_num_monitors; ++i)
gint l, r, t, b; for (j = 0; j < screen_num_desktops; ++j) {
gint l = 0, r = 0, t = 0, b = 0;
struts = g_new0(Strut, screen_num_monitors); /* only add the strut to the area if it touches the monitor */
/* calc the xinerama areas */ for (sit = struts_left; sit; sit = g_slist_next(sit)) {
for (x = 0; x < screen_num_monitors; ++x) { StrutPartial *s = sit->data;
area[i][x] = monitor_area[x]; if (RANGE_INTERSECT
if (x == 0) { (s->left_start, s->left_end - s->left_start + 1,
l = monitor_area[x].x; monitor_area[i].y, monitor_area[i].height))
t = monitor_area[x].y; l = MAX(l, s->left);
r = monitor_area[x].x + monitor_area[x].width - 1;
b = monitor_area[x].y + monitor_area[x].height - 1;
} else {
l = MIN(l, monitor_area[x].x);
t = MIN(t, monitor_area[x].y);
r = MAX(r, monitor_area[x].x + monitor_area[x].width - 1);
b = MAX(b, monitor_area[x].y + monitor_area[x].height - 1);
} }
} for (sit = struts_top; sit; sit = g_slist_next(sit)) {
RECT_SET(area[i][x], l, t, r - l + 1, b - t + 1); StrutPartial *s = sit->data;
if (RANGE_INTERSECT
/* apply the struts */ (s->top_start, s->top_end - s->top_start + 1,
monitor_area[i].x, monitor_area[i].width))
/* find the left-most xin heads, i do this in 2 loops :| */ t = MAX(t, s->top);
o = area[i][0].x;
for (x = 1; x < screen_num_monitors; ++x)
o = MIN(o, area[i][x].x);
for (x = 0; x < screen_num_monitors; ++x) {
for (it = client_list; it; it = g_list_next(it)) {
ObClient *c = it->data;
screen_area_add_strut_left(&c->strut,
&monitor_area[x],
o + c->strut.left - area[i][x].x,
&struts[x]);
} }
screen_area_add_strut_left(&dock_strut, for (sit = struts_right; sit; sit = g_slist_next(sit)) {
&monitor_area[x], StrutPartial *s = sit->data;
o + dock_strut.left - area[i][x].x, if (RANGE_INTERSECT
&struts[x]); (s->right_start, s->right_end - s->right_start + 1,
monitor_area[i].y, monitor_area[i].height))
area[i][x].x += struts[x].left; r = MAX(r, s->right);
area[i][x].width -= struts[x].left;
}
/* find the top-most xin heads, i do this in 2 loops :| */
o = area[i][0].y;
for (x = 1; x < screen_num_monitors; ++x)
o = MIN(o, area[i][x].y);
for (x = 0; x < screen_num_monitors; ++x) {
for (it = client_list; it; it = g_list_next(it)) {
ObClient *c = it->data;
screen_area_add_strut_top(&c->strut,
&monitor_area[x],
o + c->strut.top - area[i][x].y,
&struts[x]);
} }
screen_area_add_strut_top(&dock_strut, for (sit = struts_bottom; sit; sit = g_slist_next(sit)) {
&monitor_area[x], StrutPartial *s = sit->data;
o + dock_strut.top - area[i][x].y, if (RANGE_INTERSECT
&struts[x]); (s->bottom_start, s->bottom_end - s->bottom_start + 1,
monitor_area[i].x, monitor_area[i].width))
area[i][x].y += struts[x].top; b = MAX(b, s->bottom);
area[i][x].height -= struts[x].top;
}
/* find the right-most xin heads, i do this in 2 loops :| */
o = area[i][0].x + area[i][0].width - 1;
for (x = 1; x < screen_num_monitors; ++x)
o = MAX(o, area[i][x].x + area[i][x].width - 1);
for (x = 0; x < screen_num_monitors; ++x) {
for (it = client_list; it; it = g_list_next(it)) {
ObClient *c = it->data;
screen_area_add_strut_right(&c->strut,
&monitor_area[x],
(area[i][x].x +
area[i][x].width - 1) -
(o - c->strut.right),
&struts[x]);
} }
screen_area_add_strut_right(&dock_strut,
&monitor_area[x],
(area[i][x].x +
area[i][x].width - 1) -
(o - dock_strut.right),
&struts[x]);
area[i][x].width -= struts[x].right; /* based on these margins, set the work area for the
monitor/desktop */
dims[i * j + 0] += l;
dims[i * j + 1] += t;
dims[i * j + 2] -= l + r;
dims[i * j + 3] -= t + b;
} }
/* find the bottom-most xin heads, i do this in 2 loops :| */
o = area[i][0].y + area[i][0].height - 1;
for (x = 1; x < screen_num_monitors; ++x)
o = MAX(o, area[i][x].y + area[i][x].height - 1);
for (x = 0; x < screen_num_monitors; ++x) {
for (it = client_list; it; it = g_list_next(it)) {
ObClient *c = it->data;
screen_area_add_strut_bottom(&c->strut,
&monitor_area[x],
(area[i][x].y +
area[i][x].height - 1) - \
(o - c->strut.bottom),
&struts[x]);
}
screen_area_add_strut_bottom(&dock_strut,
&monitor_area[x],
(area[i][x].y +
area[i][x].height - 1) - \
(o - dock_strut.bottom),
&struts[x]);
area[i][x].height -= struts[x].bottom;
}
l = RECT_LEFT(area[i][0]);
t = RECT_TOP(area[i][0]);
r = RECT_RIGHT(area[i][0]);
b = RECT_BOTTOM(area[i][0]);
for (x = 1; x < screen_num_monitors; ++x) {
l = MIN(l, RECT_LEFT(area[i][x]));
t = MIN(l, RECT_TOP(area[i][x]));
r = MAX(r, RECT_RIGHT(area[i][x]));
b = MAX(b, RECT_BOTTOM(area[i][x]));
}
RECT_SET(area[i][screen_num_monitors], l, t,
r - l + 1, b - t + 1);
/* XXX optimize when this is run? */
/* the area has changed, adjust all the maximized
windows */
for (it = client_list; it; it = g_list_next(it)) {
ObClient *c = it->data;
if (i < screen_num_desktops) {
if (c->desktop == i)
client_reconfigure(c);
} else if (c->desktop == DESKTOP_ALL)
client_reconfigure(c);
}
if (i < screen_num_desktops) {
/* don't set these for the 'all desktops' area */
dims[(i * 4) + 0] = area[i][screen_num_monitors].x;
dims[(i * 4) + 1] = area[i][screen_num_monitors].y;
dims[(i * 4) + 2] = area[i][screen_num_monitors].width;
dims[(i * 4) + 3] = area[i][screen_num_monitors].height;
}
g_free(struts);
}
PROP_SETA32(RootWindow(ob_display, ob_screen), net_workarea, cardinal, PROP_SETA32(RootWindow(ob_display, ob_screen), net_workarea, cardinal,
dims, 4 * screen_num_desktops); dims, 4 * screen_num_desktops * screen_num_monitors);
/* the area has changed, adjust all the windows if they need it */
for (it = client_list; it; it = g_list_next(it)) {
gint x, y, w, h, lw, lh;
ObClient *client = it->data;
RECT_TO_DIMS(client->area, x, y, w, h);
client_try_configure(client, &x, &y, &w, &h, &lw, &lh, FALSE);
if (!RECT_EQUAL_DIMS(client->area, x, y, w, h)) {
gulong ignore_start;
ignore_start = event_start_ignore_all_enters();
client_configure(client, x, y, w, h, FALSE, TRUE);
event_end_ignore_all_enters(ignore_start);
}
}
g_free(dims); g_free(dims);
} }
Rect *screen_area(guint desktop) Rect* screen_area(guint desktop, Rect *search)
{ {
return screen_area_monitor(desktop, screen_num_monitors); guint i;
Rect *a;
a = screen_area_monitor(desktop, 0, search);
/* combine all the monitors together */
for (i = 0; i < screen_num_monitors; ++i) {
Rect *m = screen_area_monitor(desktop, i, search);
gint l, r, t, b;
l = MIN(RECT_LEFT(*a), RECT_LEFT(*m));
t = MIN(RECT_TOP(*a), RECT_TOP(*m));
r = MAX(RECT_RIGHT(*a), RECT_RIGHT(*m));
b = MAX(RECT_BOTTOM(*a), RECT_BOTTOM(*m));
RECT_SET(*a, l, t, r - l + 1, b - t + 1);
g_free(m);
}
return a;
} }
Rect *screen_area_monitor(guint desktop, guint head) Rect* screen_area_monitor(guint desktop, guint head, Rect *search)
{ {
if (head > screen_num_monitors) Rect *a;
return NULL; GSList *it;
if (desktop >= screen_num_desktops) { gint l, r, t, b;
if (desktop == DESKTOP_ALL)
return &area[screen_num_desktops][head]; g_assert(head < screen_num_monitors);
return NULL;
/* get the base area for the monitor */
a = g_new(Rect, 1);
*a = monitor_area[head];
/* remove any struts which will be affecting the search area */
l = t = r = b = 0;
for (it = struts_left; it; it = g_slist_next(it)) {
StrutPartial *s = it->data;
if (!search ||
RANGE_INTERSECT(search->y, search->height,
s->left_start, s->left_end - s->left_start + 1))
l = MAX(l, s->left);
} }
return &area[desktop][head]; for (it = struts_right; it; it = g_slist_next(it)) {
StrutPartial *s = it->data;
if (!search == 0 ||
RANGE_INTERSECT(search->y, search->height,
s->right_start, s->right_end - s->right_start + 1))
r = MAX(r, s->right);
}
for (it = struts_top; it; it = g_slist_next(it)) {
StrutPartial *s = it->data;
if (!search == 0 ||
RANGE_INTERSECT(search->x, search->width,
s->top_start, s->top_end - s->top_start + 1))
t = MAX(t, s->top);
}
for (it = struts_bottom; it; it = g_slist_next(it)) {
StrutPartial *s = it->data;
if (search->width == 0 ||
RANGE_INTERSECT(search->x, search->width,
s->bottom_start,
s->bottom_end - s->bottom_start + 1))
b = MAX(b, s->bottom);
}
a->x += l;
a->y += t;
a->width -= l + r;
a->height -= t + b;
return a;
} }
guint screen_find_monitor(Rect *search) guint screen_find_monitor(Rect *search)
@ -1351,23 +1330,27 @@ guint screen_find_monitor(Rect *search)
most = i; most = i;
} }
} }
g_free(area);
} }
return most; return most;
} }
Rect *screen_physical_area() Rect* screen_physical_area()
{ {
return screen_physical_area_monitor(screen_num_monitors); return screen_physical_area_monitor(screen_num_monitors);
} }
Rect *screen_physical_area_monitor(guint head) Rect* screen_physical_area_monitor(guint head)
{ {
if (head > screen_num_monitors) Rect *a;
return NULL; g_assert(head <= screen_num_monitors);
return &monitor_area[head];
a = g_new(Rect, 1);
*a = monitor_area[head];
return a;
} }
Rect *screen_physical_area_monitor_active() Rect* screen_physical_area_monitor_active()
{ {
Rect *a; Rect *a;
gint x, y; gint x, y;

View file

@ -100,13 +100,14 @@ Rect *screen_physical_area_monitor(guint head);
Rect *screen_physical_area_monitor_active(); Rect *screen_physical_area_monitor_active();
Rect *screen_area(guint desktop); Rect *screen_area(guint desktop, Rect *search);
Rect *screen_area_monitor(guint desktop, guint head); Rect *screen_area_monitor(guint desktop, guint head, Rect *search);
/*! Determines which physical monitor a rectangle is on by calculating the /*! Determines which physical monitor a rectangle is on by calculating the
area of the part of the rectable on each monitor. The number of the area of the part of the rectable on each monitor. The number of the
monitor containing the greatest area of the rectangle is returned.*/ monitor containing the greatest area of the rectangle is returned.
*/
guint screen_find_monitor(Rect *search); guint screen_find_monitor(Rect *search);
/*! Sets the root cursor. This function decides which cursor to use, but you /*! Sets the root cursor. This function decides which cursor to use, but you