+enum {
+ 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, Rect *area, gint *x, gint *y)
+{
+ gint ignore;
+ gboolean ret;
+ gint maxsize;
+ GSList *spaces = NULL, *sit, *maxit;
+
+ ob_debug("placing nonoverlap");
+
+ ret = FALSE;
+ maxsize = 0;
+ maxit = NULL;
+
+ /* try ignoring different things to find empty space */
+ for (ignore = 0; ignore < IGNORE_END && !ret; ignore++) {
+ GList *it;
+
+ /* add the whole monitor */
+ spaces = area_add(spaces, area);
+
+ /* go thru all the windows */
+ for (it = client_list; it; it = g_list_next(it)) {
+ ObClient *test = it->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(c) &&
+ test->group != c->group) continue;
+ if ((ignore >= IGNORE_BELOW) &&
+ test->layer < c->layer) continue;
+ /*
+ 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 * r->height > maxsize)
+ {
+ maxsize = r->width * r->height;
+ maxit = sit;
+ }
+ }
+
+ if (maxit) {
+ Rect *r = maxit->data;
+
+ /* center it in the area */
+ *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;
+ }
+
+ while (spaces) {
+ g_slice_free(Rect, spaces->data);
+ spaces = g_slist_delete_link(spaces, spaces);
+ }
+ }
+
+ return ret;
+}
+
+static gboolean place_under_mouse(ObClient *client, gint *x, gint *y)
+{
+ gint l, r, t, b;
+ gint px, py;
+ Rect *area;
+
+ ob_debug("placing under mouse");
+
+ if (!screen_pointer_pos(&px, &py))
+ return FALSE;
+ area = pick_pointer_head(client);
+
+ l = area->x;
+ t = area->y;
+ r = area->x + area->width - client->frame->area.width;
+ b = area->y + area->height - client->frame->area.height;
+
+ *x = px - client->area.width / 2 - client->frame->size.left;
+ *x = MIN(MAX(*x, l), r);
+ *y = py - client->area.height / 2 - client->frame->size.top;
+ *y = MIN(MAX(*y, t), b);
+
+ g_slice_free(Rect, area);
+
+ return TRUE;
+}
+
+static gboolean place_per_app_setting(ObClient *client, gint *x, gint *y,
+ ObAppSettings *settings)
+{
+ Rect *screen = NULL;
+
+ if (!settings || (settings && !settings->pos_given))
+ return FALSE;
+
+ ob_debug("placing by per-app settings");
+
+ /* Find which head the pointer is on */
+ if (settings->monitor == 0)
+ /* this can return NULL */
+ screen = pick_pointer_head(client);
+ else {
+ guint m = settings->monitor;
+ if (m < 1 || m > screen_num_monitors)
+ m = screen_monitor_primary(TRUE) + 1;
+ screen = screen_area(client->desktop, m - 1, NULL);
+ }
+
+ if (settings->position.x.center)
+ *x = screen->x + screen->width / 2 - client->area.width / 2;
+ else if (settings->position.x.opposite)
+ *x = screen->x + screen->width - client->frame->area.width -
+ settings->position.x.pos;
+ else
+ *x = screen->x + settings->position.x.pos;
+ if (settings->position.x.denom)
+ *x = (*x * screen->width) / settings->position.x.denom;
+
+ if (settings->position.y.center)
+ *y = screen->y + screen->height / 2 - client->area.height / 2;
+ else if (settings->position.y.opposite)
+ *y = screen->y + screen->height - client->frame->area.height -
+ settings->position.y.pos;
+ else
+ *y = screen->y + settings->position.y.pos;
+ if (settings->position.y.denom)
+ *y = (*y * screen->height) / settings->position.y.denom;
+
+ g_slice_free(Rect, screen);
+ return TRUE;
+}
+
+static gboolean place_transient_splash(ObClient *client, Rect *area,
+ gint *x, gint *y)