all repos — openbox @ adfca324dadd3723afa25a3d399014265a5c8412

openbox fork - make it a bit more like ryudo

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.
Dana Jansens danakj@orodu.net
commit

adfca324dadd3723afa25a3d399014265a5c8412

parent

68a100bde36089b1879581891e9fbfbbb5f24eb6

1 files changed, 89 insertions(+), 160 deletions(-)

jump to
M openbox/place.copenbox/place.c

@@ -213,176 +213,107 @@ g_slist_free(list);

return result; } -static gint area_cmp(gconstpointer p1, gconstpointer p2, gpointer data) -{ - 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; - } - } +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 +}; - /* 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 +static gboolean place_nooverlap(ObClient *c, gint *x, gint *y) { - 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; + gint ignore; + gboolean ret; + gint maxsize; + GSList *spaces = NULL, *sit, *maxit; - if (type == SMART_GROUP) { - /* has to be more than me in the group */ - if (!client_has_group_siblings(client)) - return FALSE; - } + areas = pick_head(c); + ret = FALSE; + maxsize = 0; + maxit = NULL; - areas = pick_head(client); + /* try ignoring different things to find empty space */ + for (ignore = 0; ignore < IGNORE_END && !ret; ignore = (ignore << 1) + 1) { + guint i; - for (i = 0; i < screen_num_monitors && !ret; ++i) { - spaces = area_add(spaces, areas[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]); - /* stay out from under windows in higher layers */ - for (it = stacking_list; it; it = g_list_next(it)) { - ObClient *c; + /* go thru all the windows */ + for (sit = client_list; sit; sit = g_slist_next(sit)) { + ObClient *test = sit->data; - if (WINDOW_IS_CLIENT(it->data)) { - c = it->data; - if (ignore_max && - (c->fullscreen || (c->max_vert && c->max_horz))) - continue; - } else - continue; + /* 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 (c->layer > client->layer) { - if (!SMART_IGNORE(client, c)) - spaces = area_remove(spaces, &c->frame->area); - } else - break; - } - 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); + 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; - for (; it && !stop; it = g_list_next(it)) { - ObClient *c; + /* don't ignore this window, so remove it from the available + area */ + spaces = area_remove(spaces, &test->frame->area); + } - if (WINDOW_IS_CLIENT(it->data)) { - c = it->data; - if (ignore_max && - (c->fullscreen || (c->max_vert && c->max_horz))) - continue; - } else - continue; + for (sit = spaces; sit; sit = g_slist_next(sit)) { + Rect *r = sit->data; - 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 (maxit) { + Rect *r = maxit->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; - } - } + /* 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 @@ /* Return TRUE if we want client.c to enforce on-screen-keeping */

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);