aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/headless/output.c2
-rw-r--r--backend/wayland/output.c2
-rw-r--r--include/types/wlr_output.h2
-rw-r--r--types/output/output.c40
4 files changed, 44 insertions, 2 deletions
diff --git a/backend/headless/output.c b/backend/headless/output.c
index f4719a3c..a6c97dec 100644
--- a/backend/headless/output.c
+++ b/backend/headless/output.c
@@ -71,7 +71,7 @@ static bool output_commit(struct wlr_output *wlr_output,
.commit_seq = wlr_output->commit_seq + 1,
.presented = true,
};
- wlr_output_send_present(wlr_output, &present_event);
+ output_defer_present(wlr_output, present_event);
wl_event_source_timer_update(output->frame_timer, output->frame_delay);
}
diff --git a/backend/wayland/output.c b/backend/wayland/output.c
index e51be4c5..2e5c39f5 100644
--- a/backend/wayland/output.c
+++ b/backend/wayland/output.c
@@ -590,7 +590,7 @@ static bool output_commit(struct wlr_output *wlr_output,
.commit_seq = wlr_output->commit_seq + 1,
.presented = true,
};
- wlr_output_send_present(wlr_output, &present_event);
+ output_defer_present(wlr_output, present_event);
}
}
diff --git a/include/types/wlr_output.h b/include/types/wlr_output.h
index b885fd08..e1aea1be 100644
--- a/include/types/wlr_output.h
+++ b/include/types/wlr_output.h
@@ -21,4 +21,6 @@ bool output_cursor_set_texture(struct wlr_output_cursor *cursor,
int dst_width, int dst_height, enum wl_output_transform transform,
int32_t hotspot_x, int32_t hotspot_y);
+void output_defer_present(struct wlr_output *output, struct wlr_output_event_present event);
+
#endif
diff --git a/types/output/output.c b/types/output/output.c
index 278ecb9e..a9a0ccb2 100644
--- a/types/output/output.c
+++ b/types/output/output.c
@@ -927,6 +927,46 @@ void wlr_output_send_present(struct wlr_output *output,
wl_signal_emit_mutable(&output->events.present, event);
}
+struct deferred_present_event {
+ struct wlr_output *output;
+ struct wl_event_source *idle_source;
+ struct wlr_output_event_present event;
+ struct wl_listener output_destroy;
+};
+
+static void deferred_present_event_destroy(struct deferred_present_event *deferred) {
+ wl_list_remove(&deferred->output_destroy.link);
+ free(deferred);
+}
+
+static void deferred_present_event_handle_idle(void *data) {
+ struct deferred_present_event *deferred = data;
+ wlr_output_send_present(deferred->output, &deferred->event);
+ deferred_present_event_destroy(deferred);
+}
+
+static void deferred_present_event_handle_output_destroy(struct wl_listener *listener, void *data) {
+ struct deferred_present_event *deferred = wl_container_of(listener, deferred, output_destroy);
+ wl_event_source_remove(deferred->idle_source);
+ deferred_present_event_destroy(deferred);
+}
+
+void output_defer_present(struct wlr_output *output, struct wlr_output_event_present event) {
+ struct deferred_present_event *deferred = calloc(1, sizeof(struct wlr_output_event_present));
+ if (!deferred) {
+ return;
+ }
+ *deferred = (struct deferred_present_event){
+ .output = output,
+ .event = event,
+ };
+ deferred->output_destroy.notify = deferred_present_event_handle_output_destroy;
+ wl_signal_add(&output->events.destroy, &deferred->output_destroy);
+
+ struct wl_event_loop *ev = wl_display_get_event_loop(output->display);
+ deferred->idle_source = wl_event_loop_add_idle(ev, deferred_present_event_handle_idle, deferred);
+}
+
void wlr_output_send_request_state(struct wlr_output *output,
const struct wlr_output_state *state) {
uint32_t unchanged = output_compare_state(output, state);