idle: enable the compositors to add custom idle timeouts (#1655)

* idle: enable the compositors to add custom idle timeouts

* idle: add a private constructor which also creates the resource

* idle: move resource creation to the idle implementation callback
This commit is contained in:
Ilia Bozhinov 2019-04-17 07:48:43 +02:00 committed by Simon Ser
parent dc5d1d08ef
commit d6615e0e84
2 changed files with 91 additions and 38 deletions

View file

@ -46,6 +46,12 @@ struct wlr_idle_timeout {
bool enabled; bool enabled;
uint32_t timeout; // milliseconds 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 input_listener;
struct wl_listener seat_destroy; 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, void wlr_idle_set_enabled(struct wlr_idle *idle, struct wlr_seat *seat,
bool enabled); 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 #endif

View file

@ -16,22 +16,17 @@ static struct wlr_idle_timeout *idle_timeout_from_resource(
return wl_resource_get_user_data(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) { static int idle_notify(void *data) {
struct wlr_idle_timeout *timer = data; struct wlr_idle_timeout *timer = data;
if (timer->idle_state) { if (timer->idle_state) {
return 0; return 0;
} }
timer->idle_state = true; timer->idle_state = true;
wlr_signal_emit_safe(&timer->events.idle, timer);
if (timer->resource) {
org_kde_kwin_idle_timeout_send_idle(timer->resource); org_kde_kwin_idle_timeout_send_idle(timer->resource);
}
return 1; return 1;
} }
@ -43,8 +38,12 @@ static void handle_activity(struct wlr_idle_timeout *timer) {
// in case the previous state was sleeping send a resume event and switch state // in case the previous state was sleeping send a resume event and switch state
if (timer->idle_state) { if (timer->idle_state) {
timer->idle_state = false; timer->idle_state = false;
wlr_signal_emit_safe(&timer->events.resume, timer);
if (timer->resource) {
org_kde_kwin_idle_timeout_send_resumed(timer->resource); org_kde_kwin_idle_timeout_send_resumed(timer->resource);
} }
}
// rearm the timer // rearm the timer
wl_event_source_timer_update(timer->idle_source, timer->timeout); wl_event_source_timer_update(timer->idle_source, timer->timeout);
@ -56,14 +55,14 @@ static void handle_activity(struct wlr_idle_timeout *timer) {
static void handle_timer_resource_destroy(struct wl_resource *timer_resource) { static void handle_timer_resource_destroy(struct wl_resource *timer_resource) {
struct wlr_idle_timeout *timer = idle_timeout_from_resource(timer_resource); struct wlr_idle_timeout *timer = idle_timeout_from_resource(timer_resource);
if (timer != NULL) { if (timer != NULL) {
idle_timeout_destroy(timer); wlr_idle_timeout_destroy(timer);
} }
} }
static void handle_seat_destroy(struct wl_listener *listener, void *data) { static void handle_seat_destroy(struct wl_listener *listener, void *data) {
struct wlr_idle_timeout *timer = wl_container_of(listener, timer, seat_destroy); struct wlr_idle_timeout *timer = wl_container_of(listener, timer, seat_destroy);
if (timer != NULL) { 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, static struct wlr_idle_timeout *create_timer(struct wlr_idle *idle,
struct wl_resource *idle_resource, uint32_t id, struct wlr_seat *seat, uint32_t timeout, struct wl_resource *resource) {
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 wlr_idle_timeout *timer = struct wlr_idle_timeout *timer =
calloc(1, sizeof(struct wlr_idle_timeout)); calloc(1, sizeof(struct wlr_idle_timeout));
if (!timer) { if (!timer) {
wl_resource_post_no_memory(idle_resource); return NULL;
return;
} }
timer->seat = client_seat->seat;
timer->seat = seat;
timer->timeout = timeout; timer->timeout = timeout;
timer->idle_state = false; timer->idle_state = false;
timer->enabled = idle->enabled; 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_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; timer->seat_destroy.notify = handle_seat_destroy;
wl_signal_add(&timer->seat->events.destroy, &timer->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->link);
wl_list_remove(&timer->input_listener.link); wl_list_remove(&timer->input_listener.link);
wl_list_remove(&timer->seat_destroy.link); wl_list_remove(&timer->seat_destroy.link);
wl_resource_set_user_data(timer->resource, NULL);
free(timer); free(timer);
wl_resource_post_no_memory(idle_resource); return NULL;
return;
} }
if (resource) {
timer->resource = resource;
wl_resource_set_user_data(resource, timer);
}
if (timer->enabled) { if (timer->enabled) {
// arm the timer // arm the timer
wl_event_source_timer_update(timer->idle_source, timer->timeout); 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); 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 = { 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); wl_list_remove(&idle->display_destroy.link);
struct wlr_idle_timeout *timer, *tmp; struct wlr_idle_timeout *timer, *tmp;
wl_list_for_each_safe(timer, tmp, &idle->idle_timers, link) { 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); wl_global_destroy(idle->global);
free(idle); free(idle);
@ -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) { void wlr_idle_notify_activity(struct wlr_idle *idle, struct wlr_seat *seat) {
wlr_signal_emit_safe(&idle->events.activity_notify, 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);
}