diff options
| -rw-r--r-- | include/wlr/types/wlr_xdg_shell_v6.h | 88 | ||||
| -rw-r--r-- | rootston/xdg_shell_v6.c | 183 | ||||
| -rw-r--r-- | types/wlr_output_layout.c | 8 | ||||
| -rw-r--r-- | types/wlr_xdg_shell_v6.c | 181 | 
4 files changed, 425 insertions, 35 deletions
| diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h index 0867b2f6..e2a58669 100644 --- a/include/wlr/types/wlr_xdg_shell_v6.h +++ b/include/wlr/types/wlr_xdg_shell_v6.h @@ -32,6 +32,77 @@ struct wlr_xdg_client_v6 {  	struct wl_event_source *ping_timer;  }; +enum wlr_positioner_v6_anchor { +	/** +	 * the center of the anchor rectangle +	 */ +	WLR_POSITIONER_V6_ANCHOR_NONE = 0, +	/** +	 * the top edge of the anchor rectangle +	 */ +	WLR_POSITIONER_V6_ANCHOR_TOP = 1, +	/** +	 * the bottom edge of the anchor rectangle +	 */ +	WLR_POSITIONER_V6_ANCHOR_BOTTOM = 2, +	/** +	 * the left edge of the anchor rectangle +	 */ +	WLR_POSITIONER_V6_ANCHOR_LEFT = 4, +	/** +	 * the right edge of the anchor rectangle +	 */ +	WLR_POSITIONER_V6_ANCHOR_RIGHT = 8, +}; + +enum wlr_positioner_v6_gravity { +	/** +	 * center over the anchor edge +	 */ +	WLR_POSITIONER_V6_GRAVITY_NONE = 0, +	/** +	 * position above the anchor edge +	 */ +	WLR_POSITIONER_V6_GRAVITY_TOP = 1, +	/** +	 * position below the anchor edge +	 */ +	WLR_POSITIONER_V6_GRAVITY_BOTTOM = 2, +	/** +	 * position to the left of the anchor edge +	 */ +	WLR_POSITIONER_V6_GRAVITY_LEFT = 4, +	/** +	 * position to the right of the anchor edge +	 */ +	WLR_POSITIONER_V6_GRAVITY_RIGHT = 8, +}; + +enum wlr_positioner_v6_constraint_adjustment { +	WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE = 0, +	WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1, +	WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 2, +	WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X = 4, +	WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y = 8, +	WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X = 16, +	WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 32, +}; + +struct wlr_xdg_positioner_v6_attributes { +	struct wlr_box anchor_rect; +	enum wlr_positioner_v6_anchor anchor; +	enum wlr_positioner_v6_gravity gravity; +	enum wlr_positioner_v6_constraint_adjustment constraint_adjustment; + +	struct { +		int32_t width, height; +	} size; + +	struct { +		int32_t x, y; +	} offset; +}; +  struct wlr_xdg_popup_v6 {  	struct wlr_xdg_surface_v6 *base;  	struct wl_list link; @@ -45,6 +116,8 @@ struct wlr_xdg_popup_v6 {  	// geometry of the parent surface  	struct wlr_box geometry; +	struct wlr_xdg_positioner_v6_attributes positioner; +  	struct wl_list grab_link; // wlr_xdg_popup_grab_v6::popups  }; @@ -229,4 +302,19 @@ struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6_popup_at(  		struct wlr_xdg_surface_v6 *surface, double sx, double sy,  		double *popup_sx, double *popup_sy); +struct wlr_box wlr_xdg_positioner_v6_get_geometry( +		struct wlr_xdg_positioner_v6_attributes *positioner); + +/** + * Get the anchor point for this popup in the root parent's coordinate system. + */ +void wlr_xdg_popup_v6_get_anchor_point(struct wlr_xdg_popup_v6 *popup, +		int *root_sx, int *root_sy); + +void wlr_positioner_v6_invert_x( +		struct wlr_xdg_positioner_v6_attributes *positioner); + +void wlr_positioner_v6_invert_y( +		struct wlr_xdg_positioner_v6_attributes *positioner); +  #endif diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index ad33c4b0..e3c70e96 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -50,6 +50,186 @@ static void popup_handle_new_popup(struct wl_listener *listener, void *data) {  	popup_create(popup->view_child.view, wlr_popup);  } +static void popup_get_coords(struct wlr_xdg_popup_v6 *popup, +		double *sx, double *sy) { +	struct wlr_xdg_surface_v6 *parent = popup->parent; +	double popup_sx = popup->geometry.x; +	double popup_sy = popup->geometry.y; +	while (parent->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) { +		popup_sx += parent->popup->geometry.x; +		popup_sy += parent->popup->geometry.y; +		parent = parent->popup->parent; +	} + +	*sx = popup_sx + parent->geometry.x; +	*sy = popup_sy + parent->geometry.y; +} + +static void popup_is_constrained(struct roots_xdg_popup_v6 *popup, +		bool *x_constrained, bool *y_constrained) { +	struct roots_view *view = popup->view_child.view; +	struct wlr_output_layout *layout = view->desktop->layout; +	struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup; +	int popup_width = wlr_popup->geometry.width; +	int popup_height = wlr_popup->geometry.height; + +	int anchor_lx, anchor_ly; +	wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly); + +	double popup_lx, popup_ly; +	popup_get_coords(wlr_popup, &popup_lx, &popup_ly); +	popup_lx += view->x; +	popup_ly += view->y; + +	anchor_lx += popup_lx; +	anchor_ly += popup_ly; + +	double dest_x = 0, dest_y = 0; +	wlr_output_layout_closest_point(layout, NULL, anchor_lx, anchor_ly, +		&dest_x, &dest_y); + +	struct wlr_output *output = +		wlr_output_layout_output_at(layout, dest_x, dest_y); +	// XXX: handle empty output layout +	assert(output); + +	struct wlr_box *output_box = wlr_output_layout_get_box(layout, output); +	*x_constrained = popup_lx <= output_box->x || +			popup_lx + popup_width >= output_box->x + output_box->width; +	*y_constrained = popup_ly <= output_box->y || +			popup_ly + popup_height >= output_box->y + output_box->height; +} + +static void popup_unconstrain_flip(struct roots_xdg_popup_v6 *popup) { +	bool x_constrained, y_constrained; +	popup_is_constrained(popup, &x_constrained, &y_constrained); + +	if (!x_constrained && !y_constrained) { +		return; +	} + +	if (x_constrained) { +		wlr_positioner_v6_invert_x(&popup->wlr_popup->positioner); +	} +	if (y_constrained) { +		wlr_positioner_v6_invert_y(&popup->wlr_popup->positioner); +	} + +	popup->wlr_popup->geometry = +		wlr_xdg_positioner_v6_get_geometry(&popup->wlr_popup->positioner); + +	popup_is_constrained(popup, &x_constrained, &y_constrained); + +	if (!x_constrained && !y_constrained) { +		return; +	} + +	if (x_constrained) { +		wlr_positioner_v6_invert_x(&popup->wlr_popup->positioner); +	} +	if (y_constrained) { +		wlr_positioner_v6_invert_y(&popup->wlr_popup->positioner); +	} + +	popup->wlr_popup->geometry = +		wlr_xdg_positioner_v6_get_geometry(&popup->wlr_popup->positioner); +} + +static void popup_unconstrain_slide(struct roots_xdg_popup_v6 *popup) { +	struct roots_view *view = popup->view_child.view; +	struct wlr_output_layout *layout = view->desktop->layout; +	struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup; +	int popup_width = wlr_popup->geometry.width; +	int popup_height = wlr_popup->geometry.height; + +	int anchor_lx, anchor_ly; +	wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly); + +	double popup_lx, popup_ly; +	popup_get_coords(wlr_popup, &popup_lx, &popup_ly); +	popup_lx += view->x; +	popup_ly += view->y; + +	anchor_lx += popup_lx; +	anchor_ly += popup_ly; + +	double dest_x = 0, dest_y = 0; +	wlr_output_layout_closest_point(layout, NULL, anchor_lx, anchor_ly, +		&dest_x, &dest_y); + +	struct wlr_output *output = +		wlr_output_layout_output_at(layout, dest_x, dest_y); +	// XXX: handle empty output layout +	assert(output); + +	struct wlr_box *output_box = wlr_output_layout_get_box(layout, output); + +	bool x_constrained = popup_lx <= output_box->x || +			popup_lx + popup_width >= output_box->x + output_box->width; +	bool y_constrained = popup_ly <= output_box->y || +			popup_ly + popup_height >= output_box->y + output_box->height; + +	double popup_ox = popup_lx - output_box->x, +		popup_oy = popup_ly - output_box->y; + +	if (x_constrained) { +		wlr_popup->geometry.x -= popup_width - (output_box->width - popup_ox); +	} +	if (y_constrained) { +		wlr_popup->geometry.y -= popup_height - (output_box->height - popup_oy); +	} +} + +static void popup_unconstrain_resize(struct roots_xdg_popup_v6 *popup) { +	struct roots_view *view = popup->view_child.view; +	struct wlr_output_layout *layout = view->desktop->layout; +	struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup; +	int popup_width = wlr_popup->geometry.width; +	int popup_height = wlr_popup->geometry.height; + +	int anchor_lx, anchor_ly; +	wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly); + +	double popup_lx, popup_ly; +	popup_get_coords(wlr_popup, &popup_lx, &popup_ly); +	popup_lx += view->x; +	popup_ly += view->y; + +	anchor_lx += popup_lx; +	anchor_ly += popup_ly; + +	double dest_x = 0, dest_y = 0; +	wlr_output_layout_closest_point(layout, NULL, anchor_lx, anchor_ly, +		&dest_x, &dest_y); + +	struct wlr_output *output = +		wlr_output_layout_output_at(layout, dest_x, dest_y); +	// XXX: handle empty output layout +	assert(output); + +	struct wlr_box *output_box = wlr_output_layout_get_box(layout, output); + +	bool x_constrained = popup_lx <= output_box->x || +			popup_lx + popup_width >= output_box->x + output_box->width; +	bool y_constrained = popup_ly <= output_box->y || +			popup_ly + popup_height >= output_box->y + output_box->height; + +	double popup_ox = popup_lx - output_box->x, popup_oy = popup_ly - output_box->y; + +	if (x_constrained) { +		wlr_popup->geometry.width = output_box->x + output_box->width - popup_ox; +	} +	if (y_constrained) { +		wlr_popup->geometry.height = output_box->y + output_box->height - popup_oy; +	} +} + +static void popup_unconstrain(struct roots_xdg_popup_v6 *popup) { +	popup_unconstrain_flip(popup); +	popup_unconstrain_slide(popup); +	popup_unconstrain_resize(popup); +} +  static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view,  		struct wlr_xdg_popup_v6 *wlr_popup) {  	struct roots_xdg_popup_v6 *popup = @@ -68,6 +248,9 @@ static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view,  	wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);  	popup->new_popup.notify = popup_handle_new_popup;  	wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup); + +	popup_unconstrain(popup); +  	return popup;  } diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index 2462bdd2..8d328c17 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -339,8 +339,12 @@ void wlr_output_layout_closest_point(struct wlr_output_layout *layout,  		}  	} -	*dest_x = min_x; -	*dest_y = min_y; +	if (dest_x) { +		*dest_x = min_x; +	} +	if (dest_y) { +		*dest_y = min_y; +	}  }  struct wlr_box *wlr_output_layout_get_box( diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index 65b461b7..0a8bbadf 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -18,22 +18,9 @@ static const char *wlr_desktop_xdg_popup_role = "xdg_popup_v6";  struct wlr_xdg_positioner_v6 {  	struct wl_resource *resource; - -	struct wlr_box anchor_rect; -	enum zxdg_positioner_v6_anchor anchor; -	enum zxdg_positioner_v6_gravity gravity; -	enum zxdg_positioner_v6_constraint_adjustment constraint_adjustment; - -	struct { -		int32_t width, height; -	} size; - -	struct { -		int32_t x, y; -	} offset; +	struct wlr_xdg_positioner_v6_attributes *attrs;  }; -  static void resource_handle_destroy(struct wl_client *client,  		struct wl_resource *resource) {  	wl_resource_destroy(resource); @@ -310,6 +297,7 @@ static struct wlr_xdg_positioner_v6 *xdg_positioner_from_resource(  static void xdg_positioner_destroy(struct wl_resource *resource) {  	struct wlr_xdg_positioner_v6 *positioner =  		xdg_positioner_from_resource(resource); +	free(positioner->attrs);  	free(positioner);  } @@ -325,8 +313,8 @@ static void xdg_positioner_handle_set_size(struct wl_client *client,  		return;  	} -	positioner->size.width = width; -	positioner->size.height = height; +	positioner->attrs->size.width = width; +	positioner->attrs->size.height = height;  }  static void xdg_positioner_handle_set_anchor_rect(struct wl_client *client, @@ -342,10 +330,10 @@ static void xdg_positioner_handle_set_anchor_rect(struct wl_client *client,  		return;  	} -	positioner->anchor_rect.x = x; -	positioner->anchor_rect.y = y; -	positioner->anchor_rect.width = width; -	positioner->anchor_rect.height = height; +	positioner->attrs->anchor_rect.x = x; +	positioner->attrs->anchor_rect.y = y; +	positioner->attrs->anchor_rect.width = width; +	positioner->attrs->anchor_rect.height = height;  }  static void xdg_positioner_handle_set_anchor(struct wl_client *client, @@ -363,7 +351,7 @@ static void xdg_positioner_handle_set_anchor(struct wl_client *client,  		return;  	} -	positioner->anchor = anchor; +	positioner->attrs->anchor = anchor;  }  static void xdg_positioner_handle_set_gravity(struct wl_client *client, @@ -381,7 +369,7 @@ static void xdg_positioner_handle_set_gravity(struct wl_client *client,  		return;  	} -	positioner->gravity = gravity; +	positioner->attrs->gravity = gravity;  }  static void xdg_positioner_handle_set_constraint_adjustment( @@ -390,7 +378,7 @@ static void xdg_positioner_handle_set_constraint_adjustment(  	struct wlr_xdg_positioner_v6 *positioner =  		xdg_positioner_from_resource(resource); -	positioner->constraint_adjustment = constraint_adjustment; +	positioner->attrs->constraint_adjustment = constraint_adjustment;  }  static void xdg_positioner_handle_set_offset(struct wl_client *client, @@ -398,8 +386,8 @@ static void xdg_positioner_handle_set_offset(struct wl_client *client,  	struct wlr_xdg_positioner_v6 *positioner =  		xdg_positioner_from_resource(resource); -	positioner->offset.x = x; -	positioner->offset.y = y; +	positioner->attrs->offset.x = x; +	positioner->attrs->offset.y = y;  }  static const struct zxdg_positioner_v6_interface @@ -423,6 +411,10 @@ static void xdg_shell_handle_create_positioner(struct wl_client *wl_client,  		return;  	} +	// TODO: allocate the positioner attrs? +	positioner->attrs = +		calloc(1, sizeof(struct wlr_xdg_positioner_v6_attributes)); +  	positioner->resource = wl_resource_create(wl_client,  		&zxdg_positioner_v6_interface,  		wl_resource_get_version(resource), @@ -438,9 +430,7 @@ static void xdg_shell_handle_create_positioner(struct wl_client *wl_client,  		positioner, xdg_positioner_destroy);  } -static struct wlr_box xdg_positioner_get_geometry( -		struct wlr_xdg_positioner_v6 *positioner, -		struct wlr_xdg_surface_v6 *surface, struct wlr_xdg_surface_v6 *parent) { +struct wlr_box wlr_xdg_positioner_v6_get_geometry(struct wlr_xdg_positioner_v6_attributes *positioner) {  	struct wlr_box geometry = {  		.x = positioner->offset.x,  		.y = positioner->offset.y, @@ -484,7 +474,7 @@ static struct wlr_box xdg_positioner_get_geometry(  	}  	if (positioner->constraint_adjustment == -			ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE) { +			WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE) {  		return geometry;  	} @@ -493,7 +483,6 @@ static struct wlr_box xdg_positioner_get_geometry(  	return geometry;  } -  static const struct zxdg_popup_v6_interface zxdg_popup_v6_implementation;  static struct wlr_xdg_surface_v6 *xdg_surface_from_xdg_popup_resource( @@ -598,7 +587,7 @@ static void xdg_surface_handle_get_popup(struct wl_client *client,  	struct wlr_xdg_positioner_v6 *positioner =  		xdg_positioner_from_resource(positioner_resource); -	if (positioner->size.width == 0 || positioner->anchor_rect.width == 0) { +	if (positioner->attrs->size.width == 0 || positioner->attrs->anchor_rect.width == 0) {  		wl_resource_post_error(resource,  			ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER,  			"positioner object is not complete"); @@ -629,7 +618,12 @@ static void xdg_surface_handle_get_popup(struct wl_client *client,  	surface->popup->base = surface;  	surface->popup->parent = parent;  	surface->popup->geometry = -		xdg_positioner_get_geometry(positioner, surface, parent); +		wlr_xdg_positioner_v6_get_geometry(positioner->attrs); + +	// positioner properties +	memcpy(&surface->popup->positioner, positioner->attrs, +		sizeof(struct wlr_xdg_positioner_v6_attributes)); +  	wl_list_insert(&parent->popups, &surface->popup->link);  	wl_resource_set_implementation(surface->popup->resource, @@ -639,7 +633,6 @@ static void xdg_surface_handle_get_popup(struct wl_client *client,  	wlr_signal_emit_safe(&parent->events.new_popup, surface->popup);  } -  static const struct zxdg_toplevel_v6_interface zxdg_toplevel_v6_implementation;  static struct wlr_xdg_surface_v6 *xdg_surface_from_xdg_toplevel_resource( @@ -1639,3 +1632,125 @@ struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6_popup_at(  	return NULL;  } + +void wlr_xdg_popup_v6_get_anchor_point(struct wlr_xdg_popup_v6 *popup, +		int *root_sx, int *root_sy) { +	struct wlr_box rect = popup->positioner.anchor_rect; +	enum wlr_positioner_v6_anchor anchor = popup->positioner.anchor; +	int sx = 0, sy = 0; + +	if (anchor == WLR_POSITIONER_V6_ANCHOR_NONE) { +		sx = (rect.x + rect.width) / 2; +		sy = (rect.y + rect.height) / 2; +	} else if (anchor == WLR_POSITIONER_V6_ANCHOR_TOP) { +		sx = (rect.x + rect.width) / 2; +		sy = rect.y; +	} else if (anchor == WLR_POSITIONER_V6_ANCHOR_BOTTOM) { +		sx = (rect.x + rect.width) / 2; +		sy = rect.y + rect.height; +	} else if (anchor == WLR_POSITIONER_V6_ANCHOR_LEFT) { +		sx = rect.x; +		sy = (rect.y + rect.height) / 2; +	} else if (anchor == WLR_POSITIONER_V6_ANCHOR_RIGHT) { +		sx = rect.x + rect.width; +		sy = (rect.y + rect.height) / 2; +	} else if (anchor == (WLR_POSITIONER_V6_ANCHOR_TOP | +				WLR_POSITIONER_V6_ANCHOR_LEFT)) { +		sx = rect.x; +		sy = rect.y; +	} else if (anchor == (WLR_POSITIONER_V6_ANCHOR_TOP | +				WLR_POSITIONER_V6_ANCHOR_RIGHT)) { +		sx = rect.x + rect.width; +		sy = rect.y; +	} else if (anchor == (WLR_POSITIONER_V6_ANCHOR_BOTTOM | +				WLR_POSITIONER_V6_ANCHOR_LEFT)) { +		sx = rect.x; +		sy = rect.y + rect.height; +	} else if (anchor == (WLR_POSITIONER_V6_ANCHOR_BOTTOM | +				WLR_POSITIONER_V6_ANCHOR_RIGHT)) { +		sx = rect.x + rect.width; +		sy = rect.y + rect.height; +	} + +	*root_sx = sx; +	*root_sy = sy; + +	/* +	// XXX: THIS IS WILL WORK WITH XDG SHELL STABLE +	switch (popup->positioner.anchor) { +	case WLR_POSITIONER_ANCHOR_NONE: +		sx = (rect.x + rect.width) / 2; +		sy = (rect.y + rect.height) / 2; +		break; +	case WLR_POSITIONER_ANCHOR_TOP: +		sx = (rect.x + rect.width) / 2; +		sy = rect.y; +		break; +	case WLR_POSITIONER_ANCHOR_BOTTOM: +		sx = (rect.x + rect.width) / 2; +		sy = rect.y + rect.height; +		break; +	case WLR_POSITIONER_ANCHOR_LEFT: +		sx = rect.x; +		sy = (rect.y + rect.height) / 2; +		break; +	case WLR_POSITIONER_ANCHOR_RIGHT: +		sx = rect.x + rect.width; +		sy = (rect.y + rect.height) / 2; +		break; +	case WLR_POSITIONER_ANCHOR_TOP_LEFT: +		sx = rect.x; +		sy = rect.y; +		break; +	case WLR_POSITIONER_ANCHOR_BOTTOM_LEFT: +		sx = rect.x; +		sy = rect.y + rect.height; +		break; +	case WLR_POSITIONER_ANCHOR_TOP_RIGHT: +		sx = rect.x + rect.width; +		sy = rect.y; +		break; +	case WLR_POSITIONER_ANCHOR_BOTTOM_RIGHT: +		sx = rect.x + rect.width; +		sy = rect.y + rect.height; +		break; +	} +	*/ +} + +void wlr_positioner_v6_invert_x(struct wlr_xdg_positioner_v6_attributes *positioner) { +	if (positioner->anchor & WLR_POSITIONER_V6_ANCHOR_LEFT) { +		positioner->anchor &= ~WLR_POSITIONER_V6_ANCHOR_LEFT; +		positioner->anchor |= WLR_POSITIONER_V6_ANCHOR_RIGHT; +	} else if (positioner->anchor & WLR_POSITIONER_V6_ANCHOR_RIGHT) { +		positioner->anchor &= ~WLR_POSITIONER_V6_ANCHOR_RIGHT; +		positioner->anchor |= WLR_POSITIONER_V6_ANCHOR_LEFT; +	} + +	if (positioner->gravity & WLR_POSITIONER_V6_GRAVITY_RIGHT) { +		positioner->gravity &= ~WLR_POSITIONER_V6_GRAVITY_RIGHT; +		positioner->gravity |= WLR_POSITIONER_V6_GRAVITY_LEFT; +	} else if (positioner->gravity & WLR_POSITIONER_V6_GRAVITY_LEFT) { +		positioner->gravity &= ~WLR_POSITIONER_V6_GRAVITY_LEFT; +		positioner->gravity |= WLR_POSITIONER_V6_GRAVITY_RIGHT; +	} +} + +void wlr_positioner_v6_invert_y( +		struct wlr_xdg_positioner_v6_attributes *positioner) { +	if (positioner->anchor & WLR_POSITIONER_V6_ANCHOR_TOP) { +		positioner->anchor &= ~WLR_POSITIONER_V6_ANCHOR_TOP; +		positioner->anchor |= WLR_POSITIONER_V6_ANCHOR_BOTTOM; +	} else if (positioner->anchor & WLR_POSITIONER_V6_ANCHOR_BOTTOM) { +		positioner->anchor &= ~WLR_POSITIONER_V6_ANCHOR_BOTTOM; +		positioner->anchor |= WLR_POSITIONER_V6_ANCHOR_TOP; +	} + +	if (positioner->gravity & WLR_POSITIONER_V6_GRAVITY_TOP) { +		positioner->gravity &= ~WLR_POSITIONER_V6_GRAVITY_TOP; +		positioner->gravity |= WLR_POSITIONER_V6_GRAVITY_BOTTOM; +	} else if (positioner->gravity & WLR_POSITIONER_V6_GRAVITY_BOTTOM) { +		positioner->gravity &= ~WLR_POSITIONER_V6_GRAVITY_BOTTOM; +		positioner->gravity |= WLR_POSITIONER_V6_GRAVITY_TOP; +	} +} | 
