From e10a5d9feadb01aee427842e0b4f1774e5ab33c0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 22 Apr 2011 14:01:18 -0400 Subject: [PATCH] compositor: Implement a simple screensaver feature We'll need protocol for screensaver inhibit requests. --- compositor/compositor.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++- compositor/compositor.h | 17 ++++++++ 2 files changed, 115 insertions(+), 2 deletions(-) diff --git a/compositor/compositor.c b/compositor/compositor.c index 8dbf4c1..5fd2d70 100644 --- a/compositor/compositor.c +++ b/compositor/compositor.c @@ -42,6 +42,7 @@ static const char *option_socket_name = NULL; static const char *option_background = "background.jpg"; static const char *option_geometry = "1024x640"; +static int option_idle_time = 5; static int option_connector = 0; static const GOptionEntry option_entries[] = { @@ -53,6 +54,8 @@ static const GOptionEntry option_entries[] = { &option_geometry, "Geometry" }, { "socket", 's', 0, G_OPTION_ARG_STRING, &option_socket_name, "Socket Name" }, + { "idle-time", 'i', 0, G_OPTION_ARG_INT, + &option_idle_time, "Screensaver idle time" }, { NULL } }; @@ -553,6 +556,15 @@ wlsc_surface_update_matrix(struct wlsc_surface *es) } void +wlsc_compositor_damage_all(struct wlsc_compositor *compositor) +{ + struct wlsc_output *output; + + wl_list_for_each(output, &compositor->output_list, link) + wlsc_output_damage(output); +} + +void wlsc_output_finish_frame(struct wlsc_output *output, int msecs) { struct wlsc_compositor *compositor = output->compositor; @@ -571,6 +583,18 @@ wlsc_output_finish_frame(struct wlsc_output *output, int msecs) compositor->repaint_on_timeout = 1; } +void +wlsc_output_damage(struct wlsc_output *output) +{ + struct wlsc_compositor *compositor = output->compositor; + + pixman_region32_union_rect(&compositor->damage_region, + &compositor->damage_region, + output->x, output->y, + output->width, output->height); + wlsc_compositor_schedule_repaint(compositor); +} + static void wlsc_output_repaint(struct wlsc_output *output) { @@ -599,6 +623,11 @@ wlsc_output_repaint(struct wlsc_output *output) &output->previous_damage_region); pixman_region32_copy(&output->previous_damage_region, &new_damage); + if (ec->state == WLSC_COMPOSITOR_SLEEPING) { + glClear(GL_COLOR_BUFFER_BIT); + return; + } + if (ec->focus) if (output->set_hardware_cursor(output, ec->input_device) < 0) using_hardware_cursor = 0; @@ -704,6 +733,9 @@ wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor) { struct wlsc_output *output; + if (compositor->state == WLSC_COMPOSITOR_SLEEPING) + return; + wl_list_for_each(output, &compositor->output_list, link) output->repaint_needed = 1; @@ -1031,6 +1063,49 @@ static const struct wl_grab_interface motion_grab_interface = { }; void +wlsc_compositor_wake(struct wlsc_compositor *compositor) +{ + if (compositor->idle_inhibit) + return; + + if (compositor->state == WLSC_COMPOSITOR_SLEEPING) { + compositor->state = WLSC_COMPOSITOR_ACTIVE; + wlsc_compositor_damage_all(compositor); + } + + wl_event_source_timer_update(compositor->idle_source, + option_idle_time * 1000); +} + +static void +wlsc_compositor_idle_inhibit(struct wlsc_compositor *compositor) +{ + wlsc_compositor_wake(compositor); + compositor->idle_inhibit++; +} + +static void +wlsc_compositor_idle_release(struct wlsc_compositor *compositor) +{ + compositor->idle_inhibit--; + wlsc_compositor_wake(compositor); +} + +static int +idle_handler(void *data) +{ + struct wlsc_compositor *compositor = data; + + if (compositor->idle_inhibit) + return 1; + + wlsc_compositor_damage_all(compositor); + compositor->state = WLSC_COMPOSITOR_SLEEPING; + + return 1; +} + +void notify_motion(struct wl_input_device *device, uint32_t time, int x, int y) { struct wlsc_surface *es; @@ -1043,6 +1118,8 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y) int x_valid = 0, y_valid = 0; int min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN; + wlsc_compositor_wake(ec); + wl_list_for_each(output, &ec->output_list, link) { if (output->x <= x && x <= output->x + output->width) x_valid = 1; @@ -1136,6 +1213,11 @@ notify_button(struct wl_input_device *device, struct wlsc_surface *surface = (struct wlsc_surface *) device->pointer_focus; + if (state) + wlsc_compositor_idle_inhibit(compositor); + else + wlsc_compositor_idle_release(compositor); + if (state && surface && device->grab == NULL) { wlsc_surface_activate(surface, wd, time); wl_input_device_start_grab(device, @@ -1166,7 +1248,8 @@ terminate_binding(struct wl_input_device *device, uint32_t time, { struct wlsc_compositor *compositor = data; - wl_display_terminate(compositor->wl_display); + if (state) + wl_display_terminate(compositor->wl_display); } struct wlsc_binding * @@ -1240,9 +1323,14 @@ notify_key(struct wl_input_device *device, uint32_t *k, *end; struct wlsc_binding *b; + if (state) + wlsc_compositor_idle_inhibit(compositor); + else + wlsc_compositor_idle_release(compositor); + wl_list_for_each(b, &compositor->binding_list, link) { if (b->key == key && - b->modifier == wd->modifier_state && state) { + b->modifier == wd->modifier_state) { b->handler(&wd->input_device, time, key, 0, state, b->data); break; @@ -1323,12 +1411,17 @@ notify_keyboard_focus(struct wl_input_device *device, wd->modifier_state = 0; end = device->keys.data + device->keys.size; for (k = device->keys.data; k < end; k++) { + wlsc_compositor_idle_inhibit(compositor); update_modifier_state(wd, *k, 1); } wl_input_device_set_keyboard_focus(&wd->input_device, &es->surface, time); } else { + end = device->keys.data + device->keys.size; + for (k = device->keys.data; k < end; k++) + wlsc_compositor_idle_release(compositor); + wd->modifier_state = 0; wl_input_device_set_keyboard_focus(&wd->input_device, NULL, time); @@ -1631,6 +1724,9 @@ wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display) return -1; loop = wl_display_get_event_loop(ec->wl_display); + ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec); + wl_event_source_timer_update(ec->idle_source, option_idle_time * 1000); + ec->timer_source = wl_event_loop_add_timer(loop, repaint, ec); pixman_region32_init(&ec->damage_region); wlsc_compositor_schedule_repaint(ec); diff --git a/compositor/compositor.h b/compositor/compositor.h index 6a7c0be..b8a19b2 100644 --- a/compositor/compositor.h +++ b/compositor/compositor.h @@ -90,6 +90,11 @@ struct wlsc_sprite { int height; }; +enum { + WLSC_COMPOSITOR_ACTIVE, + WLSC_COMPOSITOR_SLEEPING +}; + struct wlsc_compositor { struct wl_compositor compositor; @@ -114,6 +119,10 @@ struct wlsc_compositor { struct wl_list surface_list; struct wl_list binding_list; + uint32_t state; + struct wl_event_source *idle_source; + uint32_t idle_inhibit; + /* Repaint state. */ struct wl_event_source *timer_source; int repaint_on_timeout; @@ -200,7 +209,15 @@ notify_keyboard_focus(struct wl_input_device *device, void wlsc_output_finish_frame(struct wlsc_output *output, int msecs); void +wlsc_output_damage(struct wlsc_output *output); +void wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor); +void +wlsc_compositor_damage_all(struct wlsc_compositor *compositor); +void +wlsc_compositor_unlock(struct wlsc_compositor *compositor); +void +wlsc_compositor_wake(struct wlsc_compositor *compositor); struct wlsc_binding; typedef void (*wlsc_binding_handler_t)(struct wl_input_device *device, -- 2.7.4