- if (client->positioned)
- return;
- if (place_transient(client, x, y) ||
- ((config_place_policy == OB_PLACE_POLICY_MOUSE) ?
- place_under_mouse(client, x, y) :
- place_smart(client, x, y, SMART_FULL) ||
- place_smart(client, x, y, SMART_GROUP) ||
- place_smart(client, x, y, SMART_FOCUSED) ||
- place_random(client, x, y)))
- {
- /* make sure the window is visible. */
- client_find_onscreen(client, x, y,
- client->frame->area.width,
- client->frame->area.height,
- /* non-normal clients has less rules, and
- windows that are being restored from a session
- do also. we can assume you want it back where
- you saved it */
- client_normal(client) && !client->session);
- /* get where the client should be */
- frame_frame_gravity(client->frame, x, y);
- } else
- g_assert_not_reached(); /* the last one better succeed */
+ /* Assemble the list of windows that could overlap with @c in the user's
+ current view. */
+ GSList* potential_overlap_clients = NULL;
+ int n_client_rects = 0;
+
+ /* if we're "showing desktop", ignore all existing windows */
+ if (!screen_showing_desktop) {
+ GList* it;
+ for (it = client_list; it != NULL; it = g_list_next(it)) {
+ ObClient* maybe_client = (ObClient*)it->data;
+ if (maybe_client == c)
+ continue;
+ if (maybe_client->iconic)
+ continue;
+ if (!client_occupies_space(maybe_client))
+ continue;
+ if (c->desktop != DESKTOP_ALL) {
+ if (maybe_client->desktop != c->desktop &&
+ maybe_client->desktop != DESKTOP_ALL)
+ continue;
+ } else {
+ if (maybe_client->desktop != screen_desktop &&
+ maybe_client->desktop != DESKTOP_ALL)
+ continue;
+ }
+
+ potential_overlap_clients = g_slist_prepend(
+ potential_overlap_clients, maybe_client);
+ n_client_rects += 1;
+ }
+ }
+ Rect client_rects[n_client_rects];
+ GSList* it;
+ unsigned int i = 0;
+ for (it = potential_overlap_clients; it != NULL; it = g_slist_next(it)) {
+ ObClient* potential_overlap_client = (ObClient*)it->data;
+ client_rects[i] = potential_overlap_client->frame->area;
+ i += 1;
+ }
+ g_slist_free(potential_overlap_clients);
+
+ Point result;
+ Size req_size;
+ SIZE_SET(req_size, c->frame->area.width, c->frame->area.height);
+ place_overlap_find_least_placement(client_rects, n_client_rects, head,
+ &req_size, &result);
+ *x = result.x;
+ *y = result.y;
+
+ return TRUE;
+}
+
+/*! Return TRUE if openbox chose the position for the window, and FALSE if
+ the application chose it */
+gboolean place_client(ObClient *client, gboolean foreground, gint *x, gint *y,
+ ObAppSettings *settings)
+{
+ Rect *area;
+ gboolean ret;
+
+ /* per-app settings override program specified position
+ * but not user specified, unless pos_force is enabled */
+ if (((client->positioned & USPosition) &&
+ !(settings && settings->pos_given && settings->pos_force)) ||
+ ((client->positioned & PPosition) &&
+ !(settings && settings->pos_given)))
+ return FALSE;
+
+ area = pick_head(client, foreground, settings);
+
+ /* try a number of methods */
+ ret = place_per_app_setting(client, area, x, y, settings) ||
+ place_transient_splash(client, area, x, y) ||
+ (config_place_policy == OB_PLACE_POLICY_MOUSE &&
+ place_under_mouse(client, x, y)) ||
+ place_least_overlap(client, area, x, y);
+ g_assert(ret);
+
+ g_slice_free(Rect, area);
+
+ /* get where the client should be */
+ frame_frame_gravity(client->frame, x, y);
+ return TRUE;