openbox/openbox/place.c
2003-08-29 06:40:35 +00:00

136 lines
4.3 KiB
C

#include "client.h"
#include "group.h"
#include "screen.h"
#include "frame.h"
static Rect* pick_head(ObClient *c)
{
/* try direct parent first */
if (c->transient_for && c->transient_for != OB_TRAN_GROUP) {
return screen_area_monitor(c->desktop,
client_monitor(c->transient_for));
}
/* more than one guy in his group (more than just him) */
if (c->group && c->group->members->next) {
GSList *it;
/* try on the client's desktop */
for (it = c->group->members; it; it = g_slist_next(it)) {
ObClient *itc = it->data;
if (itc != c &&
(itc->desktop == c->desktop ||
itc->desktop == DESKTOP_ALL || c->desktop == DESKTOP_ALL))
return screen_area_monitor(c->desktop,
client_monitor(it->data));
}
/* try on all desktops */
for (it = c->group->members; it; it = g_slist_next(it)) {
ObClient *itc = it->data;
if (itc != c)
return screen_area_monitor(c->desktop,
client_monitor(it->data));
}
}
return NULL;
}
static gboolean place_random(ObClient *client, gint *x, gint *y)
{
int l, r, t, b;
Rect *area;
area = pick_head(client);
if (!area)
area = screen_area_monitor(client->desktop,
g_random_int_range(0, screen_num_monitors));
l = area->x;
t = area->y;
r = area->x + area->width - client->frame->area.width;
b = area->y + area->height - client->frame->area.height;
if (r > l) *x = g_random_int_range(l, r + 1);
else *x = 0;
if (b > t) *y = g_random_int_range(t, b + 1);
else *y = 0;
/* get where the client should be */
frame_frame_gravity(client->frame, x, y);
return TRUE;
}
static gboolean place_transient(ObClient *client, gint *x, gint *y)
{
if (client->transient_for) {
if (client->transient_for != OB_TRAN_GROUP) {
ObClient *c = client;
ObClient *p = client->transient_for;
*x = (p->frame->area.width - c->frame->area.width) / 2 +
p->frame->area.x;
*y = (p->frame->area.height - c->frame->area.height) / 2 +
p->frame->area.y;
return TRUE;
} else {
GSList *it;
gboolean first = TRUE;
int l, r, t, b;
for (it = client->group->members; it; it = it->next) {
ObClient *m = it->data;
if (!(m == client || m->transient_for)) {
if (first) {
l = m->frame->area.x;
t = m->frame->area.y;
r = m->frame->area.x + m->frame->area.width - 1;
b = m->frame->area.y + m->frame->area.height - 1;
first = FALSE;
} else {
l = MIN(l, m->frame->area.x);
t = MIN(t, m->frame->area.y);
r = MAX(r, m->frame->area.x +m->frame->area.width - 1);
b = MAX(b, m->frame->area.y +m->frame->area.height -1);
}
}
}
if (!first) {
*x = ((r + 1 - l) - client->frame->area.width) / 2 + l;
*y = ((b + 1 - t) - client->frame->area.height) / 2 + t;
return TRUE;
}
}
}
return FALSE;
}
static gboolean place_dialog(ObClient *client, gint *x, gint *y)
{
/* center parentless dialogs on the screen */
if (client->type == OB_CLIENT_TYPE_DIALOG) {
Rect *area;
area = pick_head(client);
if (!area)
area = screen_area_monitor(client->desktop, 0);
*x = (area->width - client->frame->area.width) / 2 + area->x;
*y = (area->height - client->frame->area.height) / 2 + area->y;
return TRUE;
}
return FALSE;
}
void place_client(ObClient *client, gint *x, gint *y)
{
if (client->positioned)
return;
if (place_transient(client, x, y))
return;
if (place_dialog(client, x, y))
return;
if (place_random(client, x, y))
return;
g_assert_not_reached(); /* the last one better succeed */
}