X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fplace.c;h=9892836ec80a3ce9de4ce2c585eb27e06619ced4;hb=d658612cac44ccc1406aea1bad48c851016e4751;hp=66f367d4d9fbf45372c8cfdfb4d1affb67b8d64c;hpb=a883721bf759be32048cbfd669ed4d6e4d40d00b;p=chaz%2Fopenbox diff --git a/openbox/place.c b/openbox/place.c index 66f367d4..9892836e 100644 --- a/openbox/place.c +++ b/openbox/place.c @@ -23,8 +23,11 @@ #include "frame.h" #include "focus.h" #include "config.h" +#include "dock.h" #include "debug.h" +extern ObDock *dock; + static void add_choice(guint *choice, guint mychoice) { guint i; @@ -43,19 +46,20 @@ static Rect *pick_pointer_head(ObClient *c) guint i; gint px, py; - screen_pointer_pos(&px, &py); - - for (i = 0; i < screen_num_monitors; ++i) { - if (RECT_CONTAINS(*screen_physical_area_monitor(i), px, py)) { - return screen_area_monitor(c->desktop, i); + if (screen_pointer_pos(&px, &py)) { + for (i = 0; i < screen_num_monitors; ++i) { + Rect *monitor = screen_physical_area_monitor(i); + gboolean contain = RECT_CONTAINS(*monitor, px, py); + g_free(monitor); + if (contain) + return screen_area(c->desktop, i, NULL); } - } - g_assert_not_reached(); + g_assert_not_reached(); + } else + return NULL; } -/*! 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. */ +/*! Pick a monitor to place a window on. */ static Rect **pick_head(ObClient *c) { Rect **area; @@ -82,7 +86,7 @@ static Rect **pick_head(ObClient *c) /* try on the client's desktop */ for (it = c->group->members; it; it = g_slist_next(it)) { - ObClient *itc = it->data; + ObClient *itc = it->data; if (itc != c && (itc->desktop == c->desktop || itc->desktop == DESKTOP_ALL || c->desktop == DESKTOP_ALL)) @@ -95,7 +99,7 @@ static Rect **pick_head(ObClient *c) /* try on all desktops */ for (it = c->group->members; it; it = g_slist_next(it)) { - ObClient *itc = it->data; + ObClient *itc = it->data; if (itc != c) { add_choice(choice, client_monitor(it->data)); ob_debug("placement adding choice %d for group sibling on " @@ -112,19 +116,25 @@ static Rect **pick_head(ObClient *c) screen_pointer_pos(&px, &py); - for (i = 0; i < screen_num_monitors; i++) - if (RECT_CONTAINS(*screen_physical_area_monitor(i), px, py)) { + for (i = 0; i < screen_num_monitors; i++) { + Rect *monitor = screen_physical_area_monitor(i); + gboolean contain = RECT_CONTAINS(*monitor, px, py); + g_free(monitor); + if (contain) { add_choice(choice, i); ob_debug("placement adding choice %d for mouse pointer\n", i); break; } + } /* add any leftover choices */ for (i = 0; i < screen_num_monitors; ++i) add_choice(choice, i); for (i = 0; i < screen_num_monitors; ++i) - area[i] = screen_area_monitor(c->desktop, choice[i]); + area[i] = screen_area(c->desktop, choice[i], NULL); + + g_free(choice); return area; } @@ -148,6 +158,8 @@ static gboolean place_random(ObClient *client, gint *x, gint *y) if (b > t) *y = g_random_int_range(t, b + 1); else *y = areas[i]->y; + for (i = 0; i < screen_num_monitors; ++i) + g_free(areas[i]); g_free(areas); return TRUE; @@ -214,14 +226,15 @@ static GSList* area_remove(GSList *list, Rect *a) } 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_NONFOCUS = 1 << 6, - IGNORE_END = 1 << 7 + IGNORE_FULLSCREEN = 1, + IGNORE_MAXIMIZED = 2, + IGNORE_MENUTOOL = 3, + /*IGNORE_SHADED = 3,*/ + IGNORE_NONGROUP = 4, + IGNORE_BELOW = 5, + /*IGNORE_NONFOCUS = 1 << 5,*/ + IGNORE_DOCK = 6, + IGNORE_END = 7 }; static gboolean place_nooverlap(ObClient *c, gint *x, gint *y) @@ -231,6 +244,7 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y) gboolean ret; gint maxsize; GSList *spaces = NULL, *sit, *maxit; + guint i; areas = pick_head(c); ret = FALSE; @@ -238,7 +252,7 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y) maxit = NULL; /* try ignoring different things to find empty space */ - for (ignore = 0; ignore < IGNORE_END && !ret; ignore = (ignore << 1) + 1) { + for (ignore = 0; ignore < IGNORE_END && !ret; ignore++) { guint i; /* try all monitors in order of preference */ @@ -267,37 +281,46 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y) test->type == OB_CLIENT_TYPE_DESKTOP) continue; - if ((ignore & IGNORE_FULLSCREEN) && + if ((ignore >= IGNORE_FULLSCREEN) && test->fullscreen) continue; - if ((ignore & IGNORE_MAXIMIZED) && + if ((ignore >= IGNORE_MAXIMIZED) && test->max_horz && test->max_vert) continue; - if ((ignore & IGNORE_MENUTOOL) && + 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) && + /* + if ((ignore >= IGNORE_SHADED) && test->shaded) continue; - if ((ignore & IGNORE_NONGROUP) && - client_has_group_siblings(test) && + */ + if ((ignore >= IGNORE_NONGROUP) && + client_has_group_siblings(c) && test->group != c->group) continue; - if ((ignore & IGNORE_BELOW) && + if ((ignore >= IGNORE_BELOW) && test->layer < c->layer) continue; - if ((ignore & IGNORE_NONFOCUS) && + /* + if ((ignore >= IGNORE_NONFOCUS) && focus_client != test) continue; - + */ /* don't ignore this window, so remove it from the available area */ spaces = area_remove(spaces, &test->frame->area); } + if (ignore < IGNORE_DOCK) { + Rect a; + dock_get_area(&a); + spaces = area_remove(spaces, &a); + } + for (sit = spaces; sit; sit = g_slist_next(sit)) { Rect *r = sit->data; if (r->width >= c->frame->area.width && r->height >= c->frame->area.height && - r->width > maxsize) + r->width * r->height > maxsize) { - maxsize = r->width; + maxsize = r->width * r->height; maxit = sit; } } @@ -306,8 +329,12 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y) 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; + *x = r->x; + *y = r->y; + if (config_place_center) { + *x += (r->width - c->frame->area.width) / 2; + *y += (r->height - c->frame->area.height) / 2; + } ret = TRUE; } @@ -318,6 +345,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); return ret; } @@ -328,8 +357,9 @@ static gboolean place_under_mouse(ObClient *client, gint *x, gint *y) gint px, py; Rect *area; + if (!screen_pointer_pos(&px, &py)) + return FALSE; area = pick_pointer_head(client); - screen_pointer_pos(&px, &py); l = area->x; t = area->y; @@ -354,16 +384,25 @@ static gboolean place_per_app_setting(ObClient *client, gint *x, gint *y, /* Find which head the pointer is on */ if (settings->monitor == 0) + /* this can return NULL */ screen = pick_pointer_head(client); else if (settings->monitor > 0 && (guint)settings->monitor <= screen_num_monitors) - screen = screen_area_monitor(client->desktop, - (guint)settings->monitor - 1); - else { - Rect **all = NULL; - all = pick_head(client); - screen = all[0]; - g_free(all); /* the areas themselves don't need to be freed */ + screen = screen_area(client->desktop, (guint)settings->monitor - 1, + NULL); + + /* if we have't found a screen yet.. */ + if (!screen) { + Rect **areas; + guint i; + + areas = pick_head(client); + screen = areas[0]; + + /* don't free the first one, it's being set as "screen" */ + for (i = 1; i < screen_num_monitors; ++i) + g_free(areas[i]); + g_free(areas); } if (settings->center_x) @@ -382,6 +421,7 @@ static gboolean place_per_app_setting(ObClient *client, gint *x, gint *y, else *y = screen->y + settings->position.y; + g_free(screen); return TRUE; } @@ -408,7 +448,7 @@ static gboolean place_transient_splash(ObClient *client, gint *x, gint *y) } } if (!first) { - *x = ((r + 1 - l) - client->frame->area.width) / 2 + l; + *x = ((r + 1 - l) - client->frame->area.width) / 2 + l; *y = ((b + 1 - t) - client->frame->area.height) / 2 + t; return TRUE; } @@ -419,12 +459,15 @@ static gboolean place_transient_splash(ObClient *client, gint *x, gint *y) client->type == OB_CLIENT_TYPE_SPLASH) { Rect **areas; + guint i; areas = pick_head(client); *x = (areas[0]->width - client->frame->area.width) / 2 + areas[0]->x; *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); return TRUE; } @@ -437,13 +480,18 @@ gboolean place_client(ObClient *client, gint *x, gint *y, ObAppSettings *settings) { gboolean ret; + gboolean userplaced = FALSE; - if (client->positioned) + /* per-app settings override program specified position + * but not user specified */ + if ((client->positioned & USPosition) || + ((client->positioned & PPosition) && + !(settings && settings->pos_given))) return FALSE; /* try a number of methods */ ret = place_transient_splash(client, x, y) || - place_per_app_setting(client, x, y, settings) || + (userplaced = place_per_app_setting(client, x, y, settings)) || (config_place_policy == OB_PLACE_POLICY_MOUSE && place_under_mouse(client, x, y)) || place_nooverlap(client, x, y) || @@ -451,7 +499,6 @@ gboolean place_client(ObClient *client, gint *x, gint *y, g_assert(ret); /* get where the client should be */ - frame_frame_gravity(client->frame, x, y, - client->area.width, client->area.height); - return ret; + frame_frame_gravity(client->frame, x, y); + return !userplaced; }