--- /dev/null
+#include <stdlib.h>
+
+#include "libds/log.h"
+#include "libds/util/box.h"
+#include "xdg_shell_v6.h"
+
+static void
+xdg_positioner_v6_handle_resource_destroy(struct wl_resource *resource)
+{
+ struct ds_xdg_positioner_v6 *positioner;
+
+ positioner = wl_resource_get_user_data(resource);
+ free(positioner);
+}
+
+static void
+xdg_positioner_v6_handle_destroy(struct wl_client *wl_client,
+ struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static void
+xdg_positioner_v6_handle_set_size(struct wl_client *wl_client,
+ struct wl_resource *resource, int32_t width, int32_t height)
+{
+ struct ds_xdg_positioner_v6 *positioner;
+
+ if (width < 1 || height < 1) {
+ wl_resource_post_error(resource,
+ ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+ "width and height must be positive and non-zero (%d, %d)",
+ width, height);
+ return;
+ }
+
+ positioner = wl_resource_get_user_data(resource);
+ positioner->size.width = width;
+ positioner->size.height = height;
+}
+
+static void
+xdg_positioner_v6_handle_set_anchor_rect(struct wl_client *wl_client,
+ struct wl_resource *resource,
+ int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ struct ds_xdg_positioner_v6 *positioner;
+
+ if (width < 1 || height < 1) {
+ wl_resource_post_error(resource,
+ ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+ "width and height must be positive and non-zero (%d, %d)",
+ width, height);
+ return;
+ }
+
+ positioner = wl_resource_get_user_data(resource);
+ positioner->anchor_rect.x = x;
+ positioner->anchor_rect.y = y;
+ positioner->anchor_rect.width = width;
+ positioner->anchor_rect.height = height;
+}
+
+static void
+xdg_positioner_v6_handle_set_anchor(struct wl_client *wl_client,
+ struct wl_resource *resource,
+ enum zxdg_positioner_v6_anchor anchor)
+{
+ struct ds_xdg_positioner_v6 *positioner;
+
+ if (((anchor & ZXDG_POSITIONER_V6_ANCHOR_TOP) &&
+ (anchor & ZXDG_POSITIONER_V6_ANCHOR_BOTTOM)) ||
+ ((anchor & ZXDG_POSITIONER_V6_ANCHOR_LEFT) &&
+ (anchor & ZXDG_POSITIONER_V6_ANCHOR_RIGHT))) {
+ wl_resource_post_error(resource,
+ ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+ "same-axis values are not allowed (%d)", anchor);
+ return;
+ }
+
+ positioner = wl_resource_get_user_data(resource);
+ positioner->anchor = anchor;
+}
+
+static void
+xdg_positioner_v6_handle_set_gravity(struct wl_client *wl_client,
+ struct wl_resource *resource,
+ enum zxdg_positioner_v6_gravity gravity)
+{
+ struct ds_xdg_positioner_v6 *positioner;
+
+ if (((gravity & ZXDG_POSITIONER_V6_GRAVITY_TOP) &&
+ (gravity & ZXDG_POSITIONER_V6_GRAVITY_BOTTOM)) ||
+ ((gravity & ZXDG_POSITIONER_V6_GRAVITY_LEFT) &&
+ (gravity & ZXDG_POSITIONER_V6_GRAVITY_RIGHT))) {
+ wl_resource_post_error(resource,
+ ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+ "same-axis values are not allowed (%d)", gravity);
+ return;
+ }
+
+ positioner = wl_resource_get_user_data(resource);
+ positioner->gravity = gravity;
+}
+
+static void
+xdg_positioner_v6_handle_set_constraint_adjustment(struct wl_client *wl_client,
+ struct wl_resource *resource,
+ enum zxdg_positioner_v6_constraint_adjustment constraint_adjustment)
+{
+ struct ds_xdg_positioner_v6 *positioner;
+
+ positioner = wl_resource_get_user_data(resource);
+ positioner->constraint_adjustment = constraint_adjustment;
+}
+
+static void
+xdg_positioner_v6_handle_set_offset(struct wl_client *wl_client,
+ struct wl_resource *resource, int32_t x, int32_t y)
+{
+ struct ds_xdg_positioner_v6 *positioner;
+
+ positioner = wl_resource_get_user_data(resource);
+ positioner->offset.x = x;
+ positioner->offset.y = y;
+}
+
+static const struct zxdg_positioner_v6_interface
+xdg_positioner_v6_impl = {
+ .destroy = xdg_positioner_v6_handle_destroy,
+ .set_size = xdg_positioner_v6_handle_set_size,
+ .set_anchor_rect = xdg_positioner_v6_handle_set_anchor_rect,
+ .set_anchor = xdg_positioner_v6_handle_set_anchor,
+ .set_gravity = xdg_positioner_v6_handle_set_gravity,
+ .set_constraint_adjustment = xdg_positioner_v6_handle_set_constraint_adjustment,
+ .set_offset = xdg_positioner_v6_handle_set_offset,
+};
+
+void
+create_xdg_positioner_v6(struct ds_xdg_client_v6 *client, uint32_t id)
+{
+ struct ds_xdg_positioner_v6 *positioner;
+
+ positioner = calloc(1, sizeof(*positioner));
+ if (!positioner) {
+ wl_client_post_no_memory(client->wl_client);
+ return;
+ }
+
+ positioner->resource = wl_resource_create(client->wl_client,
+ &zxdg_positioner_v6_interface,
+ wl_resource_get_version(client->resource),
+ id);
+ if (!positioner->resource) {
+ free(positioner);
+ wl_client_post_no_memory(client->wl_client);
+ return;
+ }
+ wl_resource_set_implementation(positioner->resource,
+ &xdg_positioner_v6_impl,
+ positioner,
+ xdg_positioner_v6_handle_resource_destroy);
+}