aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2023-12-08 14:22:19 +0100
committerSimon Ser <contact@emersion.fr>2023-12-25 18:55:30 +0100
commit1968ada2132237f5bf8e40b6bf903fbce76c0b40 (patch)
tree4f89bb47cbe00f0ec0197a486def8a07f84f345c
parent0ea6b6e2cc490f3fbd0b92b03c0ae6eed2c0bbbf (diff)
tearing-control-v1: synchronize state with surface
-rw-r--r--include/wlr/types/wlr_tearing_control_v1.h9
-rw-r--r--types/wlr_tearing_control_v1.c38
2 files changed, 38 insertions, 9 deletions
diff --git a/include/wlr/types/wlr_tearing_control_v1.h b/include/wlr/types/wlr_tearing_control_v1.h
index 31cc5bef..76c5c600 100644
--- a/include/wlr/types/wlr_tearing_control_v1.h
+++ b/include/wlr/types/wlr_tearing_control_v1.h
@@ -17,11 +17,12 @@
#include "tearing-control-v1-protocol.h"
struct wlr_tearing_control_v1 {
- uint32_t hint;
struct wl_client *client;
struct wl_list link;
struct wl_resource *resource;
+ enum wp_tearing_control_v1_presentation_hint current, pending;
+
struct {
struct wl_signal set_hint;
struct wl_signal destroy;
@@ -29,7 +30,13 @@ struct wlr_tearing_control_v1 {
struct wlr_surface *surface;
+ // private state
+
+ enum wp_tearing_control_v1_presentation_hint previous;
struct wlr_addon addon;
+ struct wlr_surface_synced synced;
+
+ struct wl_listener surface_commit;
};
struct wlr_tearing_control_manager_v1 {
diff --git a/types/wlr_tearing_control_v1.c b/types/wlr_tearing_control_v1.c
index f22eb6ed..a1898b4d 100644
--- a/types/wlr_tearing_control_v1.c
+++ b/types/wlr_tearing_control_v1.c
@@ -39,6 +39,8 @@ static void destroy_tearing_hint(struct wlr_tearing_control_v1 *hint) {
wl_resource_set_user_data(hint->resource, NULL);
wlr_addon_finish(&hint->addon);
+ wlr_surface_synced_finish(&hint->synced);
+ wl_list_remove(&hint->surface_commit.link);
free(hint);
}
@@ -64,21 +66,32 @@ static void destroy_tearing_resource_impl(struct wl_resource *resource) {
destroy_tearing_hint(hint);
}
-static void tearing_control_handle_presentation_hint(struct wl_client *client,
+static void tearing_control_handle_set_presentation_hint(struct wl_client *client,
struct wl_resource *resource, uint32_t hint) {
struct wlr_tearing_control_v1 *surface_hint =
tearing_surface_hint_from_resource(resource);
-
- surface_hint->hint = hint;
-
- wl_signal_emit_mutable(&surface_hint->events.set_hint, NULL);
+ surface_hint->pending = hint;
}
static const struct wp_tearing_control_v1_interface tearing_control_impl = {
.destroy = resource_handle_destroy,
- .set_presentation_hint = tearing_control_handle_presentation_hint
+ .set_presentation_hint = tearing_control_handle_set_presentation_hint,
+};
+
+static const struct wlr_surface_synced_impl surface_synced_impl = {
+ .state_size = sizeof(enum wp_tearing_control_v1_presentation_hint),
};
+static void hint_handle_surface_commit(struct wl_listener *listener, void *data) {
+ struct wlr_tearing_control_v1 *hint = wl_container_of(listener, hint, surface_commit);
+
+ if (hint->current != hint->previous) {
+ wl_signal_emit_mutable(&hint->events.set_hint, NULL);
+ }
+
+ hint->previous = hint->current;
+}
+
static void tearing_control_manager_handle_get_tearing_control(
struct wl_client *client, struct wl_resource *resource, uint32_t id,
struct wl_resource *surface_resource) {
@@ -98,6 +111,13 @@ static void tearing_control_manager_handle_get_tearing_control(
return;
}
+ if (!wlr_surface_synced_init(&hint->synced, surface,
+ &surface_synced_impl, &hint->pending, &hint->current)) {
+ free(hint);
+ wl_client_post_no_memory(client);
+ return;
+ }
+
struct wl_resource *created_resource =
wl_resource_create(client, &wp_tearing_control_v1_interface,
wl_resource_get_version(resource), id);
@@ -110,7 +130,6 @@ static void tearing_control_manager_handle_get_tearing_control(
wl_resource_set_implementation(created_resource, &tearing_control_impl,
hint, destroy_tearing_resource_impl);
- hint->hint = WP_TEARING_CONTROL_V1_PRESENTATION_HINT_VSYNC;
hint->client = client;
hint->resource = created_resource;
hint->surface = surface;
@@ -119,6 +138,9 @@ static void tearing_control_manager_handle_get_tearing_control(
wl_signal_init(&hint->events.set_hint);
wl_signal_init(&hint->events.destroy);
+ hint->surface_commit.notify = hint_handle_surface_commit;
+ wl_signal_add(&surface->events.commit, &hint->surface_commit);
+
wl_list_insert(&manager->surface_hints, &hint->link);
wl_signal_emit_mutable(&manager->events.new_object, hint);
@@ -198,5 +220,5 @@ wlr_tearing_control_manager_v1_surface_hint_from_surface(struct wlr_tearing_cont
struct wlr_tearing_control_v1 *hint = wl_container_of(addon, hint, addon);
- return hint->hint;
+ return hint->current;
}