diff options
author | Isaac Freund <mail@isaacfreund.com> | 2022-12-21 17:52:48 +0100 |
---|---|---|
committer | Isaac Freund <mail@isaacfreund.com> | 2022-12-23 16:56:42 +0100 |
commit | 869af1cfbb3944d32d59a4c08ca439e7b5eaf6d2 (patch) | |
tree | 81b4249b47bd0e57031ae2443e51b06d343725f9 | |
parent | 48a89179a3383363accefdd8b1c3d15da602ff5f (diff) |
session-lock: send more protocol errors
The invalid_destroy and invalid_unlock protocol errors aren't currently
sent by wlroots and instead left up to the compositor. However, we can
handle these as well without much additional complexity.
This also adds a missing wl_resource_destroy() call if the lock is inert
in lock_handle_unlock_and_destroy().
-rw-r--r-- | include/wlr/types/wlr_session_lock_v1.h | 4 | ||||
-rw-r--r-- | types/wlr_session_lock_v1.c | 36 |
2 files changed, 38 insertions, 2 deletions
diff --git a/include/wlr/types/wlr_session_lock_v1.h b/include/wlr/types/wlr_session_lock_v1.h index 6ad18df7..b6eee1a3 100644 --- a/include/wlr/types/wlr_session_lock_v1.h +++ b/include/wlr/types/wlr_session_lock_v1.h @@ -40,6 +40,10 @@ struct wlr_session_lock_v1 { } events; void *data; + + // private state + + bool locked_sent; }; struct wlr_session_lock_surface_v1_state { diff --git a/types/wlr_session_lock_v1.c b/types/wlr_session_lock_v1.c index 8a933fb9..aaa46fd8 100644 --- a/types/wlr_session_lock_v1.c +++ b/types/wlr_session_lock_v1.c @@ -126,7 +126,6 @@ static void lock_surface_handle_ack_configure(struct wl_client *client, free(configure); } - static const struct ext_session_lock_surface_v1_interface lock_surface_implementation = { .destroy = resource_handle_destroy, .ack_configure = lock_surface_handle_ack_configure, @@ -306,6 +305,17 @@ static void lock_handle_unlock_and_destroy(struct wl_client *client, struct wl_resource *lock_resource) { struct wlr_session_lock_v1 *lock = lock_from_resource(lock_resource); if (lock == NULL) { + // This can happen if the compositor sent the locked event and + // later the finished event as the lock is destroyed when the + // finished event is sent. + wl_resource_destroy(lock_resource); + return; + } + + if (!lock->locked_sent) { + wl_resource_post_error(lock_resource, + EXT_SESSION_LOCK_V1_ERROR_INVALID_UNLOCK, + "the locked event was never sent"); return; } @@ -314,13 +324,35 @@ static void lock_handle_unlock_and_destroy(struct wl_client *client, wl_resource_destroy(lock_resource); } +static void lock_handle_destroy(struct wl_client *client, + struct wl_resource *lock_resource) { + struct wlr_session_lock_v1 *lock = lock_from_resource(lock_resource); + if (lock == NULL) { + // The compositor sent the finished event and destroyed the lock. + wl_resource_destroy(lock_resource); + return; + } + + if (lock->locked_sent) { + wl_resource_post_error(lock_resource, + EXT_SESSION_LOCK_V1_ERROR_INVALID_DESTROY, + "the session lock may not be destroyed while locked"); + } else { + wl_resource_post_error(lock_resource, + EXT_SESSION_LOCK_V1_ERROR_INVALID_DESTROY, + "the finished event was never sent"); + } +} + static const struct ext_session_lock_v1_interface lock_implementation = { - .destroy = resource_handle_destroy, + .destroy = lock_handle_destroy, .get_lock_surface = lock_handle_get_lock_surface, .unlock_and_destroy = lock_handle_unlock_and_destroy, }; void wlr_session_lock_v1_send_locked(struct wlr_session_lock_v1 *lock) { + assert(!lock->locked_sent); + lock->locked_sent = true; ext_session_lock_v1_send_locked(lock->resource); } |