diff --git a/include/sway/output.h b/include/sway/output.h index f6dc6af2..50d90d25 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -57,6 +57,7 @@ struct sway_output { uint32_t refresh_nsec; int max_render_time; // In milliseconds struct wl_event_source *repaint_timer; + bool gamma_lut_changed; }; struct sway_output_non_desktop { @@ -187,6 +188,8 @@ enum wlr_direction opposite_direction(enum wlr_direction d); void handle_output_layout_change(struct wl_listener *listener, void *data); +void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data); + void handle_output_manager_apply(struct wl_listener *listener, void *data); void handle_output_manager_test(struct wl_listener *listener, void *data); diff --git a/include/sway/server.h b/include/sway/server.h index a65843ce..aaa8781b 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -91,6 +91,9 @@ struct sway_server { struct wl_listener output_manager_apply; struct wl_listener output_manager_test; + struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1; + struct wl_listener gamma_control_set_gamma; + struct { bool locked; struct wlr_session_lock_manager_v1 *manager; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 43ce2d70..09353c15 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -564,6 +565,7 @@ static int output_repaint_timer_handler(void *data) { wlr_output->frame_pending = false; if (!wlr_output->needs_frame && + !output->gamma_lut_changed && !pixman_region32_not_empty(&output->damage_ring.current)) { return 0; } @@ -578,6 +580,19 @@ static int output_repaint_timer_handler(void *data) { fullscreen_con = workspace->current.fullscreen; } + if (output->gamma_lut_changed) { + struct wlr_gamma_control_v1 *gamma_control = + wlr_gamma_control_manager_v1_get_control( + server.gamma_control_manager_v1, wlr_output); + if (!wlr_gamma_control_v1_apply(gamma_control, &wlr_output->pending)) { + return 0; + } + if (!wlr_output_test(wlr_output)) { + wlr_output_rollback(wlr_output); + wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); + } + } + pixman_region32_t frame_damage; get_frame_damage(output, &frame_damage); wlr_output_set_damage(wlr_output, &frame_damage); @@ -1076,6 +1091,16 @@ void handle_output_layout_change(struct wl_listener *listener, update_output_manager_config(server); } +void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data) { + struct sway_server *server = + wl_container_of(listener, server, gamma_control_set_gamma); + const struct wlr_gamma_control_manager_v1_set_gamma_event *event = data; + + struct sway_output *output = event->output->data; + output->gamma_lut_changed = true; + wlr_output_schedule_frame(output->wlr_output); +} + static void output_manager_apply(struct sway_server *server, struct wlr_output_configuration_v1 *config, bool test_only) { // TODO: perform atomic tests on the whole backend atomically diff --git a/sway/server.c b/sway/server.c index c87e30fd..9797cf60 100644 --- a/sway/server.c +++ b/sway/server.c @@ -114,7 +114,11 @@ bool server_init(struct sway_server *server) { server->data_device_manager = wlr_data_device_manager_create(server->wl_display); - wlr_gamma_control_manager_v1_create(server->wl_display); + server->gamma_control_manager_v1 = + wlr_gamma_control_manager_v1_create(server->wl_display); + server->gamma_control_set_gamma.notify = handle_gamma_control_set_gamma; + wl_signal_add(&server->gamma_control_manager_v1->events.set_gamma, + &server->gamma_control_set_gamma); server->new_output.notify = handle_new_output; wl_signal_add(&server->backend->events.new_output, &server->new_output);