aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/types/wlr_xdg_shell_v6.h88
-rw-r--r--rootston/xdg_shell_v6.c183
-rw-r--r--types/wlr_output_layout.c8
-rw-r--r--types/wlr_xdg_shell_v6.c181
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;
+ }
+}