[PATCH 3/3] Dim unresponsive windows

Scott Moreau oreaus at gmail.com
Mon Apr 16 10:25:42 PDT 2012


If a client is not responding, lower the brightness and
saturation to indicate it's stalled. The surface is restored
to it's original color values if the client later becomes
responsive.
---
 src/compositor.c |    3 ++
 src/compositor.h |   10 +++++++
 src/shell.c      |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 84 insertions(+), 0 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 3667f39..2b00f6c 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -656,6 +656,9 @@ destroy_surface(struct wl_resource *resource)
 	if (!region_is_undefined(&surface->input))
 		pixman_region32_fini(&surface->input);
 
+	if (surface->unresponsive_animation.exists)
+		wl_list_remove(&surface->unresponsive_animation.current.link);
+
 	free(surface);
 }
 
diff --git a/src/compositor.h b/src/compositor.h
index a9fa69f..6aaa4de 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -336,6 +336,16 @@ struct weston_surface {
 	struct wl_listener buffer_destroy_listener;
 
 	/*
+	 * This is used to indicate a client is currently not responding
+	 */
+	struct {
+		struct weston_animation current;
+		int exists;
+		int fading_in;
+		uint32_t timestamp;
+	} unresponsive_animation;
+
+	/*
 	 * If non-NULL, this function will be called on surface::attach after
 	 * a new buffer has been set up for this surface. The integer params
 	 * are the sx and sy paramerters supplied to surface::attach .
diff --git a/src/shell.c b/src/shell.c
index d8374fa..9e2a108 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -275,6 +275,69 @@ static const struct wl_pointer_grab_interface move_grab_interface = {
 	move_grab_button,
 };
 
+static void
+unresponsive_surface_fade(struct weston_surface *surface, bool reverse)
+{
+	surface->unresponsive_animation.fading_in = reverse ? 0 : 1;
+
+	if(!surface->unresponsive_animation.exists) {
+		wl_list_insert(&surface->compositor->animation_list,
+			       &surface->unresponsive_animation.current.link);
+		surface->unresponsive_animation.exists = 1;
+		surface->unresponsive_animation.timestamp = weston_compositor_get_time();
+		weston_surface_damage(surface);
+	}
+}
+
+static void
+ping_timeout_fade_frame(struct weston_animation *animation,
+		struct weston_output *output, uint32_t msecs)
+{
+	struct weston_surface *surface =
+		container_of(animation, struct weston_surface, unresponsive_animation.current);
+	struct shell_surface *shsurf =
+		container_of(&surface, struct shell_surface, surface);
+	unsigned int step = 32;
+
+	if (!surface || !shsurf)
+		return;
+
+	if (surface->unresponsive_animation.fading_in) {
+		while (step < msecs - surface->unresponsive_animation.timestamp) {
+			if (surface->saturation > 1)
+				surface->saturation -= 5;
+			if (surface->brightness > 200)
+				surface->brightness--;
+
+			surface->unresponsive_animation.timestamp += step;
+		}
+
+		if (surface->saturation <= 1 && surface->brightness <= 200) {
+			wl_list_remove(&surface->unresponsive_animation.current.link);
+			surface->unresponsive_animation.exists = 0;
+		}
+	}
+	else {
+		while (step < msecs - surface->unresponsive_animation.timestamp) {
+			if (surface->saturation < 255)
+				surface->saturation += 5;
+			if (surface->brightness < 255)
+				surface->brightness++;
+
+			surface->unresponsive_animation.timestamp += step;
+		}
+
+		if (surface->saturation >= 255 && surface->brightness >= 255) {
+			surface->saturation = surface->brightness = 255;
+			wl_list_remove(&surface->unresponsive_animation.current.link);
+			surface->unresponsive_animation.exists = 0;
+		}
+	}
+
+	surface->geometry.dirty = 1;
+	weston_surface_damage(surface);
+}
+
 static int
 ping_timeout_handler(void *data)
 {
@@ -303,6 +366,7 @@ ping_timeout_handler(void *data)
 	else {
 		/* Client is not responding */
 		timer->shsurf->is_not_responsive = 1;
+		unresponsive_surface_fade(timer->shsurf->surface, false);
 	}
 
 	return 1;
@@ -345,6 +409,10 @@ shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
 
 	wl_list_for_each(timer, &shsurf->ping_timer_list, link) {
 		if (timer->serial == serial) {
+			if (timer->shsurf->is_not_responsive) {
+				/* Received pong from previously unresponsive client */
+				unresponsive_surface_fade(timer->shsurf->surface, true);
+			}
 			timer->pong_received = 1;
 			timer->shsurf->is_not_responsive = 0;
 		}
@@ -1009,6 +1077,9 @@ shell_get_shell_surface(struct wl_client *client,
 	}
 
 	surface->configure = shell_surface_configure;
+	surface->unresponsive_animation.exists = 0;
+	surface->unresponsive_animation.fading_in = 0;
+	surface->unresponsive_animation.current.frame = ping_timeout_fade_frame;
 
 	shsurf->is_not_responsive = 0;
 
-- 
1.7.4.1



More information about the wayland-devel mailing list