diff options
| author | Dana Jansens <danakj@orodu.net> | 2007-06-12 03:42:47 +0000 |
|---|---|---|
| committer | Dana Jansens <danakj@orodu.net> | 2007-06-12 03:42:47 +0000 |
| commit | adfca324dadd3723afa25a3d399014265a5c8412 (patch) | |
| tree | 791b7712613f09cda98d6b86c713bac66a7f544d /openbox/place.c | |
| parent | 68a100bde36089b1879581891e9fbfbbb5f24eb6 (diff) | |
new window placement, but i was a lil tipsy when i started this so maybe its not so good. smart placement was just as useless anyways though, so yeah. and this code is much cleaner. on to stealing fvwm code now.
Diffstat (limited to 'openbox/place.c')
| -rw-r--r-- | openbox/place.c | 271 |
1 files changed, 100 insertions, 171 deletions
diff --git a/openbox/place.c b/openbox/place.c index 0b8309a2..5d848cb9 100644 --- a/openbox/place.c +++ b/openbox/place.c @@ -213,176 +213,107 @@ static GSList* area_remove(GSList *list, Rect *a) return result; } -static gint area_cmp(gconstpointer p1, gconstpointer p2, gpointer data) +enum { + IGNORE_FULLSCREEN = 1 << 0, + IGNORE_MAXIMIZED = 1 << 1, + IGNORE_MENUTOOL = 1 << 2, + IGNORE_SHADED = 1 << 3, + IGNORE_NONGROUP = 1 << 4, + IGNORE_BELOW = 1 << 5, + IGNORE_END = 1 << 6 +}; + +static gboolean place_nooverlap(ObClient *c, gint *x, gint *y) { - ObClient *c = data; - Rect *carea = &c->frame->area; - const Rect *a1 = p1, *a2 = p2; - gboolean diffhead = FALSE; - guint i; - Rect *a; - - for (i = 0; i < screen_num_monitors; ++i) { - a = screen_physical_area_monitor(i); - if (RECT_CONTAINS(*a, a1->x, a1->y) && - !RECT_CONTAINS(*a, a2->x, a2->y)) - { - diffhead = TRUE; - break; - } - } - - /* has to be more than me in the group */ - if (diffhead && client_has_group_siblings(c)) { - guint *num, most; - GSList *it; - - /* find how many clients in the group are on each monitor, use the - monitor with the most in it */ - num = g_new0(guint, screen_num_monitors); - for (it = c->group->members; it; it = g_slist_next(it)) - if (it->data != c) - ++num[client_monitor(it->data)]; - most = 0; - for (i = 1; i < screen_num_monitors; ++i) - if (num[i] > num[most]) - most = i; - - g_free(num); - - a = screen_physical_area_monitor(most); - if (RECT_CONTAINS(*a, a1->x, a1->y)) - return -1; - if (RECT_CONTAINS(*a, a2->x, a2->y)) - return 1; - } - - return MIN((a1->width - carea->width), (a1->height - carea->height)) - - MIN((a2->width - carea->width), (a2->height - carea->height)); -} - -typedef enum -{ - SMART_FULL, - SMART_GROUP, - SMART_FOCUSED -} ObSmartType; - -#define SMART_IGNORE(placer, c) \ - (placer == c || c->shaded || !c->frame->visible || \ - c->type == OB_CLIENT_TYPE_SPLASH || c->type == OB_CLIENT_TYPE_DESKTOP || \ - ((c->type == OB_CLIENT_TYPE_MENU || c->type == OB_CLIENT_TYPE_TOOLBAR) &&\ - client_has_parent(c)) || \ - (c->desktop != DESKTOP_ALL && \ - c->desktop != (placer->desktop == DESKTOP_ALL ? \ - screen_desktop : placer->desktop))) - -static gboolean place_smart(ObClient *client, gint *x, gint *y, - ObSmartType type, gboolean ignore_max) -{ - gboolean ret = FALSE; - GSList *spaces = NULL, *sit; - GList *it; Rect **areas; - guint i; - - if (type == SMART_GROUP) { - /* has to be more than me in the group */ - if (!client_has_group_siblings(client)) - return FALSE; - } - - areas = pick_head(client); + gint ignore; + gboolean ret; + gint maxsize; + GSList *spaces = NULL, *sit, *maxit; + + areas = pick_head(c); + ret = FALSE; + maxsize = 0; + maxit = NULL; + + /* try ignoring different things to find empty space */ + for (ignore = 0; ignore < IGNORE_END && !ret; ignore = (ignore << 1) + 1) { + guint i; + + /* try all monitors in order of preference */ + for (i = 0; i < screen_num_monitors && !ret; ++i) { + /* add the whole monitor */ + spaces = area_add(spaces, areas[i]); + + /* go thru all the windows */ + for (sit = client_list; sit; sit = g_slist_next(sit)) { + ObClient *test = sit->data; + + /* should we ignore this client? */ + if (screen_showing_desktop) continue; + if (c == test) continue; + if (test->iconic) continue; + if (c->desktop != DESKTOP_ALL) { + if (test->desktop != c->desktop && + test->desktop != DESKTOP_ALL) continue; + } else { + if (test->desktop != screen_desktop && + test->desktop != DESKTOP_ALL) continue; + } + if (test->type == OB_CLIENT_TYPE_SPLASH || + test->type == OB_CLIENT_TYPE_DESKTOP) continue; + + + if ((ignore & IGNORE_FULLSCREEN) && + test->fullscreen) continue; + if ((ignore & IGNORE_MAXIMIZED) && + test->max_horz && test->max_vert) continue; + if ((ignore & IGNORE_MENUTOOL) && + (test->type == OB_CLIENT_TYPE_MENU || + test->type == OB_CLIENT_TYPE_TOOLBAR) && + client_has_parent(c)) continue; + if ((ignore & IGNORE_SHADED) && + test->shaded) continue; + if ((ignore & IGNORE_NONGROUP) && + client_has_group_siblings(test) && + test->group != c->group) continue; + if ((ignore & IGNORE_BELOW) && + test->layer < c->layer) continue; + + /* don't ignore this window, so remove it from the available + area */ + spaces = area_remove(spaces, &test->frame->area); + } - for (i = 0; i < screen_num_monitors && !ret; ++i) { - spaces = area_add(spaces, areas[i]); - - /* stay out from under windows in higher layers */ - for (it = stacking_list; it; it = g_list_next(it)) { - ObClient *c; - - if (WINDOW_IS_CLIENT(it->data)) { - c = it->data; - if (ignore_max && - (c->fullscreen || (c->max_vert && c->max_horz))) - continue; - } else - continue; - - if (c->layer > client->layer) { - if (!SMART_IGNORE(client, c)) - spaces = area_remove(spaces, &c->frame->area); - } else - break; - } + for (sit = spaces; sit; sit = g_slist_next(sit)) { + Rect *r = sit->data; - if (type == SMART_FULL || type == SMART_FOCUSED) { - gboolean found_foc = FALSE, stop = FALSE; - ObClient *foc; - - foc = focus_order_find_first(client->desktop == DESKTOP_ALL ? - screen_desktop : client->desktop); - - for (; it && !stop; it = g_list_next(it)) { - ObClient *c; - - if (WINDOW_IS_CLIENT(it->data)) { - c = it->data; - if (ignore_max && - (c->fullscreen || (c->max_vert && c->max_horz))) - continue; - } else - continue; - - if (!SMART_IGNORE(client, c)) { - if (type == SMART_FOCUSED) - if (found_foc) - stop = TRUE; - if (!stop) - spaces = area_remove(spaces, &c->frame->area); + if (r->width >= c->frame->area.width && + r->height >= c->frame->area.height && + r->width > maxsize) + { + maxsize = r->width; + maxit = sit; } - - if (c == foc) - found_foc = TRUE; - } - } else if (type == SMART_GROUP) { - for (sit = client->group->members; sit; sit = g_slist_next(sit)) { - ObClient *c = sit->data; - if (!SMART_IGNORE(client, c)) - spaces = area_remove(spaces, &c->frame->area); } - } else - g_assert_not_reached(); - - spaces = g_slist_sort_with_data(spaces, area_cmp, client); - - for (sit = spaces; sit; sit = g_slist_next(sit)) { - Rect *r = sit->data; - - if (!ret) { - if (r->width >= client->frame->area.width && - r->height >= client->frame->area.height) { - ret = TRUE; - if (client->type == OB_CLIENT_TYPE_DIALOG || - type != SMART_FULL) - { - *x = r->x + (r->width - client->frame->area.width)/2; - *y = r->y + (r->height - client->frame->area.height)/2; - } else { - *x = r->x; - *y = r->y; - } - } + + if (maxit) { + Rect *r = maxit->data; + + /* center it in the area */ + *x = r->x + (r->width - c->frame->area.width) / 2; + *y = r->y + (r->height - c->frame->area.height) / 2; + ret = TRUE; } - g_free(r); + while (spaces) { + g_free(spaces->data); + spaces = g_slist_delete_link(spaces, spaces); + } } - g_slist_free(spaces); - spaces = NULL; } g_free(areas); - return ret; } @@ -500,22 +431,20 @@ static gboolean place_transient_splash(ObClient *client, gint *x, gint *y) gboolean place_client(ObClient *client, gint *x, gint *y, ObAppSettings *settings) { - gboolean ret = FALSE; + gboolean ret; + if (client->positioned) return FALSE; - if (place_transient_splash(client, x, y)) - ret = TRUE; - else if (!( + + /* try a number of methods */ + ret = place_transient_splash(client, x, y) || place_per_app_setting(client, x, y, settings) || - ((config_place_policy == OB_PLACE_POLICY_MOUSE) ? - place_under_mouse(client, x, y) : - place_smart(client, x, y, SMART_FULL, FALSE) || - place_smart(client, x, y, SMART_FULL, TRUE) || - place_smart(client, x, y, SMART_GROUP, FALSE) || - place_smart(client, x, y, SMART_GROUP, TRUE) || - place_smart(client, x, y, SMART_FOCUSED, TRUE) || - place_random(client, x, y)))) - g_assert_not_reached(); /* the last one better succeed */ + (config_place_policy == OB_PLACE_POLICY_MOUSE && + place_under_mouse(client, x, y)) || + place_nooverlap(client, x, y) || + place_random(client, x, y); + g_assert(ret); + /* get where the client should be */ frame_frame_gravity(client->frame, x, y, client->area.width, client->area.height); |
