diff options
| author | Dana Jansens <danakj@orodu.net> | 2003-08-29 06:40:35 +0000 |
|---|---|---|
| committer | Dana Jansens <danakj@orodu.net> | 2003-08-29 06:40:35 +0000 |
| commit | 5e06be6abb68a95aa9cafc5a6f0c5e295ebe9bee (patch) | |
| tree | be3e0b0b51db77c7e3b96055d22e9aa1516052e4 /openbox/place.c | |
| parent | db4b0e6270a7f943b1e1a3238283673a78ffd469 (diff) | |
add window placement routines to the kernel
Diffstat (limited to 'openbox/place.c')
| -rw-r--r-- | openbox/place.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/openbox/place.c b/openbox/place.c new file mode 100644 index 00000000..91beea4b --- /dev/null +++ b/openbox/place.c @@ -0,0 +1,136 @@ +#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 */ +} |
