mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-12 16:35:58 +01:00
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:
parent
6b7a55aa3d
commit
3994762ae0
8 changed files with 123 additions and 20 deletions
|
@ -159,6 +159,14 @@ void wlr_surface_send_leave(struct wlr_surface *surface,
|
|||
void wlr_surface_send_frame_done(struct wlr_surface *surface,
|
||||
const struct timespec *when);
|
||||
|
||||
struct wlr_box;
|
||||
/**
|
||||
* Get the bounding box that contains the surface and all subsurfaces in
|
||||
* surface coordinates.
|
||||
* X and y may be negative, if there are subsurfaces with negative position.
|
||||
*/
|
||||
void wlr_surface_get_extends(struct wlr_surface *surface, struct wlr_box *box);
|
||||
|
||||
/**
|
||||
* Set a callback for surface commit that runs before all the other callbacks.
|
||||
* This is intended for use by the surface role.
|
||||
|
|
|
@ -341,6 +341,15 @@ bool wlr_surface_is_xdg_surface(struct wlr_surface *surface);
|
|||
struct wlr_xdg_surface *wlr_xdg_surface_from_wlr_surface(
|
||||
struct wlr_surface *surface);
|
||||
|
||||
/**
|
||||
* Get the surface geometry.
|
||||
* This is either the geometry as set by the client, or defaulted to the bounds
|
||||
* of the surface + the subsurfaces (as specified by the protocol).
|
||||
*
|
||||
* The x and y value can be <0
|
||||
*/
|
||||
void wlr_xdg_surface_get_geometry(struct wlr_xdg_surface *surface, struct wlr_box *box);
|
||||
|
||||
/**
|
||||
* Call `iterator` on each surface in the xdg-surface tree, with the surface's
|
||||
* position relative to the root xdg-surface. The function is called from root to
|
||||
|
|
|
@ -318,6 +318,15 @@ bool wlr_surface_is_xdg_surface_v6(struct wlr_surface *surface);
|
|||
struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6_from_wlr_surface(
|
||||
struct wlr_surface *surface);
|
||||
|
||||
/**
|
||||
* Get the surface geometry.
|
||||
* This is either the geometry as set by the client, or defaulted to the bounds
|
||||
* of the surface + the subsurfaces (as specified by the protocol).
|
||||
*
|
||||
* The x and y value can be <0
|
||||
*/
|
||||
void wlr_xdg_surface_v6_get_geometry(struct wlr_xdg_surface_v6 *surface, struct wlr_box *box);
|
||||
|
||||
/**
|
||||
* Call `iterator` on each surface in the xdg-surface tree, with the surface's
|
||||
* position relative to the root xdg-surface. The function is called from root to
|
||||
|
|
|
@ -132,14 +132,10 @@ static void get_size(const struct roots_view *view, struct wlr_box *box) {
|
|||
assert(view->type == ROOTS_XDG_SHELL_VIEW);
|
||||
struct wlr_xdg_surface *surface = view->xdg_surface;
|
||||
|
||||
if (surface->geometry.width > 0 && surface->geometry.height > 0) {
|
||||
box->width = surface->geometry.width;
|
||||
box->height = surface->geometry.height;
|
||||
} else {
|
||||
assert(surface->surface);
|
||||
box->width = surface->surface->current->width;
|
||||
box->height = surface->surface->current->height;
|
||||
}
|
||||
struct wlr_box geo_box;
|
||||
wlr_xdg_surface_get_geometry(surface, &geo_box);
|
||||
box->width = geo_box.width;
|
||||
box->height = geo_box.height;
|
||||
}
|
||||
|
||||
static void activate(struct roots_view *view, bool active) {
|
||||
|
|
|
@ -133,14 +133,10 @@ static void get_size(const struct roots_view *view, struct wlr_box *box) {
|
|||
assert(view->type == ROOTS_XDG_SHELL_V6_VIEW);
|
||||
struct wlr_xdg_surface_v6 *surface = view->xdg_surface_v6;
|
||||
|
||||
if (surface->geometry.width > 0 && surface->geometry.height > 0) {
|
||||
box->width = surface->geometry.width;
|
||||
box->height = surface->geometry.height;
|
||||
} else {
|
||||
assert(surface->surface);
|
||||
box->width = surface->surface->current->width;
|
||||
box->height = surface->surface->current->height;
|
||||
}
|
||||
struct wlr_box geo_box;
|
||||
wlr_xdg_surface_v6_get_geometry(surface, &geo_box);
|
||||
box->width = geo_box.width;
|
||||
box->height = geo_box.height;
|
||||
}
|
||||
|
||||
static void activate(struct roots_view *view, bool active) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue