[RFC] protocol: add screensaver interface

Pekka Paalanen ppaalanen at gmail.com
Tue Nov 22 05:09:19 PST 2011


Add the screensaver interface to the desktop-shell protocol file. Also
add stubs for it in the compositor, and make wscreensaver to bind to the
screensaver interface. Wscreensaver gets a new option --demo to retain
the current behaviour as a regular wayland client.

When a screensaver application starts, it should bind to the screensaver
interface, enumerate all outputs, create a surface per output, and
register those surfaces via screensaver::set_surface request. Then it
continues with the usual animation loop, waiting for frame events. The
compositor will decide, when the given screensaver surfaces are
displayed. A screensaver application should respond to outputs coming
and going away by creating and destroying surfaces.

The compositor is supposed to activate a screensaver by exec'ing it, and
stop the screensaver by killing the client process. Only one client may
be bound to the screensaver interface at a time. If there already is a
client, the compositor could either kill it first, or not exec a new
one.

Signed-off-by: Pekka Paalanen <ppaalanen at gmail.com>
---
 clients/Makefile.am        |    7 +++++-
 clients/wscreensaver.c     |   42 +++++++++++++++++++++++++++++++--
 compositor/shell.c         |   54 ++++++++++++++++++++++++++++++++++++++++++++
 protocol/desktop-shell.xml |   13 ++++++++++
 4 files changed, 112 insertions(+), 4 deletions(-)

diff --git a/clients/Makefile.am b/clients/Makefile.am
index 1f7125f..25385b7 100644
--- a/clients/Makefile.am
+++ b/clients/Makefile.am
@@ -70,7 +70,12 @@ smoke_LDADD = $(toolkit_libs)
 resizor_SOURCES = resizor.c
 resizor_LDADD = $(toolkit_libs)
 
-wscreensaver_SOURCES = wscreensaver.c wscreensaver-glue.c glmatrix.c
+wscreensaver_SOURCES =				\
+	wscreensaver.c				\
+	desktop-shell-client-protocol.h		\
+	desktop-shell-protocol.c		\
+	wscreensaver-glue.c			\
+	glmatrix.c
 wscreensaver_LDADD = $(toolkit_libs) -lGLU
 
 eventdemo_SOURCES = eventdemo.c
diff --git a/clients/wscreensaver.c b/clients/wscreensaver.c
index 6070c5d..15c9a34 100644
--- a/clients/wscreensaver.c
+++ b/clients/wscreensaver.c
@@ -20,7 +20,7 @@
  * OF THIS SOFTWARE.
  */
 
-#include "config.h"
+#include "../config.h"
 
 #include "wscreensaver.h"
 
@@ -32,8 +32,10 @@
 #include <GL/gl.h>
 #include <EGL/eglext.h>
 
+#include <wayland-client.h>
+
 #include "wayland-util.h"
-#include "wayland-client.h"
+#include "desktop-shell-client-protocol.h"
 
 #include "window.h"
 
@@ -46,7 +48,11 @@ static const struct wscreensaver_plugin * const plugins[] = {
 
 const char *progname = NULL;
 
+static int demo_mode;
+
 struct wscreensaver {
+	struct screensaver *screensaver;
+
 	struct display *display;
 
 	/* per output, if fullscreen mode */
@@ -247,6 +253,24 @@ init_wscreensaver(struct wscreensaver *wscr, struct display *display)
 	return NULL;
 }
 
+static void
+global_handler(struct wl_display *display, uint32_t id,
+	       const char *interface, uint32_t version, void *data)
+{
+	struct wscreensaver *wscr = data;
+
+	if (!strcmp(interface, "screensaver")) {
+		wscr->screensaver =
+			wl_display_bind(display, id, &screensaver_interface);
+	}
+}
+
+static const GOptionEntry option_entries[] = {
+	{ "demo", 0, 0, G_OPTION_ARG_NONE, &demo_mode,
+		"Run as a regular application, not a screensaver.", NULL },
+	{ NULL }
+};
+
 int main(int argc, char *argv[])
 {
 	struct display *d;
@@ -255,12 +279,24 @@ int main(int argc, char *argv[])
 
 	init_frand();
 
-	d = display_create(&argc, &argv, NULL);
+	d = display_create(&argc, &argv, option_entries);
 	if (d == NULL) {
 		fprintf(stderr, "failed to create display: %m\n");
 		return EXIT_FAILURE;
 	}
 
+	if (!demo_mode) {
+		wl_display_add_global_listener(display_get_display(d),
+					       global_handler, &wscr);
+		wl_display_roundtrip(display_get_display(d));
+		if (!wscr.screensaver) {
+			fprintf(stderr,
+				"Server did not offer screensaver interface,"
+				" exiting.\n");
+			return EXIT_FAILURE;
+		}
+	}
+
 	msg = init_wscreensaver(&wscr, d);
 	if (msg) {
 		fprintf(stderr, "wscreensaver init failed: %s\n", msg);
diff --git a/compositor/shell.c b/compositor/shell.c
index f8305db..c6e5a4d 100644
--- a/compositor/shell.c
+++ b/compositor/shell.c
@@ -56,6 +56,8 @@ struct wl_shell {
 	struct wlsc_surface *lock_surface;
 	struct wl_listener lock_surface_listener;
 	struct wl_list hidden_surface_list;
+
+	struct wl_resource *screensaver;
 };
 
 struct wlsc_move_grab {
@@ -1215,6 +1217,54 @@ bind_desktop_shell(struct wl_client *client,
 	wl_resource_destroy(resource, 0);
 }
 
+static void
+screensaver_set_surface(struct wl_client *client,
+			struct wl_resource *resource,
+			struct wl_resource *surface_resource,
+			struct wl_resource *output_resource)
+{
+	struct wl_shell *shell = resource->data;
+	struct wlsc_surface *surface = surface_resource->data;
+	struct wlsc_output *output = output_resource->data;
+
+	/* TODO */
+}
+
+static const struct screensaver_interface screensaver_implementation = {
+	screensaver_set_surface
+};
+
+static void
+unbind_screensaver(struct wl_resource *resource)
+{
+	struct wl_shell *shell = resource->data;
+
+	shell->screensaver = NULL;
+	free(resource);
+}
+
+static void
+bind_screensaver(struct wl_client *client,
+		 void *data, uint32_t version, uint32_t id)
+{
+	struct wl_shell *shell = data;
+	struct wl_resource *resource;
+
+	resource = wl_client_add_object(client, &screensaver_interface,
+					&screensaver_implementation,
+					id, shell);
+
+	if (shell->screensaver == NULL) {
+		resource->destroy = unbind_screensaver;
+		shell->screensaver = resource;
+		return;
+	}
+
+	wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+			       "screensaver already bound");
+	wl_resource_destroy(resource, 0);
+}
+
 int
 shell_init(struct wlsc_compositor *ec);
 
@@ -1247,6 +1297,10 @@ shell_init(struct wlsc_compositor *ec)
 				  shell, bind_desktop_shell) == NULL)
 		return -1;
 
+	if (wl_display_add_global(ec->wl_display, &screensaver_interface,
+				  shell, bind_screensaver) == NULL)
+		return -1;
+
 	if (launch_desktop_shell_process(shell) != 0)
 		return -1;
 
diff --git a/protocol/desktop-shell.xml b/protocol/desktop-shell.xml
index d099925..4c39d44 100644
--- a/protocol/desktop-shell.xml
+++ b/protocol/desktop-shell.xml
@@ -33,4 +33,17 @@
     <event name="prepare_lock_surface"/>
   </interface>
 
+  <!-- Only one client can bind this interface at a time. -->
+  <interface name="screensaver" version="1">
+
+    <!-- Set the surface type as a screensaver for a particular output.
+         A screensaver surface is normally hidden, and only visible after
+         a idle timeout. -->
+    <request name="set_surface">
+      <arg name="surface" type="object" interface="wl_surface"/>
+      <arg name="output" type="object" interface="wl_output"/>
+    </request>
+
+  </interface>
+
 </protocol>
-- 
1.7.3.4



More information about the wayland-devel mailing list