Add wlr_surface_get_geometry

This function defaults and clips the xdg-surface geometry to the
bounding box of the surface + its subsurfaces, as specified by the
protocol spec.
This commit is contained in:
Markus Ongyerth 2018-06-01 13:27:10 +02:00
parent 6b7a55aa3d
commit 3994762ae0
8 changed files with 123 additions and 20 deletions

View file

@ -16,6 +16,22 @@
#define SURFACE_VERSION 4
#define SUBSURFACE_VERSION 1
static int min(int fst, int snd) {
if (fst < snd) {
return fst;
} else {
return snd;
}
}
static int max(int fst, int snd) {
if (fst > snd) {
return fst;
} else {
return snd;
}
}
static void surface_state_reset_buffer(struct wlr_surface_state *state) {
if (state->buffer) {
wl_list_remove(&state->buffer_destroy_listener.link);
@ -1036,3 +1052,35 @@ void wlr_surface_for_each_surface(struct wlr_surface *surface,
wlr_surface_iterator_func_t iterator, void *user_data) {
surface_for_each_surface(surface, 0, 0, iterator, user_data);
}
struct bound_acc {
int32_t min_x, min_y;
int32_t max_x, max_y;
};
static void handle_bounding_box_surface(struct wlr_surface *surface,
int x, int y, void *data) {
struct bound_acc *acc = data;
acc->min_x = min(x, acc->min_x);
acc->min_y = min(x, acc->min_y);
acc->max_x = max(x + surface->current->width, acc->max_x);
acc->max_y = max(y + surface->current->height, acc->max_y);
}
void wlr_surface_get_extends(struct wlr_surface *surface, struct wlr_box *box) {
struct bound_acc acc = {
.min_x = 0,
.min_y = 0,
.max_x = surface->current->width,
.max_y = surface->current->height,
};
wlr_surface_for_each_surface(surface, handle_bounding_box_surface, &acc);
box->x = acc.min_x;
box->y = acc.min_y;
box->width = acc.max_x - acc.min_x;
box->height = acc.max_y - acc.min_y;
}

View file

@ -251,6 +251,13 @@ static void xdg_surface_handle_set_window_geometry(struct wl_client *client,
return;
}
if (width <= 0 || height <= 0) {
wlr_log(L_ERROR, "Client tried to set invalid geometry");
//XXX: Switch to the proper error value once available
wl_resource_post_error(resource, -1, "Tried to set invalid xdg-surface geometry");
return;
}
surface->has_next_geometry = true;
surface->next_geometry.height = height;
surface->next_geometry.width = width;
@ -474,9 +481,11 @@ static void xdg_popup_get_position(struct wlr_xdg_popup *popup,
double *popup_sx, double *popup_sy) {
struct wlr_xdg_surface *parent =
wlr_xdg_surface_from_wlr_surface(popup->parent);
*popup_sx = parent->geometry.x + popup->geometry.x -
struct wlr_box parent_geo;
wlr_xdg_surface_get_geometry(parent, &parent_geo);
*popup_sx = parent_geo.x + popup->geometry.x -
popup->base->geometry.x;
*popup_sy = parent->geometry.y + popup->geometry.y -
*popup_sy = parent_geo.y + popup->geometry.y -
popup->base->geometry.y;
}
@ -546,3 +555,13 @@ void wlr_xdg_surface_for_each_surface(struct wlr_xdg_surface *surface,
wlr_surface_iterator_func_t iterator, void *user_data) {
xdg_surface_for_each_surface(surface, 0, 0, iterator, user_data);
}
void wlr_xdg_surface_get_geometry(struct wlr_xdg_surface *surface, struct wlr_box *box) {
wlr_surface_get_extends(surface->surface, box);
/* The client never set the geometry */
if (!surface->geometry.width) {
return;
}
wlr_box_intersection(&surface->geometry, box, box);
}

View file

@ -198,6 +198,12 @@ static void xdg_surface_handle_set_window_geometry(struct wl_client *client,
return;
}
if (width <= 0 || height <= 0) {
wlr_log(L_ERROR, "Client tried to set invalid geometry");
wl_resource_post_error(resource, -1, "Tried to set invalid xdg-surface geometry");
}
surface->has_next_geometry = true;
surface->next_geometry.height = height;
surface->next_geometry.width = width;
@ -454,9 +460,11 @@ struct wlr_xdg_surface_v6 *create_xdg_surface_v6(
static void xdg_popup_v6_get_position(struct wlr_xdg_popup_v6 *popup,
double *popup_sx, double *popup_sy) {
struct wlr_xdg_surface_v6 *parent = popup->parent;
*popup_sx = parent->geometry.x + popup->geometry.x -
struct wlr_box parent_geo;
wlr_xdg_surface_v6_get_geometry(parent, &parent_geo);
*popup_sx = parent_geo.x + popup->geometry.x -
popup->base->geometry.x;
*popup_sy = parent->geometry.y + popup->geometry.y -
*popup_sy = parent_geo.y + popup->geometry.y -
popup->base->geometry.y;
}
@ -526,3 +534,13 @@ void wlr_xdg_surface_v6_for_each_surface(struct wlr_xdg_surface_v6 *surface,
wlr_surface_iterator_func_t iterator, void *user_data) {
xdg_surface_v6_for_each_surface(surface, 0, 0, iterator, user_data);
}
void wlr_xdg_surface_v6_get_geometry(struct wlr_xdg_surface_v6 *surface, struct wlr_box *box) {
wlr_surface_get_extends(surface->surface, box);
/* The client never set the geometry */
if (!surface->geometry.width) {
return;
}
wlr_box_intersection(&surface->geometry, box, box);
}