mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	xdg-shell: fix positioner
The anchor and gravity bitfields in xdg-shell-unstable-v6 have been changed to a plain enum whose values cannot be used as a bitfield in xdg-shell. While it makes input validation easier, it also makes positioner operations a pain in the ass.
This commit is contained in:
		
							parent
							
								
									b28f06eca0
								
							
						
					
					
						commit
						cc12d03545
					
				
					 1 changed files with 104 additions and 46 deletions
				
			
		| 
						 | 
				
			
			@ -422,6 +422,37 @@ static void xdg_shell_handle_create_positioner(struct wl_client *wl_client,
 | 
			
		|||
		positioner, xdg_positioner_destroy);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool positioner_anchor_has_edge(enum xdg_positioner_anchor anchor,
 | 
			
		||||
		enum xdg_positioner_anchor edge) {
 | 
			
		||||
	switch (edge) {
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_TOP:
 | 
			
		||||
		return anchor == XDG_POSITIONER_ANCHOR_TOP ||
 | 
			
		||||
			anchor == XDG_POSITIONER_ANCHOR_TOP_LEFT ||
 | 
			
		||||
			anchor == XDG_POSITIONER_ANCHOR_TOP_RIGHT;
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_BOTTOM:
 | 
			
		||||
		return anchor == XDG_POSITIONER_ANCHOR_BOTTOM ||
 | 
			
		||||
			anchor == XDG_POSITIONER_ANCHOR_BOTTOM_LEFT ||
 | 
			
		||||
			anchor == XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT;
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_LEFT:
 | 
			
		||||
		return anchor == XDG_POSITIONER_ANCHOR_LEFT ||
 | 
			
		||||
			anchor == XDG_POSITIONER_ANCHOR_TOP_LEFT ||
 | 
			
		||||
			anchor == XDG_POSITIONER_ANCHOR_BOTTOM_LEFT;
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_RIGHT:
 | 
			
		||||
		return anchor == XDG_POSITIONER_ANCHOR_RIGHT ||
 | 
			
		||||
			anchor == XDG_POSITIONER_ANCHOR_TOP_RIGHT ||
 | 
			
		||||
			anchor == XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT;
 | 
			
		||||
	default:
 | 
			
		||||
		assert(false); // not reached
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool positioner_gravity_has_edge(enum xdg_positioner_gravity gravity,
 | 
			
		||||
		enum xdg_positioner_gravity edge) {
 | 
			
		||||
	// gravity and edge enums are the same
 | 
			
		||||
	return positioner_anchor_has_edge((enum xdg_positioner_anchor)gravity,
 | 
			
		||||
		(enum xdg_positioner_anchor)edge);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct wlr_box wlr_xdg_positioner_get_geometry(
 | 
			
		||||
		struct wlr_xdg_positioner *positioner) {
 | 
			
		||||
	struct wlr_box geometry = {
 | 
			
		||||
| 
						 | 
				
			
			@ -431,9 +462,11 @@ struct wlr_box wlr_xdg_positioner_get_geometry(
 | 
			
		|||
		.height = positioner->size.height,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	if (positioner->anchor & XDG_POSITIONER_ANCHOR_TOP) {
 | 
			
		||||
	if (positioner_anchor_has_edge(positioner->anchor,
 | 
			
		||||
			XDG_POSITIONER_ANCHOR_TOP)) {
 | 
			
		||||
		geometry.y += positioner->anchor_rect.y;
 | 
			
		||||
	} else if (positioner->anchor & XDG_POSITIONER_ANCHOR_BOTTOM) {
 | 
			
		||||
	} else if (positioner_anchor_has_edge(positioner->anchor,
 | 
			
		||||
			XDG_POSITIONER_ANCHOR_BOTTOM)) {
 | 
			
		||||
		geometry.y +=
 | 
			
		||||
			positioner->anchor_rect.y + positioner->anchor_rect.height;
 | 
			
		||||
	} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -441,26 +474,32 @@ struct wlr_box wlr_xdg_positioner_get_geometry(
 | 
			
		|||
			positioner->anchor_rect.y + positioner->anchor_rect.height / 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (positioner->anchor & XDG_POSITIONER_ANCHOR_LEFT) {
 | 
			
		||||
	if (positioner_anchor_has_edge(positioner->anchor,
 | 
			
		||||
			XDG_POSITIONER_ANCHOR_LEFT)) {
 | 
			
		||||
		geometry.x += positioner->anchor_rect.x;
 | 
			
		||||
	} else if (positioner->anchor & XDG_POSITIONER_ANCHOR_RIGHT) {
 | 
			
		||||
	} else if (positioner_anchor_has_edge(positioner->anchor,
 | 
			
		||||
			XDG_POSITIONER_ANCHOR_RIGHT)) {
 | 
			
		||||
		geometry.x += positioner->anchor_rect.x + positioner->anchor_rect.width;
 | 
			
		||||
	} else {
 | 
			
		||||
		geometry.x +=
 | 
			
		||||
			positioner->anchor_rect.x + positioner->anchor_rect.width / 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (positioner->gravity & XDG_POSITIONER_GRAVITY_TOP) {
 | 
			
		||||
	if (positioner_gravity_has_edge(positioner->gravity,
 | 
			
		||||
			XDG_POSITIONER_GRAVITY_TOP)) {
 | 
			
		||||
		geometry.y -= geometry.height;
 | 
			
		||||
	} else if (positioner->gravity & XDG_POSITIONER_GRAVITY_BOTTOM) {
 | 
			
		||||
	} else if (positioner_gravity_has_edge(positioner->gravity,
 | 
			
		||||
			XDG_POSITIONER_GRAVITY_BOTTOM)) {
 | 
			
		||||
		geometry.y = geometry.y;
 | 
			
		||||
	} else {
 | 
			
		||||
		geometry.y -= geometry.height / 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (positioner->gravity & XDG_POSITIONER_GRAVITY_LEFT) {
 | 
			
		||||
	if (positioner_gravity_has_edge(positioner->gravity,
 | 
			
		||||
			XDG_POSITIONER_GRAVITY_LEFT)) {
 | 
			
		||||
		geometry.x -= geometry.width;
 | 
			
		||||
	} else if (positioner->gravity & XDG_POSITIONER_GRAVITY_RIGHT) {
 | 
			
		||||
	} else if (positioner_gravity_has_edge(positioner->gravity,
 | 
			
		||||
			XDG_POSITIONER_GRAVITY_RIGHT)) {
 | 
			
		||||
		geometry.x = geometry.x;
 | 
			
		||||
	} else {
 | 
			
		||||
		geometry.x -= geometry.width / 2;
 | 
			
		||||
| 
						 | 
				
			
			@ -1632,20 +1671,16 @@ void wlr_xdg_popup_get_anchor_point(struct wlr_xdg_popup *popup,
 | 
			
		|||
	} else if (anchor == XDG_POSITIONER_ANCHOR_RIGHT) {
 | 
			
		||||
		sx = rect.x + rect.width;
 | 
			
		||||
		sy = (rect.y + rect.height) / 2;
 | 
			
		||||
	} else if (anchor == (XDG_POSITIONER_ANCHOR_TOP |
 | 
			
		||||
				XDG_POSITIONER_ANCHOR_LEFT)) {
 | 
			
		||||
	} else if (anchor == XDG_POSITIONER_ANCHOR_TOP_LEFT) {
 | 
			
		||||
		sx = rect.x;
 | 
			
		||||
		sy = rect.y;
 | 
			
		||||
	} else if (anchor == (XDG_POSITIONER_ANCHOR_TOP |
 | 
			
		||||
				XDG_POSITIONER_ANCHOR_RIGHT)) {
 | 
			
		||||
	} else if (anchor == XDG_POSITIONER_ANCHOR_TOP_RIGHT) {
 | 
			
		||||
		sx = rect.x + rect.width;
 | 
			
		||||
		sy = rect.y;
 | 
			
		||||
	} else if (anchor == (XDG_POSITIONER_ANCHOR_BOTTOM |
 | 
			
		||||
				XDG_POSITIONER_ANCHOR_LEFT)) {
 | 
			
		||||
	} else if (anchor == XDG_POSITIONER_ANCHOR_BOTTOM_LEFT) {
 | 
			
		||||
		sx = rect.x;
 | 
			
		||||
		sy = rect.y + rect.height;
 | 
			
		||||
	} else if (anchor == (XDG_POSITIONER_ANCHOR_BOTTOM |
 | 
			
		||||
				XDG_POSITIONER_ANCHOR_RIGHT)) {
 | 
			
		||||
	} else if (anchor == XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT) {
 | 
			
		||||
		sx = rect.x + rect.width;
 | 
			
		||||
		sy = rect.y + rect.height;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1834,43 +1869,66 @@ void wlr_xdg_popup_unconstrain_from_box(struct wlr_xdg_popup *popup,
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void wlr_positioner_invert_x(struct wlr_xdg_positioner *positioner) {
 | 
			
		||||
	if (positioner->anchor & XDG_POSITIONER_ANCHOR_LEFT) {
 | 
			
		||||
		positioner->anchor &= ~XDG_POSITIONER_ANCHOR_LEFT;
 | 
			
		||||
		positioner->anchor |= XDG_POSITIONER_ANCHOR_RIGHT;
 | 
			
		||||
	} else if (positioner->anchor & XDG_POSITIONER_ANCHOR_RIGHT) {
 | 
			
		||||
		positioner->anchor &= ~XDG_POSITIONER_ANCHOR_RIGHT;
 | 
			
		||||
		positioner->anchor |= XDG_POSITIONER_ANCHOR_LEFT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (positioner->gravity & XDG_POSITIONER_GRAVITY_RIGHT) {
 | 
			
		||||
		positioner->gravity &= ~XDG_POSITIONER_GRAVITY_RIGHT;
 | 
			
		||||
		positioner->gravity |= XDG_POSITIONER_GRAVITY_LEFT;
 | 
			
		||||
	} else if (positioner->gravity & XDG_POSITIONER_GRAVITY_LEFT) {
 | 
			
		||||
		positioner->gravity &= ~XDG_POSITIONER_GRAVITY_LEFT;
 | 
			
		||||
		positioner->gravity |= XDG_POSITIONER_GRAVITY_RIGHT;
 | 
			
		||||
static enum xdg_positioner_anchor positioner_anchor_invert_x(
 | 
			
		||||
		enum xdg_positioner_anchor anchor) {
 | 
			
		||||
	switch (anchor) {
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_LEFT:
 | 
			
		||||
		return XDG_POSITIONER_ANCHOR_RIGHT;
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_RIGHT:
 | 
			
		||||
		return XDG_POSITIONER_ANCHOR_LEFT;
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_TOP_LEFT:
 | 
			
		||||
		return XDG_POSITIONER_ANCHOR_TOP_RIGHT;
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT:
 | 
			
		||||
		return XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT;
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT:
 | 
			
		||||
		return XDG_POSITIONER_ANCHOR_BOTTOM_LEFT;
 | 
			
		||||
	default:
 | 
			
		||||
		return anchor;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void wlr_positioner_invert_y(
 | 
			
		||||
		struct wlr_xdg_positioner *positioner) {
 | 
			
		||||
	if (positioner->anchor & XDG_POSITIONER_ANCHOR_TOP) {
 | 
			
		||||
		positioner->anchor &= ~XDG_POSITIONER_ANCHOR_TOP;
 | 
			
		||||
		positioner->anchor |= XDG_POSITIONER_ANCHOR_BOTTOM;
 | 
			
		||||
	} else if (positioner->anchor & XDG_POSITIONER_ANCHOR_BOTTOM) {
 | 
			
		||||
		positioner->anchor &= ~XDG_POSITIONER_ANCHOR_BOTTOM;
 | 
			
		||||
		positioner->anchor |= XDG_POSITIONER_ANCHOR_TOP;
 | 
			
		||||
	}
 | 
			
		||||
static enum xdg_positioner_gravity positioner_gravity_invert_x(
 | 
			
		||||
		enum xdg_positioner_gravity gravity) {
 | 
			
		||||
	// gravity and edge enums are the same
 | 
			
		||||
	return (enum xdg_positioner_gravity)positioner_anchor_invert_x(
 | 
			
		||||
		(enum xdg_positioner_anchor)gravity);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	if (positioner->gravity & XDG_POSITIONER_GRAVITY_TOP) {
 | 
			
		||||
		positioner->gravity &= ~XDG_POSITIONER_GRAVITY_TOP;
 | 
			
		||||
		positioner->gravity |= XDG_POSITIONER_GRAVITY_BOTTOM;
 | 
			
		||||
	} else if (positioner->gravity & XDG_POSITIONER_GRAVITY_BOTTOM) {
 | 
			
		||||
		positioner->gravity &= ~XDG_POSITIONER_GRAVITY_BOTTOM;
 | 
			
		||||
		positioner->gravity |= XDG_POSITIONER_GRAVITY_TOP;
 | 
			
		||||
static enum xdg_positioner_anchor positioner_anchor_invert_y(
 | 
			
		||||
		enum xdg_positioner_anchor anchor) {
 | 
			
		||||
	switch (anchor) {
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_TOP:
 | 
			
		||||
		return XDG_POSITIONER_ANCHOR_BOTTOM;
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_BOTTOM:
 | 
			
		||||
		return XDG_POSITIONER_ANCHOR_TOP;
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_TOP_LEFT:
 | 
			
		||||
		return XDG_POSITIONER_ANCHOR_BOTTOM_LEFT;
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT:
 | 
			
		||||
		return XDG_POSITIONER_ANCHOR_TOP_LEFT;
 | 
			
		||||
	case XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT:
 | 
			
		||||
		return XDG_POSITIONER_ANCHOR_TOP_RIGHT;
 | 
			
		||||
	default:
 | 
			
		||||
		return anchor;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static enum xdg_positioner_gravity positioner_gravity_invert_y(
 | 
			
		||||
		enum xdg_positioner_gravity gravity) {
 | 
			
		||||
	// gravity and edge enums are the same
 | 
			
		||||
	return (enum xdg_positioner_gravity)positioner_anchor_invert_y(
 | 
			
		||||
		(enum xdg_positioner_anchor)gravity);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void wlr_positioner_invert_x(struct wlr_xdg_positioner *positioner) {
 | 
			
		||||
	positioner->anchor = positioner_anchor_invert_x(positioner->anchor);
 | 
			
		||||
	positioner->gravity = positioner_gravity_invert_x(positioner->gravity);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void wlr_positioner_invert_y(struct wlr_xdg_positioner *positioner) {
 | 
			
		||||
	positioner->anchor = positioner_anchor_invert_y(positioner->anchor);
 | 
			
		||||
	positioner->gravity = positioner_gravity_invert_y(positioner->gravity);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct xdg_surface_iterator_data {
 | 
			
		||||
	wlr_surface_iterator_func_t user_iterator;
 | 
			
		||||
	void *user_data;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue