mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-22 12:55:58 +01:00
compositor: introduce wlr_surface_reject_pending()
This commit is contained in:
parent
5ae8ce807a
commit
0052078bd3
8 changed files with 59 additions and 21 deletions
|
@ -231,6 +231,9 @@ struct wlr_surface {
|
||||||
|
|
||||||
bool opaque;
|
bool opaque;
|
||||||
|
|
||||||
|
bool handling_commit;
|
||||||
|
bool pending_rejected;
|
||||||
|
|
||||||
int32_t preferred_buffer_scale;
|
int32_t preferred_buffer_scale;
|
||||||
bool preferred_buffer_transform_sent;
|
bool preferred_buffer_transform_sent;
|
||||||
enum wl_output_transform preferred_buffer_transform;
|
enum wl_output_transform preferred_buffer_transform;
|
||||||
|
@ -290,6 +293,15 @@ void wlr_surface_map(struct wlr_surface *surface);
|
||||||
*/
|
*/
|
||||||
void wlr_surface_unmap(struct wlr_surface *surface);
|
void wlr_surface_unmap(struct wlr_surface *surface);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the pending state of a surface as rejected due to a protocol violation,
|
||||||
|
* preventing it from being cached or committed.
|
||||||
|
*
|
||||||
|
* This function must only be used while processing a commit request.
|
||||||
|
*/
|
||||||
|
void wlr_surface_reject_pending(struct wlr_surface *surface, struct wl_resource *resource,
|
||||||
|
uint32_t code, const char *msg, ...);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not this surface currently has an attached buffer. A surface has
|
* Whether or not this surface currently has an attached buffer. A surface has
|
||||||
* an attached buffer when it commits with a non-null buffer in its pending
|
* an attached buffer when it commits with a non-null buffer in its pending
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wayland-server-core.h>
|
#include <wayland-server-core.h>
|
||||||
#include <wlr/render/interface.h>
|
#include <wlr/render/interface.h>
|
||||||
|
@ -200,7 +201,7 @@ static void surface_finalize_pending(struct wlr_surface *surface) {
|
||||||
"is not divisible by scale (%d)", pending->buffer_width,
|
"is not divisible by scale (%d)", pending->buffer_width,
|
||||||
pending->buffer_height, pending->scale);
|
pending->buffer_height, pending->scale);
|
||||||
} else {
|
} else {
|
||||||
wl_resource_post_error(surface->resource,
|
wlr_surface_reject_pending(surface, surface->resource,
|
||||||
WL_SURFACE_ERROR_INVALID_SIZE,
|
WL_SURFACE_ERROR_INVALID_SIZE,
|
||||||
"Buffer size (%dx%d) is not divisible by scale (%d)",
|
"Buffer size (%dx%d) is not divisible by scale (%d)",
|
||||||
pending->buffer_width, pending->buffer_height, pending->scale);
|
pending->buffer_width, pending->buffer_height, pending->scale);
|
||||||
|
@ -567,6 +568,8 @@ static void surface_commit_state(struct wlr_surface *surface,
|
||||||
static void surface_handle_commit(struct wl_client *client,
|
static void surface_handle_commit(struct wl_client *client,
|
||||||
struct wl_resource *resource) {
|
struct wl_resource *resource) {
|
||||||
struct wlr_surface *surface = wlr_surface_from_resource(resource);
|
struct wlr_surface *surface = wlr_surface_from_resource(resource);
|
||||||
|
surface->handling_commit = true;
|
||||||
|
|
||||||
surface_finalize_pending(surface);
|
surface_finalize_pending(surface);
|
||||||
|
|
||||||
if (surface->role != NULL && surface->role->client_commit != NULL &&
|
if (surface->role != NULL && surface->role->client_commit != NULL &&
|
||||||
|
@ -576,6 +579,11 @@ static void surface_handle_commit(struct wl_client *client,
|
||||||
|
|
||||||
wl_signal_emit_mutable(&surface->events.client_commit, NULL);
|
wl_signal_emit_mutable(&surface->events.client_commit, NULL);
|
||||||
|
|
||||||
|
surface->handling_commit = false;
|
||||||
|
if (surface->pending_rejected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (surface->pending.cached_state_locks > 0 || !wl_list_empty(&surface->cached)) {
|
if (surface->pending.cached_state_locks > 0 || !wl_list_empty(&surface->cached)) {
|
||||||
surface_cache_pending(surface);
|
surface_cache_pending(surface);
|
||||||
} else {
|
} else {
|
||||||
|
@ -853,6 +861,26 @@ void wlr_surface_unmap(struct wlr_surface *surface) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wlr_surface_reject_pending(struct wlr_surface *surface, struct wl_resource *resource,
|
||||||
|
uint32_t code, const char *msg, ...) {
|
||||||
|
assert(surface->handling_commit);
|
||||||
|
if (surface->pending_rejected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, msg);
|
||||||
|
|
||||||
|
// XXX: libwayland could expose wl_resource_post_error_vargs() instead
|
||||||
|
char buffer[128]; // Matches the size of the buffer used in libwayland
|
||||||
|
vsnprintf(buffer, sizeof(buffer), msg, args);
|
||||||
|
|
||||||
|
wl_resource_post_error(resource, code, "%s", buffer);
|
||||||
|
surface->pending_rejected = true;
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
bool wlr_surface_set_role(struct wlr_surface *surface, const struct wlr_surface_role *role,
|
bool wlr_surface_set_role(struct wlr_surface *surface, const struct wlr_surface_role *role,
|
||||||
struct wl_resource *error_resource, uint32_t error_code) {
|
struct wl_resource *error_resource, uint32_t error_code) {
|
||||||
assert(role != NULL);
|
assert(role != NULL);
|
||||||
|
|
|
@ -331,7 +331,7 @@ static void layer_surface_role_client_commit(struct wlr_surface *wlr_surface) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wlr_surface_state_has_buffer(&wlr_surface->pending) && !surface->configured) {
|
if (wlr_surface_state_has_buffer(&wlr_surface->pending) && !surface->configured) {
|
||||||
wl_resource_post_error(surface->resource,
|
wlr_surface_reject_pending(wlr_surface, surface->resource,
|
||||||
ZWLR_LAYER_SHELL_V1_ERROR_ALREADY_CONSTRUCTED,
|
ZWLR_LAYER_SHELL_V1_ERROR_ALREADY_CONSTRUCTED,
|
||||||
"layer_surface has never been configured");
|
"layer_surface has never been configured");
|
||||||
return;
|
return;
|
||||||
|
@ -341,7 +341,7 @@ static void layer_surface_role_client_commit(struct wlr_surface *wlr_surface) {
|
||||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
|
||||||
if (surface->pending.desired_width == 0 &&
|
if (surface->pending.desired_width == 0 &&
|
||||||
(surface->pending.anchor & horiz) != horiz) {
|
(surface->pending.anchor & horiz) != horiz) {
|
||||||
wl_resource_post_error(surface->resource,
|
wlr_surface_reject_pending(wlr_surface, surface->resource,
|
||||||
ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SIZE,
|
ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SIZE,
|
||||||
"width 0 requested without setting left and right anchors");
|
"width 0 requested without setting left and right anchors");
|
||||||
return;
|
return;
|
||||||
|
@ -351,7 +351,7 @@ static void layer_surface_role_client_commit(struct wlr_surface *wlr_surface) {
|
||||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
|
||||||
if (surface->pending.desired_height == 0 &&
|
if (surface->pending.desired_height == 0 &&
|
||||||
(surface->pending.anchor & vert) != vert) {
|
(surface->pending.anchor & vert) != vert) {
|
||||||
wl_resource_post_error(surface->resource,
|
wlr_surface_reject_pending(wlr_surface, surface->resource,
|
||||||
ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SIZE,
|
ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SIZE,
|
||||||
"height 0 requested without setting top and bottom anchors");
|
"height 0 requested without setting top and bottom anchors");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -157,14 +157,14 @@ static void lock_surface_role_client_commit(struct wlr_surface *surface) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wlr_surface_state_has_buffer(&surface->pending)) {
|
if (!wlr_surface_state_has_buffer(&surface->pending)) {
|
||||||
wl_resource_post_error(lock_surface->resource,
|
wlr_surface_reject_pending(surface, lock_surface->resource,
|
||||||
EXT_SESSION_LOCK_SURFACE_V1_ERROR_NULL_BUFFER,
|
EXT_SESSION_LOCK_SURFACE_V1_ERROR_NULL_BUFFER,
|
||||||
"session lock surface is committed with a null buffer");
|
"session lock surface is committed with a null buffer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lock_surface->configured) {
|
if (!lock_surface->configured) {
|
||||||
wl_resource_post_error(lock_surface->resource,
|
wlr_surface_reject_pending(surface, lock_surface->resource,
|
||||||
EXT_SESSION_LOCK_SURFACE_V1_ERROR_COMMIT_BEFORE_FIRST_ACK,
|
EXT_SESSION_LOCK_SURFACE_V1_ERROR_COMMIT_BEFORE_FIRST_ACK,
|
||||||
"session lock surface has never been configured");
|
"session lock surface has never been configured");
|
||||||
return;
|
return;
|
||||||
|
@ -172,7 +172,7 @@ static void lock_surface_role_client_commit(struct wlr_surface *surface) {
|
||||||
|
|
||||||
if ((uint32_t)surface->pending.width != lock_surface->pending.width ||
|
if ((uint32_t)surface->pending.width != lock_surface->pending.width ||
|
||||||
(uint32_t)surface->pending.height != lock_surface->pending.height) {
|
(uint32_t)surface->pending.height != lock_surface->pending.height) {
|
||||||
wl_resource_post_error(lock_surface->resource,
|
wlr_surface_reject_pending(surface, lock_surface->resource,
|
||||||
EXT_SESSION_LOCK_SURFACE_V1_ERROR_DIMENSIONS_MISMATCH,
|
EXT_SESSION_LOCK_SURFACE_V1_ERROR_DIMENSIONS_MISMATCH,
|
||||||
"committed surface dimensions do not match last acked configure");
|
"committed surface dimensions do not match last acked configure");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -151,7 +151,8 @@ static void viewport_handle_surface_client_commit(struct wl_listener *listener,
|
||||||
if (!state->viewport.has_dst &&
|
if (!state->viewport.has_dst &&
|
||||||
(floor(state->viewport.src.width) != state->viewport.src.width ||
|
(floor(state->viewport.src.width) != state->viewport.src.width ||
|
||||||
floor(state->viewport.src.height) != state->viewport.src.height)) {
|
floor(state->viewport.src.height) != state->viewport.src.height)) {
|
||||||
wl_resource_post_error(viewport->resource, WP_VIEWPORT_ERROR_BAD_SIZE,
|
wlr_surface_reject_pending(viewport->surface,
|
||||||
|
viewport->resource, WP_VIEWPORT_ERROR_BAD_SIZE,
|
||||||
"wl_viewport.set_source width and height must be integers "
|
"wl_viewport.set_source width and height must be integers "
|
||||||
"when the destination rectangle is unset");
|
"when the destination rectangle is unset");
|
||||||
return;
|
return;
|
||||||
|
@ -159,7 +160,8 @@ static void viewport_handle_surface_client_commit(struct wl_listener *listener,
|
||||||
|
|
||||||
if (state->viewport.has_src && state->buffer != NULL &&
|
if (state->viewport.has_src && state->buffer != NULL &&
|
||||||
!check_src_buffer_bounds(state)) {
|
!check_src_buffer_bounds(state)) {
|
||||||
wl_resource_post_error(viewport->resource, WP_VIEWPORT_ERROR_OUT_OF_BUFFER,
|
wlr_surface_reject_pending(viewport->surface,
|
||||||
|
viewport->resource, WP_VIEWPORT_ERROR_OUT_OF_BUFFER,
|
||||||
"source rectangle out of buffer bounds");
|
"source rectangle out of buffer bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,9 +240,8 @@ static struct wlr_xdg_popup_grab *get_xdg_shell_popup_grab_from_seat(
|
||||||
|
|
||||||
void handle_xdg_popup_client_commit(struct wlr_xdg_popup *popup) {
|
void handle_xdg_popup_client_commit(struct wlr_xdg_popup *popup) {
|
||||||
if (!popup->parent) {
|
if (!popup->parent) {
|
||||||
wl_resource_post_error(popup->base->resource,
|
wlr_surface_reject_pending(popup->base->surface, popup->base->resource,
|
||||||
XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
|
XDG_SURFACE_ERROR_NOT_CONSTRUCTED, "xdg_popup has no parent");
|
||||||
"xdg_popup has no parent");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,16 +261,14 @@ static void xdg_surface_role_client_commit(struct wlr_surface *wlr_surface) {
|
||||||
assert(surface != NULL);
|
assert(surface != NULL);
|
||||||
|
|
||||||
if (wlr_surface_state_has_buffer(&wlr_surface->pending) && !surface->configured) {
|
if (wlr_surface_state_has_buffer(&wlr_surface->pending) && !surface->configured) {
|
||||||
wl_resource_post_error(surface->resource,
|
wlr_surface_reject_pending(wlr_surface, surface->resource,
|
||||||
XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER,
|
XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER, "xdg_surface has never been configured");
|
||||||
"xdg_surface has never been configured");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface->role_resource == NULL) {
|
if (surface->role_resource == NULL) {
|
||||||
wl_resource_post_error(surface->resource,
|
wlr_surface_reject_pending(wlr_surface, surface->resource,
|
||||||
XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
|
XDG_SURFACE_ERROR_NOT_CONSTRUCTED, "xdg_surface must have a role object");
|
||||||
"xdg_surface must have a role object");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,9 +125,8 @@ void handle_xdg_toplevel_client_commit(struct wlr_xdg_toplevel *toplevel) {
|
||||||
pending->max_width < 0 || pending->max_height < 0 ||
|
pending->max_width < 0 || pending->max_height < 0 ||
|
||||||
(pending->max_width != 0 && pending->max_width < pending->min_width) ||
|
(pending->max_width != 0 && pending->max_width < pending->min_width) ||
|
||||||
(pending->max_height != 0 && pending->max_height < pending->min_height)) {
|
(pending->max_height != 0 && pending->max_height < pending->min_height)) {
|
||||||
wl_resource_post_error(toplevel->resource,
|
wlr_surface_reject_pending(toplevel->base->surface, toplevel->resource,
|
||||||
XDG_TOPLEVEL_ERROR_INVALID_SIZE,
|
XDG_TOPLEVEL_ERROR_INVALID_SIZE, "client provided an invalid min or max size");
|
||||||
"client provided an invalid min or max size");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue