#include "edges.h"
#include "labwc.h"
#include "resistance.h"
+#include "snap-constraints.h"
#include "view.h"
static void
struct border next_edges;
edges_initialize(&next_edges);
+ /* Use a constrained, effective geometry for snapping if appropriate */
+ enum wlr_edges resize_edges = view->server->resize_edges;
+ struct wlr_box origin =
+ snap_constraints_effective(view, resize_edges, /* use_pending */ false);
+
if (rc.screen_edge_strength != 0) {
/* Find any relevant output edges encountered by this move */
edges_find_outputs(&next_edges, view,
- view->current, *new_geom, NULL, check_edge_output);
+ origin, *new_geom, NULL, check_edge_output);
}
if (rc.window_edge_strength != 0) {
/* Find any relevant window edges encountered by this move */
- edges_find_neighbors(&next_edges, view, view->current, *new_geom,
+ edges_find_neighbors(&next_edges, view, origin, *new_geom,
NULL, check_edge_window, /* ignore_hidden */ true);
}
/* If any "best" edges were encountered during this move, snap motion */
edges_adjust_resize_geom(view, next_edges,
view->server->resize_edges, new_geom, /* use_pending */ false);
+
+ /*
+ * Record effective geometry after snapping in case the client opts to
+ * ignore or modify the configured geometry
+ */
+ snap_constraints_set(view, resize_edges, *new_geom);
}
static struct {
struct view *view;
bool pending;
- int offset;
- enum view_edge direction;
+ int vertical_offset;
+ int horizontal_offset;
+ enum wlr_edges resize_edges;
struct wlr_box geom;
} last_snap_hit;
{
last_snap_hit.view = NULL;
last_snap_hit.pending = false;
- last_snap_hit.offset = INT_MIN;
- last_snap_hit.direction = VIEW_EDGE_INVALID;
+ last_snap_hit.horizontal_offset = INT_MIN;
+ last_snap_hit.vertical_offset = INT_MIN;
+ last_snap_hit.resize_edges = WLR_EDGE_NONE;
memset(&last_snap_hit.geom, 0, sizeof(last_snap_hit.geom));
}
static bool
-snap_constraints_are_valid(struct view *view, enum view_edge direction)
+snap_constraints_are_valid(struct view *view, enum wlr_edges resize_edges)
{
assert(view);
return false;
}
- /* Cache is not valid if direction has changed */
- if (direction != last_snap_hit.direction) {
+ /* Cache is not valid if expected edges do not match */
+ if (resize_edges != last_snap_hit.resize_edges) {
return false;
}
- /* Cache is not valid if offset is unbounded */
- if (!BOUNDED_INT(last_snap_hit.offset)) {
+ /* Cache is not valid if edge offsets are invalid */
+ if (resize_edges & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)) {
+ if (!BOUNDED_INT(last_snap_hit.horizontal_offset)) {
+ return false;
+ }
+
+ if ((resize_edges & WLR_EDGE_LEFT) && (resize_edges & WLR_EDGE_RIGHT)) {
+ return false;
+ }
+ } else if (resize_edges & (WLR_EDGE_TOP | WLR_EDGE_BOTTOM)) {
+ if (!BOUNDED_INT(last_snap_hit.vertical_offset)) {
+ return false;
+ }
+
+ if ((resize_edges & WLR_EDGE_TOP) && (resize_edges & WLR_EDGE_BOTTOM)) {
+ return false;
+ }
+ } else {
return false;
}
- /* Cache is valid iff pending view geometry matches expectation */
+ /* Cache is valid iff view geometry matches expectation */
return wlr_box_equal(&view->pending, &last_snap_hit.geom);
}
void
snap_constraints_set(struct view *view,
- enum view_edge direction, struct wlr_box geom)
+ enum wlr_edges resize_edges, struct wlr_box geom)
{
assert(view);
- int offset = INT_MIN;
- switch (direction) {
- case VIEW_EDGE_LEFT:
- offset = geom.x;
- break;
- case VIEW_EDGE_RIGHT:
- offset = geom.x + geom.width;
- break;
- case VIEW_EDGE_UP:
- offset = geom.y;
- break;
- case VIEW_EDGE_DOWN:
- offset = geom.y + geom.height;
- break;
- default:
- break;
+ /* Set horizontal offset when resizing horizontal edges */
+ last_snap_hit.horizontal_offset = INT_MIN;
+ if (resize_edges & WLR_EDGE_LEFT) {
+ last_snap_hit.horizontal_offset = geom.x;
+ } else if (resize_edges & WLR_EDGE_RIGHT) {
+ last_snap_hit.horizontal_offset = geom.x + geom.width;
}
- if (!BOUNDED_INT(offset)) {
- snap_constraints_reset();
- return;
+ /* Set vertical offset when resizing vertical edges */
+ last_snap_hit.vertical_offset = INT_MIN;
+ if (resize_edges & WLR_EDGE_TOP) {
+ last_snap_hit.vertical_offset = geom.y;
+ } else if (resize_edges & WLR_EDGE_BOTTOM) {
+ last_snap_hit.vertical_offset = geom.y + geom.height;
}
/* Capture the current geometry and effective snapped edge */
last_snap_hit.view = view;
- last_snap_hit.offset = offset;
- last_snap_hit.direction = direction;
+ last_snap_hit.resize_edges = resize_edges;
last_snap_hit.geom = geom;
/*
}
struct wlr_box
-snap_constraints_effective(struct view *view, enum view_edge direction)
+snap_constraints_effective(struct view *view,
+ enum wlr_edges resize_edges, bool use_pending)
{
assert(view);
+ struct wlr_box real_geom = use_pending ? view->pending : view->current;
+
/* Use actual geometry when constraints do not apply */
- if (!snap_constraints_are_valid(view, direction)) {
- return view->pending;
+ if (!snap_constraints_are_valid(view, resize_edges)) {
+ return real_geom;
}
/* Override changing edge with constrained value */
- struct wlr_box geom = view->pending;
- switch (last_snap_hit.direction) {
- case VIEW_EDGE_LEFT:
- geom.x = last_snap_hit.offset;
- break;
- case VIEW_EDGE_RIGHT:
- geom.width = last_snap_hit.offset - geom.x;
- break;
- case VIEW_EDGE_UP:
- geom.y = last_snap_hit.offset;
- break;
- case VIEW_EDGE_DOWN:
- geom.height = last_snap_hit.offset - geom.y;
- break;
- default:
- return view->pending;
+ struct wlr_box geom = real_geom;
+
+ if (resize_edges & WLR_EDGE_LEFT) {
+ geom.x = last_snap_hit.horizontal_offset;
+ } else if (resize_edges & WLR_EDGE_RIGHT) {
+ geom.width = last_snap_hit.horizontal_offset - geom.x;
+ }
+
+ if (resize_edges & WLR_EDGE_TOP) {
+ geom.y = last_snap_hit.vertical_offset;
+ } else if (resize_edges & WLR_EDGE_BOTTOM) {
+ geom.height = last_snap_hit.vertical_offset - geom.y;
}
/* Fall back to actual geometry when constrained geometry is nonsense */
+ if (!BOUNDED_INT(geom.x) || !BOUNDED_INT(geom.y)) {
+ return real_geom;
+ }
+
if (geom.width <= 0 || geom.height <= 0) {
- return view->pending;
+ return real_geom;
}
return geom;
edges_initialize(&next_edges);
/* Use a constrained, effective geometry for snapping if appropriate */
- struct wlr_box origin = snap_constraints_effective(view, direction);
+ struct wlr_box origin =
+ snap_constraints_effective(view, resize_edges, /* use_pending */ true);
/* Limit motion to any intervening edge of other views on this output */
edges_find_neighbors(&next_edges, view, origin, *geo,
* Record effective geometry after snapping in case the client opts to
* ignore or modify the configured geometry
*/
- snap_constraints_set(view, direction, *geo);
+ snap_constraints_set(view, resize_edges, *geo);
}
void
edges_initialize(&next_edges);
/* Use a constrained, effective geometry for snapping if appropriate */
- struct wlr_box origin = snap_constraints_effective(view, direction);
+ struct wlr_box origin =
+ snap_constraints_effective(view, resize_edges, /* use_pending */ true);
/* Snap to output edges if the moving edge started off-screen */
edges_find_outputs(&next_edges, view,
* Record effective geometry after snapping in case the client opts to
* ignore or modify the configured geometry
*/
- snap_constraints_set(view, direction, *geo);
+ snap_constraints_set(view, resize_edges, *geo);
}