diff --git a/include/wlr/types/wlr_idle.h b/include/wlr/types/wlr_idle.h index d8c81a60..da268555 100644 --- a/include/wlr/types/wlr_idle.h +++ b/include/wlr/types/wlr_idle.h @@ -46,6 +46,12 @@ struct wlr_idle_timeout { bool enabled; uint32_t timeout; // milliseconds + struct { + struct wl_signal idle; + struct wl_signal resume; + struct wl_signal destroy; + } events; + struct wl_listener input_listener; struct wl_listener seat_destroy; @@ -68,4 +74,15 @@ void wlr_idle_notify_activity(struct wlr_idle *idle, struct wlr_seat *seat); */ void wlr_idle_set_enabled(struct wlr_idle *idle, struct wlr_seat *seat, bool enabled); + +/** + * Create a new timer on the given seat. The idle event will be called after + * the given amount of milliseconds of inactivity, and the resumed event will + * be sent at the first user activty after the fired event. + */ +struct wlr_idle_timeout *wlr_idle_timeout_create(struct wlr_idle *idle, + struct wlr_seat *seat, uint32_t timeout); + +void wlr_idle_timeout_destroy(struct wlr_idle_timeout *timeout); + #endif diff --git a/types/wlr_idle.c b/types/wlr_idle.c index 29367ceb..7ea8cd76 100644 --- a/types/wlr_idle.c +++ b/types/wlr_idle.c @@ -16,22 +16,17 @@ static struct wlr_idle_timeout *idle_timeout_from_resource( return wl_resource_get_user_data(resource); } -static void idle_timeout_destroy(struct wlr_idle_timeout *timer) { - wl_list_remove(&timer->input_listener.link); - wl_list_remove(&timer->seat_destroy.link); - wl_event_source_remove(timer->idle_source); - wl_list_remove(&timer->link); - wl_resource_set_user_data(timer->resource, NULL); - free(timer); -} - static int idle_notify(void *data) { struct wlr_idle_timeout *timer = data; if (timer->idle_state) { return 0; } timer->idle_state = true; - org_kde_kwin_idle_timeout_send_idle(timer->resource); + wlr_signal_emit_safe(&timer->events.idle, timer); + + if (timer->resource) { + org_kde_kwin_idle_timeout_send_idle(timer->resource); + } return 1; } @@ -43,7 +38,11 @@ static void handle_activity(struct wlr_idle_timeout *timer) { // in case the previous state was sleeping send a resume event and switch state if (timer->idle_state) { timer->idle_state = false; - org_kde_kwin_idle_timeout_send_resumed(timer->resource); + wlr_signal_emit_safe(&timer->events.resume, timer); + + if (timer->resource) { + org_kde_kwin_idle_timeout_send_resumed(timer->resource); + } } // rearm the timer @@ -56,14 +55,14 @@ static void handle_activity(struct wlr_idle_timeout *timer) { static void handle_timer_resource_destroy(struct wl_resource *timer_resource) { struct wlr_idle_timeout *timer = idle_timeout_from_resource(timer_resource); if (timer != NULL) { - idle_timeout_destroy(timer); + wlr_idle_timeout_destroy(timer); } } static void handle_seat_destroy(struct wl_listener *listener, void *data) { struct wlr_idle_timeout *timer = wl_container_of(listener, timer, seat_destroy); if (timer != NULL) { - idle_timeout_destroy(timer); + wlr_idle_timeout_destroy(timer); } } @@ -101,34 +100,23 @@ static void handle_input_notification(struct wl_listener *listener, void *data) } } -static void create_idle_timer(struct wl_client *client, - struct wl_resource *idle_resource, uint32_t id, - struct wl_resource *seat_resource, uint32_t timeout) { - struct wlr_idle *idle = idle_from_resource(idle_resource); - struct wlr_seat_client *client_seat = - wlr_seat_client_from_resource(seat_resource); - +static struct wlr_idle_timeout *create_timer(struct wlr_idle *idle, + struct wlr_seat *seat, uint32_t timeout, struct wl_resource *resource) { struct wlr_idle_timeout *timer = calloc(1, sizeof(struct wlr_idle_timeout)); if (!timer) { - wl_resource_post_no_memory(idle_resource); - return; + return NULL; } - timer->seat = client_seat->seat; + + timer->seat = seat; timer->timeout = timeout; timer->idle_state = false; timer->enabled = idle->enabled; - timer->resource = wl_resource_create(client, - &org_kde_kwin_idle_timeout_interface, - wl_resource_get_version(idle_resource), id); - if (timer->resource == NULL) { - free(timer); - wl_resource_post_no_memory(idle_resource); - return; - } - wl_resource_set_implementation(timer->resource, &idle_timeout_impl, timer, - handle_timer_resource_destroy); + wl_list_insert(&idle->idle_timers, &timer->link); + wl_signal_init(&timer->events.idle); + wl_signal_init(&timer->events.resume); + wl_signal_init(&timer->events.destroy); timer->seat_destroy.notify = handle_seat_destroy; wl_signal_add(&timer->seat->events.destroy, &timer->seat_destroy); @@ -142,11 +130,15 @@ static void create_idle_timer(struct wl_client *client, wl_list_remove(&timer->link); wl_list_remove(&timer->input_listener.link); wl_list_remove(&timer->seat_destroy.link); - wl_resource_set_user_data(timer->resource, NULL); free(timer); - wl_resource_post_no_memory(idle_resource); - return; + return NULL; } + + if (resource) { + timer->resource = resource; + wl_resource_set_user_data(resource, timer); + } + if (timer->enabled) { // arm the timer wl_event_source_timer_update(timer->idle_source, timer->timeout); @@ -154,6 +146,30 @@ static void create_idle_timer(struct wl_client *client, idle_notify(timer); } } + + return timer; +} + +static void create_idle_timer(struct wl_client *client, + struct wl_resource *idle_resource, uint32_t id, + struct wl_resource *seat_resource, uint32_t timeout) { + struct wlr_idle *idle = idle_from_resource(idle_resource); + struct wlr_seat_client *client_seat = + wlr_seat_client_from_resource(seat_resource); + + struct wl_resource *resource = wl_resource_create(client, + &org_kde_kwin_idle_timeout_interface, + wl_resource_get_version(idle_resource), id); + if (resource == NULL) { + wl_resource_post_no_memory(idle_resource); + return; + } + wl_resource_set_implementation(resource, &idle_timeout_impl, + NULL, handle_timer_resource_destroy); + + if (!create_timer(idle, client_seat->seat, timeout, resource)) { + wl_resource_post_no_memory(resource); + } } static const struct org_kde_kwin_idle_interface idle_impl = { @@ -202,7 +218,7 @@ void wlr_idle_destroy(struct wlr_idle *idle) { wl_list_remove(&idle->display_destroy.link); struct wlr_idle_timeout *timer, *tmp; wl_list_for_each_safe(timer, tmp, &idle->idle_timers, link) { - idle_timeout_destroy(timer); + wlr_idle_timeout_destroy(timer); } wl_global_destroy(idle->global); free(idle); @@ -234,7 +250,7 @@ struct wlr_idle *wlr_idle_create(struct wl_display *display) { idle->global = wl_global_create(display, &org_kde_kwin_idle_interface, 1, idle, idle_bind); - if (idle->global == NULL){ + if (idle->global == NULL) { wl_list_remove(&idle->display_destroy.link); free(idle); return NULL; @@ -246,3 +262,23 @@ struct wlr_idle *wlr_idle_create(struct wl_display *display) { void wlr_idle_notify_activity(struct wlr_idle *idle, struct wlr_seat *seat) { wlr_signal_emit_safe(&idle->events.activity_notify, seat); } + +struct wlr_idle_timeout *wlr_idle_timeout_create(struct wlr_idle *idle, + struct wlr_seat *seat, uint32_t timeout) { + return create_timer(idle, seat, timeout, NULL); +} + +void wlr_idle_timeout_destroy(struct wlr_idle_timeout *timer) { + wlr_signal_emit_safe(&timer->events.destroy, NULL); + + wl_list_remove(&timer->input_listener.link); + wl_list_remove(&timer->seat_destroy.link); + wl_event_source_remove(timer->idle_source); + wl_list_remove(&timer->link); + + if (timer->resource) { + wl_resource_set_user_data(timer->resource, NULL); + } + + free(timer); +}