From ff1db4a4f36be3b97f83cacc448b35a1615fe6c0 Mon Sep 17 00:00:00 2001 From: Scott Moreau Date: Tue, 17 Apr 2012 19:06:18 -0600 Subject: [PATCH] Install structuring for ping-pong protocol --- clients/window.c | 8 +++++ src/compositor.c | 16 +++++++++ src/compositor.h | 2 ++ src/shell.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+) diff --git a/clients/window.c b/clients/window.c index a033130d..e79747bb 100644 --- a/clients/window.c +++ b/clients/window.c @@ -1946,6 +1946,13 @@ widget_schedule_resize(struct widget *widget, int32_t width, int32_t height) window_schedule_resize(widget->window, width, height); } +static void +handle_ping(void *data, struct wl_shell_surface *shell_surface, + uint32_t serial) +{ + wl_shell_surface_pong(shell_surface, serial); +} + static void handle_configure(void *data, struct wl_shell_surface *shell_surface, uint32_t edges, int32_t width, int32_t height) @@ -1984,6 +1991,7 @@ handle_popup_done(void *data, struct wl_shell_surface *shell_surface) } static const struct wl_shell_surface_listener shell_surface_listener = { + handle_ping, handle_configure, handle_popup_done }; diff --git a/src/compositor.c b/src/compositor.c index 9b7badf2..4c59da65 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -1557,8 +1557,12 @@ notify_button(struct wl_input_device *device, { struct weston_input_device *wd = (struct weston_input_device *) device; struct weston_compositor *compositor = wd->compositor; + struct weston_surface *focus = (struct weston_surface *) device->pointer_focus; + uint32_t serial = wl_display_next_serial(compositor->wl_display); if (state) { + if (compositor->ping_handler && focus) + compositor->ping_handler(focus, serial); weston_compositor_idle_inhibit(compositor); if (device->button_count == 0) { device->grab_button = button; @@ -1587,6 +1591,11 @@ notify_axis(struct wl_input_device *device, { struct weston_input_device *wd = (struct weston_input_device *) device; struct weston_compositor *compositor = wd->compositor; + struct weston_surface *focus = (struct weston_surface *) device->pointer_focus; + uint32_t serial = wl_display_next_serial(compositor->wl_display); + + if (compositor->ping_handler && focus) + compositor->ping_handler(focus, serial); weston_compositor_activity(compositor); @@ -1640,9 +1649,14 @@ notify_key(struct wl_input_device *device, { struct weston_input_device *wd = (struct weston_input_device *) device; struct weston_compositor *compositor = wd->compositor; + struct weston_surface *focus = (struct weston_surface *) device->pointer_focus; + uint32_t serial = wl_display_next_serial(compositor->wl_display); uint32_t *k, *end; if (state) { + if (compositor->ping_handler && focus) + compositor->ping_handler(focus, serial); + weston_compositor_idle_inhibit(compositor); device->grab_key = key; device->grab_time = time; @@ -2435,6 +2449,8 @@ weston_compositor_init(struct weston_compositor *ec, struct wl_display *display) screenshooter_create(ec); + ec->ping_handler = NULL; + wl_data_device_manager_init(ec->wl_display); glActiveTexture(GL_TEXTURE0); diff --git a/src/compositor.h b/src/compositor.h index a4f5209b..e9c68237 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -234,6 +234,8 @@ struct weston_compositor { void (*destroy)(struct weston_compositor *ec); int (*authenticate)(struct weston_compositor *c, uint32_t id); + void (*ping_handler)(struct weston_surface *surface, uint32_t serial); + struct screenshooter *screenshooter; int launcher_sock; }; diff --git a/src/shell.c b/src/shell.c index b412d8c5..7e58fd56 100644 --- a/src/shell.c +++ b/src/shell.c @@ -95,6 +95,12 @@ enum shell_surface_type { SHELL_SURFACE_POPUP }; +struct ping_timer { + struct wl_event_source *source; + uint32_t pong_received; + uint32_t serial; +}; + struct shell_surface { struct wl_resource resource; @@ -106,6 +112,7 @@ struct shell_surface { enum shell_surface_type type; int32_t saved_x, saved_y; bool saved_position_valid; + int unresponsive; struct { struct weston_transform transform; @@ -128,6 +135,8 @@ struct shell_surface { struct weston_surface *black_surface; } fullscreen; + struct ping_timer *ping_timer; + struct weston_output *fullscreen_output; struct weston_output *output; struct wl_list link; @@ -284,6 +293,69 @@ static const struct wl_pointer_grab_interface move_grab_interface = { move_grab_button, }; +static int +ping_timeout_handler(void *data) +{ + struct shell_surface *shsurf = data; + + if (!shsurf || !shsurf->ping_timer) + return 1; + + if (shsurf->ping_timer->pong_received) { + free(shsurf->ping_timer); + shsurf->ping_timer = NULL; + } else { + /* Client is not responding */ + shsurf->unresponsive = 1; + } + + return 1; +} + +static void +ping_handler(struct weston_surface *surface, uint32_t serial) +{ + struct shell_surface *shsurf; + shsurf = get_shell_surface(surface); + struct wl_event_loop *loop; + int ping_timeout = 15000; + + if (!shsurf) + return; + + if (!shsurf->ping_timer) { + shsurf->ping_timer = malloc(sizeof shsurf->ping_timer); + if (!shsurf->ping_timer) + return; + + shsurf->ping_timer->serial = serial; + shsurf->ping_timer->pong_received = 0; + loop = wl_display_get_event_loop(surface->compositor->wl_display); + shsurf->ping_timer->source = + wl_event_loop_add_timer(loop, ping_timeout_handler, shsurf); + wl_event_source_timer_update(shsurf->ping_timer->source, ping_timeout); + + wl_shell_surface_send_ping(&shsurf->resource, serial); + } +} + +static void +shell_surface_pong(struct wl_client *client, struct wl_resource *resource, + uint32_t serial) +{ + struct shell_surface *shsurf = resource->data; + + if (!shsurf || !shsurf->ping_timer) + return; + + if (shsurf->ping_timer->serial == serial) { + shsurf->ping_timer->pong_received = 1; + shsurf->unresponsive = 0; + free(shsurf->ping_timer); + shsurf->ping_timer = NULL; + } +} + static int weston_surface_move(struct weston_surface *es, struct weston_input_device *wd) @@ -876,6 +948,7 @@ shell_surface_set_popup(struct wl_client *client, } static const struct wl_shell_surface_interface shell_surface_implementation = { + shell_surface_pong, shell_surface_move, shell_surface_resize, shell_surface_set_toplevel, @@ -907,6 +980,8 @@ destroy_shell_surface(struct wl_resource *resource) */ wl_list_remove(&shsurf->surface_destroy_listener.link); shsurf->surface->configure = NULL; + if (shsurf->ping_timer) + free(shsurf->ping_timer); wl_list_remove(&shsurf->link); free(shsurf); @@ -970,6 +1045,8 @@ shell_get_shell_surface(struct wl_client *client, surface->configure = shell_surface_configure; + shsurf->unresponsive = 0; + shsurf->resource.destroy = destroy_shell_surface; shsurf->resource.object.id = id; shsurf->resource.object.interface = &wl_shell_surface_interface; @@ -983,6 +1060,7 @@ shell_get_shell_surface(struct wl_client *client, shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT; shsurf->fullscreen.framerate = 0; shsurf->fullscreen.black_surface = NULL; + shsurf->ping_timer = NULL; wl_list_init(&shsurf->fullscreen.transform.link); shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy; @@ -2225,12 +2303,22 @@ debug_repaint_binding(struct wl_input_device *device, uint32_t time, static void shell_destroy(struct wl_listener *listener, void *data) { + struct weston_surface *surface; + struct shell_surface *shsurf; struct desktop_shell *shell = container_of(listener, struct desktop_shell, destroy_listener); if (shell->child.client) wl_client_destroy(shell->child.client); + wl_list_for_each(surface, &shell->compositor->surface_list, link) { + shsurf = get_shell_surface(surface); + if (!shsurf) + continue; + if (shsurf->ping_timer) + free(shsurf->ping_timer); + } + free(shell->screensaver.path); free(shell); } @@ -2256,6 +2344,7 @@ shell_init(struct weston_compositor *ec) wl_signal_add(&ec->lock_signal, &shell->lock_listener); shell->unlock_listener.notify = unlock; wl_signal_add(&ec->unlock_signal, &shell->unlock_listener); + ec->ping_handler = ping_handler; wl_list_init(&shell->backgrounds); wl_list_init(&shell->panels);