diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h
index 7ef3de98..cfad8f70 100644
--- a/include/wlr/interfaces/wlr_output.h
+++ b/include/wlr/interfaces/wlr_output.h
@@ -146,5 +146,10 @@ void wlr_output_send_frame(struct wlr_output *output);
  */
 void wlr_output_send_present(struct wlr_output *output,
 	struct wlr_output_event_present *event);
+/**
+ * Request the compositor to apply new state.
+ */
+void wlr_output_send_request_state(struct wlr_output *output,
+	const struct wlr_output_state *state);
 
 #endif
diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h
index 6b39cfc8..bb056b30 100644
--- a/include/wlr/types/wlr_output.h
+++ b/include/wlr/types/wlr_output.h
@@ -178,6 +178,7 @@ struct wlr_output {
 		struct wl_signal enable;
 		struct wl_signal mode;
 		struct wl_signal description;
+		struct wl_signal request_state;
 		struct wl_signal destroy;
 	} events;
 
@@ -258,6 +259,11 @@ struct wlr_output_event_bind {
 	struct wl_resource *resource;
 };
 
+struct wlr_output_event_request_state {
+	struct wlr_output *output;
+	const struct wlr_output_state *state;
+};
+
 struct wlr_surface;
 
 /**
diff --git a/types/output/output.c b/types/output/output.c
index ab10286b..405e4481 100644
--- a/types/output/output.c
+++ b/types/output/output.c
@@ -935,6 +935,22 @@ void wlr_output_send_present(struct wlr_output *output,
 	wl_signal_emit_mutable(&output->events.present, event);
 }
 
+void wlr_output_send_request_state(struct wlr_output *output,
+		const struct wlr_output_state *state) {
+	uint32_t unchanged = output_compare_state(output, state);
+	struct wlr_output_state copy = *state;
+	copy.committed &= ~unchanged;
+	if (copy.committed == 0) {
+		return;
+	}
+
+	struct wlr_output_event_request_state event = {
+		.output = output,
+		.state = &copy,
+	};
+	wl_signal_emit_mutable(&output->events.request_state, &event);
+}
+
 void wlr_output_set_gamma(struct wlr_output *output, size_t size,
 		const uint16_t *r, const uint16_t *g, const uint16_t *b) {
 	uint16_t *gamma_lut = NULL;