[PATCH 04/16] xdg-shell: Implement part of the interface.

Kristian Høgsberg hoegsberg at gmail.com
Fri Nov 29 15:29:06 PST 2013


On Wed, Nov 27, 2013 at 03:50:20PM -0200, Rafael Antognolli wrote:
> Basic requests are implemented, enough to get a surface displayed.
> ---
>  src/.gitignore  |   2 +
>  src/Makefile.am |   6 +-
>  src/shell.c     | 228 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
>  3 files changed, 223 insertions(+), 13 deletions(-)
> 
> diff --git a/src/.gitignore b/src/.gitignore
> index 723967d..8e59be6 100644
> --- a/src/.gitignore
> +++ b/src/.gitignore
> @@ -19,3 +19,5 @@ workspaces-protocol.c
>  workspaces-server-protocol.h
>  input-method-protocol.c
>  input-method-server-protocol.h
> +xdg-shell-protocol.c
> +xdg-shell-server-protocol.h
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 551dff9..f6f277d 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -294,7 +294,9 @@ desktop_shell_la_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS)
>  desktop_shell_la_SOURCES =			\
>  	shell.c					\
>  	desktop-shell-protocol.c		\
> -	desktop-shell-server-protocol.h
> +	desktop-shell-server-protocol.h 	\
> +	xdg-shell-protocol.c			\
> +	xdg-shell-server-protocol.h
>  endif
>  
>  if ENABLE_TABLET_SHELL
> @@ -355,6 +357,8 @@ BUILT_SOURCES =					\
>  	input-method-server-protocol.h		\
>  	workspaces-server-protocol.h		\
>  	workspaces-protocol.c			\
> +	xdg-shell-protocol.c			\
> +	xdg-shell-server-protocol.h		\
>  	git-version.h
>  
>  CLEANFILES = $(BUILT_SOURCES)
> diff --git a/src/shell.c b/src/shell.c
> index 507d46f..f775899 100644
> --- a/src/shell.c
> +++ b/src/shell.c
> @@ -40,6 +40,7 @@
>  #include "input-method-server-protocol.h"
>  #include "workspaces-server-protocol.h"
>  #include "../shared/config-parser.h"
> +#include "xdg-shell-server-protocol.h"
>  
>  #define DEFAULT_NUM_WORKSPACES 1
>  #define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
> @@ -1564,8 +1565,8 @@ surface_move(struct shell_surface *shsurf, struct weston_seat *seat)
>  }
>  
>  static void
> -shell_surface_move(struct wl_client *client, struct wl_resource *resource,
> -		   struct wl_resource *seat_resource, uint32_t serial)
> +common_surface_move(struct wl_resource *resource,
> +		    struct wl_resource *seat_resource, uint32_t serial)
>  {
>  	struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
>  	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
> @@ -1587,6 +1588,13 @@ shell_surface_move(struct wl_client *client, struct wl_resource *resource,
>  	}
>  }
>  
> +static void
> +shell_surface_move(struct wl_client *client, struct wl_resource *resource,
> +		   struct wl_resource *seat_resource, uint32_t serial)
> +{
> +	common_surface_move(resource, seat_resource, serial);
> +}
> +
>  struct weston_resize_grab {
>  	struct shell_grab base;
>  	uint32_t edges;
> @@ -1741,9 +1749,9 @@ surface_resize(struct shell_surface *shsurf,
>  }
>  
>  static void
> -shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
> -		     struct wl_resource *seat_resource, uint32_t serial,
> -		     uint32_t edges)
> +common_surface_resize(struct wl_resource *resource,
> +		      struct wl_resource *seat_resource, uint32_t serial,
> +		      uint32_t edges)
>  {
>  	struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
>  	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
> @@ -1763,6 +1771,14 @@ shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
>  }
>  
>  static void
> +shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
> +		     struct wl_resource *seat_resource, uint32_t serial,
> +		     uint32_t edges)
> +{
> +	common_surface_resize(resource, seat_resource, serial, edges);
> +}
> +
> +static void
>  end_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer);
>  
>  static void
> @@ -1943,12 +1959,10 @@ create_pointer_focus_listener(struct weston_seat *seat)
>  }
>  
>  static void
> -shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
> -							uint32_t serial)
> +surface_pong(struct shell_surface *shsurf, uint32_t serial)
>  {
> -	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
> -	struct weston_seat *seat;
>  	struct weston_compositor *ec = shsurf->surface->compositor;
> +	struct weston_seat *seat;
>  
>  	if (shsurf->ping_timer == NULL)
>  		/* Just ignore unsolicited pong. */
> @@ -1965,6 +1979,16 @@ shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
>  }
>  
>  static void
> +shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
> +							uint32_t serial)
> +{
> +	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
> +
> +	surface_pong(shsurf, serial);
> +
> +}
> +
> +static void
>  set_title(struct shell_surface *shsurf, const char *title)
>  {
>  	free(shsurf->title);
> @@ -2802,9 +2826,9 @@ get_shell_surface(struct weston_surface *surface)
>  		return NULL;
>  }
>  
> -static 	struct shell_surface *
> -create_shell_surface(void *shell, struct weston_surface *surface,
> -		     const struct weston_shell_client *client)
> +static struct shell_surface *
> +create_common_surface(void *shell, struct weston_surface *surface,
> +		      const struct weston_shell_client *client)
>  {
>  	struct shell_surface *shsurf;
>  
> @@ -2863,6 +2887,19 @@ create_shell_surface(void *shell, struct weston_surface *surface,
>  	return shsurf;
>  }
>  
> +static struct shell_surface *
> +create_shell_surface(void *shell, struct weston_surface *surface,
> +		     const struct weston_shell_client *client)
> +{
> +	struct shell_surface *shsurf;
> +	shsurf = create_common_surface(shell, surface, client);
> +
> +	shsurf->type = SHELL_SURFACE_NONE;
> +	shsurf->next_type = SHELL_SURFACE_NONE;
> +
> +	return shsurf;
> +}
> +
>  static struct weston_view *
>  get_primary_view(void *shell, struct shell_surface *shsurf)
>  {
> @@ -2907,6 +2944,157 @@ static const struct wl_shell_interface shell_implementation = {
>  	shell_get_shell_surface
>  };
>  
> +/****************************
> + * xdg-shell implementation */
> +
> +static void
> +xdg_surface_destroy(struct wl_client *client,
> +		    struct wl_resource *resource)
> +{
> +	wl_resource_destroy(resource);
> +}
> +
> +static void
> +xdg_surface_pong(struct wl_client *client,
> +		 struct wl_resource *resource,
> +		 uint32_t serial)
> +{
> +	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
> +
> +	surface_pong(shsurf, serial);
> +}
> +
> +static void
> +xdg_surface_set_app_id(struct wl_client *client,
> +		       struct wl_resource *resource,
> +		       const char *app_id)
> +{
> +	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
> +
> +	free(shsurf->class);
> +	shsurf->class = strdup(app_id);
> +}
> +
> +static void
> +xdg_surface_set_title(struct wl_client *client,
> +			struct wl_resource *resource, const char *title)
> +{
> +	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
> +
> +	set_title(shsurf, title);
> +}
> +
> +static void
> +xdg_surface_move(struct wl_client *client, struct wl_resource *resource,
> +		 struct wl_resource *seat_resource, uint32_t serial)
> +{
> +	common_surface_move(resource, seat_resource, serial);
> +}
> +
> +static void
> +xdg_surface_resize(struct wl_client *client, struct wl_resource *resource,
> +		   struct wl_resource *seat_resource, uint32_t serial,
> +		   uint32_t edges)
> +{
> +	common_surface_resize(resource, seat_resource, serial, edges);
> +}
> +
> +static const struct xdg_surface_interface xdg_surface_implementation = {
> +	xdg_surface_destroy,
> +	NULL, // set_transient_for
> +	xdg_surface_set_title,
> +	xdg_surface_set_app_id,
> +	xdg_surface_pong,
> +	xdg_surface_move,
> +	xdg_surface_resize,
> +	NULL, // set_output
> +	NULL, // set_fullscreen
> +	NULL, // unset_fullscreen
> +	NULL, // set_maximized
> +	NULL, // unset_maximized
> +	NULL // set_minimized

We try to avoid // style comments even for a one-line thing like this.
But I think you should just squash patches 4-7 into one big patch.
The point of small commits is mainly bisectability - fix one issues or
add one feature at a time.  In this case the entire xdg_shell
interface is one feature.  If you're landing a big chunk of work,
there's really no point in committing it one or three functions at a
time.

> +};
> +
> +static void
> +xdg_send_configure(struct weston_surface *surface,
> +	       uint32_t edges, int32_t width, int32_t height)
> +{
> +	struct shell_surface *shsurf = get_shell_surface(surface);
> +
> +	xdg_surface_send_configure(shsurf->resource, edges, width, height);
> +}
> +
> +static const struct weston_shell_client xdg_client = {
> +	xdg_send_configure
> +};
> +
> +static void
> +xdg_use_unstable_version(struct wl_client *client,
> +			 struct wl_resource *resource,
> +			 int32_t version)
> +{
> +	if (version > 1) {
> +		wl_resource_post_error(resource,
> +				       1,
> +				       "xdg-shell:: version not implemented yet.");
> +		return;
> +	}
> +}
> +
> +static struct shell_surface *
> +create_xdg_surface(void *shell, struct weston_surface *surface,
> +		   const struct weston_shell_client *client)
> +{
> +	struct shell_surface *shsurf;
> +	shsurf = create_common_surface(shell, surface, client);
> +
> +	shsurf->type = SHELL_SURFACE_NONE;
> +	shsurf->next_type = SHELL_SURFACE_TOPLEVEL;
> +
> +	return shsurf;
> +}
> +
> +static void
> +xdg_get_xdg_surface(struct wl_client *client,
> +		    struct wl_resource *resource,
> +		    uint32_t id,
> +		    struct wl_resource *surface_resource)
> +{
> +	struct weston_surface *surface =
> +		wl_resource_get_user_data(surface_resource);
> +	struct desktop_shell *shell = wl_resource_get_user_data(resource);
> +	struct shell_surface *shsurf;
> +
> +	if (get_shell_surface(surface)) {
> +		wl_resource_post_error(surface_resource,
> +				       WL_DISPLAY_ERROR_INVALID_OBJECT,
> +				       "desktop_shell::get_shell_surface already requested");
> +		return;
> +	}
> +
> +	shsurf = create_xdg_surface(shell, surface, &xdg_client);
> +	if (!shsurf) {
> +		wl_resource_post_error(surface_resource,
> +				       WL_DISPLAY_ERROR_INVALID_OBJECT,
> +				       "surface->configure already set");
> +		return;
> +	}
> +
> +	shsurf->resource =
> +		wl_resource_create(client,
> +				   &xdg_surface_interface, 1, id);
> +	wl_resource_set_implementation(shsurf->resource,
> +				       &xdg_surface_implementation,
> +				       shsurf, shell_destroy_shell_surface);
> +}
> +
> +static const struct xdg_shell_interface xdg_implementation = {
> +	xdg_use_unstable_version,
> +	xdg_get_xdg_surface,
> +	NULL // get_xdg_popup
> +};
> +
> +
>  static void
>  shell_fade(struct desktop_shell *shell, enum fade_type type);
>  
> @@ -4507,6 +4695,18 @@ bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
>  }
>  
>  static void
> +bind_xdg_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
> +{
> +	struct desktop_shell *shell = data;
> +	struct wl_resource *resource;
> +
> +	resource = wl_resource_create(client, &xdg_shell_interface, 1, id);
> +	if (resource)
> +		wl_resource_set_implementation(resource, &xdg_implementation,
> +					       shell, NULL);

I'd like to make sure we can't call any requests in the object until
use_unstable_version() has been called with a matching version.  We can do something like

static int
xdg_shell_unversioned_dispatch(const void *implementation,
			       void *_target, uint32_t opcode,
			       const struct wl_message *message,
			       union wl_argument *args)
{
	struct wl_resource *resource = target;
	struct desktop_shell *shell = wl_resource_get_user_data(resource);
	
	if (opcode != 0) {
		wl_resource_post_error(resource,
				       WL_DISPLAY_ERROR_INVALID_OBJECT,
				       "must call set_unstable_version first");
		return 0;
	}

#define XDG_SERVER_VERSION 1

	if (args[0].i != XDG_SERVER_VERSION) {
		wl_resource_post_error(resource,
				       WL_DISPLAY_ERROR_INVALID_OBJECT,
				       "incompatible version, server is %d "
				       "client wants %d",
				       XDG_SERVER_VERSION, args[0].i);
		return 0;
	}

	wl_resource_set_implementation(resource, &xdg_implementation,
				       shell, NULL);
}

and then use

   wl_resource_set_dispatcher(resource, xdg_shell_unversioned_dispatch,
			      NULL, shell, NULL);
			      
in bind_xdg_shell().

> +}
> +
> +static void
>  unbind_desktop_shell(struct wl_resource *resource)
>  {
>  	struct desktop_shell *shell = wl_resource_get_user_data(resource);
> @@ -6045,6 +6245,10 @@ module_init(struct weston_compositor *ec,
>  				  shell, bind_shell) == NULL)
>  		return -1;
>  
> +	if (wl_global_create(ec->wl_display, &xdg_shell_interface, 1,
> +				  shell, bind_xdg_shell) == NULL)
> +		return -1;
> +
>  	if (wl_global_create(ec->wl_display,
>  			     &desktop_shell_interface, 2,
>  			     shell, bind_desktop_shell) == NULL)
> -- 
> 1.8.3.1
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list