[RFC PATCH 06/12] tablet-shell: Applications can run on tablet

Tiago Vignatti tiago.vignatti at linux.intel.com
Mon Aug 6 01:35:53 PDT 2012


Hi Juan,

There's an intentional separation of the wl_shell_surface_interface on 
its own (desktop) shell file. Its purpose is for building full desktop 
interfaces, in principle, and in fact things like _move, _resize, 
_set_title and etc don't make sense on tablet style of interface. So 
what you're suggesting here doesn't make sense either when a client 
would be replying to a fullscreen event, because what we want is to all 
tablet clients be fullscreen. We need is just a way to configure the 
clients always like that and I believe this code is already in place on 
tablet-shell.c.

Another tip, try to work a bit more on the commit messages and its 
subject line:

http://vignatti.wordpress.com/2010/07/12/attracting-reviewers-in-your-patch-series/

Tiago


On 08/03/2012 02:21 PM, juan.j.zhao at linux.intel.com wrote:
> From: Juan Zhao <juan.j.zhao at intel.com>
>
> Add a event in tablet-client. When a client is connected to server, the
> set_fullscreen event would be sent. and client will call shell_surface's
> set_fullscreen method to be fullscreen.
>
> Client application like dnd clickdot can run on tablet-shell.
> listener is added in window.c and that can be moved to application side.
> And simple-egl is still not sure how to resize the egl surface, so this
> version can't run fullscreen.
>
> Signed-off-by: Tang Ning <tecton69 at gmail.com>
> ---
>   clients/Makefile.am       |   9 +-
>   clients/window.c          |  23 +++
>   protocol/tablet-shell.xml |   2 +
>   src/tablet-shell.c        | 383 ++++++++++++++++++++++++++++++++++++++++++++++
>   4 files changed, 415 insertions(+), 2 deletions(-)
>
> diff --git a/clients/Makefile.am b/clients/Makefile.am
> index 133eaca..a1cb865 100644
> --- a/clients/Makefile.am
> +++ b/clients/Makefile.am
> @@ -24,7 +24,10 @@ simple_clients_programs =			\
>   	simple-shm				\
>   	simple-touch
>
> -simple_egl_SOURCES = simple-egl.c
> +simple_egl_SOURCES =				\
> +	simple-egl.c				\
> +	tablet-shell-client-protocol.h		\
> +	tablet-shell-protocol.c
>   simple_egl_CPPFLAGS = $(SIMPLE_CLIENT_CFLAGS)
>   simple_egl_LDADD = $(SIMPLE_CLIENT_LIBS) -lm
>
> @@ -66,7 +69,9 @@ libtoytoolkit_a_SOURCES =			\
>   	window.c				\
>   	window.h				\
>   	text-cursor-position-protocol.c		\
> -	text-cursor-position-client-protocol.h
> +	text-cursor-position-client-protocol.h	\
> +	tablet-shell-client-protocol.h		\
> +	tablet-shell-protocol.c
>
>   toolkit_libs =						\
>   	libtoytoolkit.a					\
> diff --git a/clients/window.c b/clients/window.c
> index d0b7a7d..18447d5 100644
> --- a/clients/window.c
> +++ b/clients/window.c
> @@ -63,6 +63,7 @@
>   #include "../shared/cairo-util.h"
>   #include "text-cursor-position-client-protocol.h"
>   #include "../shared/os-compatibility.h"
> +#include "tablet-shell-client-protocol.h"
>
>   #include "window.h"
>
> @@ -74,6 +75,7 @@ struct display {
>   	struct wl_shell *shell;
>   	struct wl_shm *shm;
>   	struct wl_data_device_manager *data_device_manager;
> +	struct tablet_client *tablet_client;
>   	struct text_cursor_position *text_cursor_position;
>   	EGLDisplay dpy;
>   	EGLConfig argb_config;
> @@ -3247,6 +3249,22 @@ static const struct wl_output_listener output_listener = {
>   };
>
>   static void
> +tablet_client_handle_set_fullscreen(void *data,
> +				    struct tablet_client *tablet_client)
> +{
> +	struct display *display = data;
> +	struct window *window;
> +	wl_list_for_each (window, &display->window_list, link) {
> +		if (window->fullscreen_handler)
> +			window->fullscreen_handler(window, window->user_data);
> +	}
> +}
> +
> +static const struct tablet_client_listener tablet_client_listener = {
> +	tablet_client_handle_set_fullscreen
> +};
> +
> +static void
>   display_add_output(struct display *d, uint32_t id)
>   {
>   	struct output *output;
> @@ -3411,6 +3429,11 @@ display_handle_global(struct wl_display *display, uint32_t id,
>   		d->text_cursor_position =
>   			wl_display_bind(display, id,
>   					&text_cursor_position_interface);
> +	} else if (strcmp(interface, "tablet_client") == 0) {
> +		d->tablet_client =
> +			wl_display_bind(display, id, &tablet_client_interface);
> +		tablet_client_add_listener(d->tablet_client,
> +				&tablet_client_listener, d);
>   	}
>   }
>
> diff --git a/protocol/tablet-shell.xml b/protocol/tablet-shell.xml
> index 10f1756..430f346 100644
> --- a/protocol/tablet-shell.xml
> +++ b/protocol/tablet-shell.xml
> @@ -35,6 +35,8 @@
>     <interface name="tablet_client" version="1">
>       <request name="destroy" type="destructor"/>
>       <request name="activate"/>
> +
> +    <event name="set_fullscreen" />
>     </interface>
>
>   </protocol>
> diff --git a/src/tablet-shell.c b/src/tablet-shell.c
> index f17d888..b2db2b7 100644
> --- a/src/tablet-shell.c
> +++ b/src/tablet-shell.c
> @@ -45,6 +45,7 @@ enum {
>
>   struct tablet_shell {
>   	struct wl_resource resource;
> +	struct wl_resource client_resource;
>
>   	struct wl_listener lock_listener;
>   	struct wl_listener unlock_listener;
> @@ -75,6 +76,36 @@ struct tablet_shell {
>   	struct wl_event_source *long_press_source;
>   };
>
> +struct ping_timer {
> +	struct wl_event_source *source;
> +	uint32_t serial;
> +};
> +
> +struct shell_surface {
> +	struct wl_resource resource;
> +
> +	struct weston_surface *surface;
> +	struct weston_surface *parent_surface;
> +	struct wl_listener surface_destroy_listener;
> +	struct tablet_shell *shell;
> +
> +	char *path, *class;
> +	char *title;
> +	int unresponsive;
> +	struct ping_timer *ping_timer;
> +	struct weston_output *output;
> +	struct wl_list link;
> +
> +	int is_fullscreen;
> +	struct {
> +		enum wl_shell_surface_fullscreen_method type;
> +		struct weston_transform transform;
> +		uint32_t framerate;
> +	} fullscreen;
> +
> +	const struct weston_shell_client *client;
> +};
> +
>   struct tablet_client {
>   	struct wl_resource resource;
>   	struct tablet_shell *shell;
> @@ -84,6 +115,283 @@ struct tablet_client {
>   };
>
>   static void
> +tablet_shell_surface_configure(struct weston_surface *surface,
> +			       int32_t sx, int32_t sy);
> +
> +static void
> +shell_surface_configure(struct weston_surface *surface,
> +			int32_t sx, int32_t sy);
> +
> +static struct shell_surface *
> +get_shell_surface(struct weston_surface *surface)
> +{
> +	if (surface->configure == shell_surface_configure)
> +		return surface->private;
> +	else
> +		return NULL;
> +}
> +
> +static void
> +ping_timer_destroy(struct shell_surface *shsurf)
> +{
> +	if (!shsurf || !shsurf->ping_timer)
> +		return;
> +
> +	if (shsurf->ping_timer->source)
> +		wl_event_source_remove(shsurf->ping_timer->source);
> +
> +	free(shsurf->ping_timer);
> +	shsurf->ping_timer = NULL;
> +}
> +static void
> +shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
> +		uint32_t serial)
> +{
> +	struct shell_surface *shsurf = resource->data;
> +	int was_unresponsive;
> +
> +	if (shsurf->ping_timer->serial == serial) {
> +		was_unresponsive = shsurf->unresponsive;
> +		shsurf->unresponsive = 0;
> +		if (was_unresponsive) {
> +			// Received pong from previous...
> +		}
> +		ping_timer_destroy(shsurf);
> +	}
> +}
> +
> +static void
> +shell_surface_set_title(struct wl_client *client,
> +			struct wl_resource *resource, const char *title)
> +{
> +	return;
> +}
> +static void
> +shell_surface_set_class(struct wl_client *client,
> +			struct wl_resource *resource, const char *class)
> +{
> +	return;
> +}
> +
> +static void
> +shell_surface_move(struct wl_client *client, struct wl_resource *resource,
> +			struct wl_resource *seat_resource, uint32_t serial)
> +{
> +	return;
> +}
> +static void
> +shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
> +			struct wl_resource *seat_resource, uint32_t serial,
> +			uint32_t edges)
> +{
> +	return;
> +}
> +
> +static void
> +shell_surface_set_toplevel(struct wl_client *client,
> +			struct wl_resource *resource)
> +{
> +	return;
> +}
> +
> +static void
> +shell_surface_set_transient(struct wl_client *client,
> +			struct wl_resource *resource,
> +			struct wl_resource *parent_resource,
> +			int x, int y, uint32_t flags)
> +{
> +	return;
> +}
> +static void
> +shell_surface_set_fullscreen(struct wl_client *client,
> +			struct wl_resource *resource,
> +			uint32_t method,
> +			uint32_t framerate,
> +			struct wl_resource *output_resource)
> +{
> +	struct shell_surface *shsurf = resource->data;
> +	struct weston_surface *es = shsurf->surface;
> +
> +	if (output_resource)
> +		shsurf->output = output_resource->data;
> +	else
> +		shsurf->output = container_of(es->compositor->output_list.next,
> +			    struct weston_output, link);
> +
> +	shsurf->client->send_configure(shsurf->surface, 0,
> +				       shsurf->output->current->width,
> +				       shsurf->output->current->height);
> +}
> +
> +static void
> +shell_surface_set_popup(struct wl_client *client,
> +			struct wl_resource *resource,
> +			struct wl_resource *seat_resource,
> +			uint32_t serial,
> +			struct wl_resource *parent_resource,
> +			int32_t x, int32_t y, uint32_t flags)
> +{
> +	return;
> +}
> +
> +static void
> +shell_surface_set_maximized(struct wl_client *client,
> +			struct wl_resource *resource,
> +			struct wl_resource *output_resource)
> +{
> +	return;
> +}
> +static const struct wl_shell_surface_interface shell_surface_implementation = {
> +	shell_surface_pong,
> +	shell_surface_move,
> +	shell_surface_resize,
> +	shell_surface_set_toplevel,
> +	shell_surface_set_transient,
> +	shell_surface_set_fullscreen,
> +	shell_surface_set_popup,
> +	shell_surface_set_maximized,
> +	shell_surface_set_title,
> +	shell_surface_set_class
> +};
> +
> +static void
> +destroy_shell_surface(struct shell_surface *shsurf)
> +{
> +	wl_list_remove(&shsurf->surface_destroy_listener.link);
> +	shsurf->surface->configure = NULL;
> +	ping_timer_destroy(shsurf);
> +
> +	wl_list_remove(&shsurf->link);
> +	free(shsurf);
> +	weston_log("shell surface destroyed\n");
> +}
> +
> +static void
> +shell_destroy_shell_surface(struct wl_resource *resource)
> +{
> +	struct shell_surface *shsurf = resource->data;
> +	destroy_shell_surface(shsurf);
> +}
> +
> +static void
> +shell_handle_surface_destroy(struct wl_listener *listener, void *data)
> +{
> +	struct shell_surface *shsurf =
> +		container_of(listener, struct shell_surface,
> +			     surface_destroy_listener);
> +	if (shsurf->resource.client) {
> +		wl_resource_destroy(&shsurf->resource);
> +	} else {
> +		wl_signal_emit(&shsurf->resource.destroy_signal,
> +				&shsurf->resource);
> +		destroy_shell_surface(shsurf);
> +	}
> +}
> +
> +static struct shell_surface *
> +create_shell_surface(void *shell, struct weston_surface *surface,
> +			const struct weston_shell_client *client)
> +{
> +	struct shell_surface *shsurf;
> +
> +	if (surface->configure) {
> +		weston_log("surface->configure already set\n");
> +		return NULL;
> +	}
> +
> +	shsurf = calloc(1, sizeof *shsurf);
> +		if (!shsurf) {
> +		weston_log("no memory to allocate shell surface\n");
> +		return NULL;
> +	}
> +
> +	surface->configure = shell_surface_configure;
> +	surface->private = shsurf;
> +	surface->compositor->shell_interface.shell = shell;
> +
> +	shsurf->shell = (struct tablet_shell *) shell;
> +	shsurf->unresponsive = 0;
> +	shsurf->surface = surface;
> +	shsurf->ping_timer = NULL;
> +
> +	wl_signal_init(&shsurf->resource.destroy_signal);
> +	shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
> +	wl_signal_add(&surface->surface.resource.destroy_signal,
> +		      &shsurf->surface_destroy_listener);
> +
> +	/* init link so its safe to always remove it in destroy_shell_surface */
> +	wl_list_init(&shsurf->link);
> +
> +	shsurf->client = client;
> +
> +	return shsurf;
> +}
> +
> +static void
> +send_configure(struct weston_surface *surface,
> +	       uint32_t edges, int32_t width, int32_t height)
> +{
> +	struct shell_surface *shsurf = get_shell_surface(surface);
> +
> +	wl_shell_surface_send_configure(&shsurf->resource,
> +					edges, width, height);
> +}
> +
> +static const struct weston_shell_client shell_client = {
> +	send_configure
> +};
> +
> +static void
> +shell_get_shell_surface(struct wl_client *client,
> +			struct wl_resource *resource,
> +			uint32_t id,
> +			struct wl_resource *surface_resource)
> +{
> +	struct weston_surface *surface = surface_resource->data;
> +	struct tablet_shell *shell = resource->data;
> +	struct shell_surface *shsurf;
> +
> +	weston_log("get shell surface\n");
> +
> +	if (get_shell_surface(surface)) {
> +		wl_resource_post_error(surface_resource,
> +				       WL_DISPLAY_ERROR_INVALID_OBJECT,
> +				       "tablet_shell::get_shell_surface already requested");
> +		return;
> +	}
> +
> +	shsurf = create_shell_surface(shell, surface, &shell_client);
> +	if (!shsurf) {
> +		wl_resource_post_error(surface_resource,
> +				       WL_DISPLAY_ERROR_INVALID_OBJECT,
> +				       "surface->configure already set");
> +		return;
> +	}
> +
> +	shsurf->resource.destroy = shell_destroy_shell_surface;
> +	shsurf->resource.object.id = id;
> +	shsurf->resource.object.interface = &wl_shell_surface_interface;
> +	shsurf->resource.object.implementation =
> +		(void (**)(void)) &shell_surface_implementation;
> +	shsurf->resource.data = shsurf;
> +
> +	wl_client_add_resource(client, &shsurf->resource);
> +}
> +
> +static const struct wl_shell_interface shell_implementation = {
> +	shell_get_shell_surface
> +};
> +
> +static void
> +bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
> +{
> +	struct tablet_shell *shell = data;
> +
> +	wl_client_add_object(client, &wl_shell_interface,
> +			     &shell_implementation, id, shell);
> +}
> +
> +static void
>   tablet_shell_destroy(struct wl_listener *listener, void *data);
>
>   static struct tablet_shell *
> @@ -166,6 +474,57 @@ tablet_shell_surface_configure(struct weston_surface *surface,
>   }
>
>   static void
> +configure(struct tablet_shell *shell, struct weston_surface *surface,
> +	  GLfloat x, GLfloat y, int32_t width, int32_t height)
> +{
> +	surface->geometry.x = x;
> +	surface->geometry.y = y;
> +	surface->geometry.width = width;
> +	surface->geometry.height = height;
> +	surface->geometry.dirty = 1;
> +
> +	weston_surface_assign_output(surface);
> +}
> +
> +static void
> +shell_surface_configure(struct weston_surface *surface,
> +			int32_t sx, int32_t sy)
> +{
> +	struct tablet_shell *shell = get_shell(surface->compositor);
> +	int32_t width, height;
> +
> +	if (!weston_surface_is_mapped(surface)) {
> +		width = surface->buffer->width;
> +		height = surface->buffer->height;
> +
> +		weston_surface_configure(surface, 0, 0, width, height);
> +// 		tablet_shell_set_state(shell, STATE_TASK);
> +
> +		wl_list_insert(&shell->application_layer.surface_list,
> +				&surface->layer_link);
> +		// have a try
> +		tablet_client_send_set_fullscreen(&shell->client_resource);
> +		weston_surface_assign_output(surface);
> +	}
> +	if (sx != 0 || sy != 0 ||
> +		 surface->geometry.width != surface->buffer->width ||
> +		 surface->geometry.height != surface->buffer->height) {
> +		GLfloat from_x, from_y;
> +		GLfloat to_x, to_y;
> +
> +		weston_surface_to_global_float(surface, 0, 0,
> +					       &from_x, &from_y);
> +		weston_surface_to_global_float(surface, sx, sy,
> +					       &to_x, &to_y);
> +		configure(shell, surface,
> +			  surface->geometry.x + to_x - from_x,
> +			  surface->geometry.y + to_y - from_y,
> +			  surface->buffer->width,
> +			  surface->buffer->height);
> +	}
> +}
> +
> +static void
>   handle_lockscreen_surface_destroy(struct wl_listener *listener, void *data)
>   {
>   	struct tablet_shell *shell =
> @@ -515,6 +874,23 @@ bind_tablet_shell(struct wl_client *client, void *data, uint32_t version,
>   }
>
>   static void
> +bind_tablet_client(struct wl_client *client, void *data, uint32_t version,
> +		   uint32_t id)
> +{
> +	struct tablet_shell *shell = data;
> +	fprintf(stderr, "bind_tablet_client\n");
> +	shell->client_resource.object.id = id;
> +	shell->client_resource.object.interface = &tablet_client_interface;
> +	shell->client_resource.object.implementation =
> +		(void (**)(void)) &tablet_client_implementation;
> +	shell->client_resource.client = client;
> +	shell->client_resource.data = shell;
> +	shell->client_resource.destroy = destroy_tablet_shell;
> +
> +	wl_client_add_resource(client, &shell->client_resource);
> +}
> +
> +static void
>   tablet_shell_destroy(struct wl_listener *listener, void *data)
>   {
>   	struct tablet_shell *shell =
> @@ -553,10 +929,17 @@ shell_init(struct weston_compositor *compositor)
>   	shell->unlock_listener.notify = tablet_shell_unlock;
>   	wl_signal_add(&compositor->unlock_signal, &shell->unlock_listener);
>
> +	wl_display_add_global(compositor->wl_display, &tablet_client_interface,
> +			      shell, bind_tablet_client);
> +
>   	/* FIXME: This will make the object available to all clients. */
>   	wl_display_add_global(compositor->wl_display, &tablet_shell_interface,
>   			      shell, bind_tablet_shell);
>
> +	if (wl_display_add_global(compositor->wl_display, &wl_shell_interface,
> +				  shell, bind_shell) == NULL)
> +		return;
> +
>   	loop = wl_display_get_event_loop(compositor->wl_display);
>   	shell->long_press_source =
>   		wl_event_loop_add_timer(loop, long_press_handler, shell);
>




More information about the wayland-devel mailing list