view: honor automatic placement when adjusting floating geometry

The view_adjust_floating_geometry function is called when un-maximizing
a window or changing the output layout to ensure that views are well
placed. Rather than always centering these views should they fall
offscren, use the automatic placement strategy if so configured.
This commit is contained in:
Andrew J. Hesford 2023-12-30 11:19:27 -05:00 committed by Johan Malm
parent 7f357a388b
commit b1c5e95c05
4 changed files with 32 additions and 19 deletions

View file

@ -3,8 +3,9 @@
#define LABWC_PLACEMENT_H
#include <stdbool.h>
#include <wlr/util/box.h>
#include "view.h"
bool placement_find_best(struct view *view, int *x, int *y);
bool placement_find_best(struct view *view, struct wlr_box *geometry);
#endif /* LABWC_PLACEMENT_H */

View file

@ -945,9 +945,9 @@ actions_run(struct view *activator, struct server *server,
break;
case ACTION_TYPE_AUTO_PLACE:
if (view) {
int x = 0, y = 0;
if (placement_find_best(view, &x, &y)) {
view_move(view, x, y);
struct wlr_box geometry = view->pending;
if (placement_find_best(view, &geometry)) {
view_move(view, geometry.x, geometry.y);
}
}
break;

View file

@ -396,11 +396,13 @@ compute_overlap(struct overlap_bitmap *bmp, int i, int j,
}
/*
* Find, in (*x, *y), the placement of *view on its output that will minimize
* overlap with all other views.
* Find the placement of *view, with an expected width and height of
* geometry->width and geometry->height, respectively, that will minimize
* overlap with all other views. The values geometry->x and geometry->y will be
* overwritten with the optimum placement.
*/
bool
placement_find_best(struct view *view, int *x, int *y)
placement_find_best(struct view *view, struct wlr_box *geometry)
{
assert(view);
@ -416,16 +418,16 @@ placement_find_best(struct view *view, int *x, int *y)
/* Default placement is just the upper-left corner of the output */
struct wlr_box usable = output_usable_area_in_layout_coords(output);
*x = usable.x + margin.left;
*y = usable.y + margin.top;
geometry->x = usable.x + margin.left;
geometry->y = usable.y + margin.top;
/* Build the placement grid and overlap bitmap */
struct overlap_bitmap bmp = { 0 };
build_grid(&bmp, view);
build_overlap(&bmp, view);
int height = view->pending.height + margin.top + margin.bottom;
int width = view->pending.width + margin.left + margin.right;
int height = geometry->height + margin.top + margin.bottom;
int width = geometry->width + margin.left + margin.right;
int min_overlap = INT_MAX;
@ -484,18 +486,18 @@ placement_find_best(struct view *view, int *x, int *y)
if (rt) {
/* Extend window right from left edge */
*x = bmp.cols[j] + margin.left;
geometry->x = bmp.cols[j] + margin.left;
} else {
/* Extend window left from right edge */
*x = bmp.cols[j + 1] - width + margin.left;
geometry->x = bmp.cols[j + 1] - width + margin.left;
}
if (dn) {
/* Extend window down from top edge */
*y = bmp.rows[i] + margin.top;
geometry->y = bmp.rows[i] + margin.top;
} else {
/* Extend window up from bottom edge */
*y = bmp.rows[i + 1] - height + margin.top;
geometry->y = bmp.rows[i + 1] - height + margin.top;
}
/* If there is no overlap, the search is done. */

View file

@ -636,7 +636,17 @@ view_adjust_floating_geometry(struct view *view, struct wlr_box *geometry)
adjusted = true;
}
} else {
/* If offscreen, then just center the view */
/*
* Reposition offscreen views; if automatic placement was is
* configured, try to automatically place the windows.
*/
if (rc.placement_policy == LAB_PLACE_AUTOMATIC) {
if (placement_find_best(view, geometry)) {
return true;
}
}
/* If automatic placement failed or was not enabled, just center */
adjusted = view_compute_centered_position(view, NULL,
geometry->width, geometry->height,
&geometry->x, &geometry->y);
@ -698,9 +708,9 @@ view_place_initial(struct view *view)
view_move_to_cursor(view);
return;
} else if (rc.placement_policy == LAB_PLACE_AUTOMATIC) {
int x = 0, y = 0;
if (placement_find_best(view, &x, &y)) {
view_move(view, x, y);
struct wlr_box geometry = view->pending;
if (placement_find_best(view, &geometry)) {
view_move(view, geometry.x, geometry.y);
return;
}
}