mirror of
				https://github.com/labwc/labwc.git
				synced 2025-10-29 05:40:24 -04:00 
			
		
		
		
	resistance: refactor snap constraints, use in interactive resistance
This commit is contained in:
		
							parent
							
								
									3aab0c3b91
								
							
						
					
					
						commit
						476fd5f25e
					
				
					 4 changed files with 89 additions and 60 deletions
				
			
		|  | @ -2,19 +2,21 @@ | |||
| #ifndef LABWC_SNAP_CONSTRAINTS_H | ||||
| #define LABWC_SNAP_CONSTRAINTS_H | ||||
| 
 | ||||
| #include <wlr/util/edges.h> | ||||
| 
 | ||||
| #include "common/border.h" | ||||
| #include "view.h" | ||||
| 
 | ||||
| struct wlr_box; | ||||
| 
 | ||||
| void snap_constraints_set(struct view *view, | ||||
| 	enum view_edge direction, struct wlr_box geom); | ||||
| 	enum wlr_edges direction, struct wlr_box geom); | ||||
| 
 | ||||
| void snap_constraints_invalidate(struct view *view); | ||||
| 
 | ||||
| void snap_constraints_update(struct view *view); | ||||
| 
 | ||||
| struct wlr_box snap_constraints_effective(struct view *view, | ||||
| 	enum view_edge direction); | ||||
| 	enum wlr_edges direction, bool use_pending); | ||||
| 
 | ||||
| #endif /* LABWC_SNAP_CONSTRAINTS_H */ | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include "edges.h" | ||||
| #include "labwc.h" | ||||
| #include "resistance.h" | ||||
| #include "snap-constraints.h" | ||||
| #include "view.h" | ||||
| 
 | ||||
| static void | ||||
|  | @ -165,19 +166,30 @@ resistance_resize_apply(struct view *view, struct wlr_box *new_geom) | |||
| 	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); | ||||
| } | ||||
|  |  | |||
|  | @ -37,8 +37,9 @@ | |||
| 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; | ||||
| 
 | ||||
|  | @ -47,13 +48,14 @@ snap_constraints_reset(void) | |||
| { | ||||
| 	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); | ||||
| 
 | ||||
|  | @ -62,53 +64,61 @@ snap_constraints_are_valid(struct view *view, enum view_edge direction) | |||
| 		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; | ||||
| 
 | ||||
| 	/*
 | ||||
|  | @ -152,37 +162,40 @@ snap_constraints_update(struct view *view) | |||
| } | ||||
| 
 | ||||
| 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; | ||||
|  |  | |||
							
								
								
									
										10
									
								
								src/snap.c
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/snap.c
									
										
									
									
									
								
							|  | @ -195,7 +195,8 @@ snap_grow_to_next_edge(struct view *view, | |||
| 	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, | ||||
|  | @ -208,7 +209,7 @@ snap_grow_to_next_edge(struct view *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); | ||||
| } | ||||
| 
 | ||||
| void | ||||
|  | @ -261,7 +262,8 @@ snap_shrink_to_next_edge(struct view *view, | |||
| 	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, | ||||
|  | @ -278,5 +280,5 @@ snap_shrink_to_next_edge(struct view *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); | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andrew J. Hesford
						Andrew J. Hesford