[PATCH 2/3] Modify wayland-scanner to generate inert objects

Derek Foreman derekf at osg.samsung.com
Wed Sep 23 09:33:23 PDT 2015


This one's been waiting for a long time...

I'm currently pretending to make an effort to clean up patchwork a bit. ;)

On 25/02/15 08:03 AM, David FORT wrote:
> As stated in the very good blog post[1] of Pekka Paalanen, server-side we can have
> sometime troubles with object that the server has deleted but that the client
> is still requesting. This patch complements the scanner to create some code
> that will return inert objects, ie objects that will do nothing and will never
> return anything else but an inert object. An example is a get_pointer() on
> a wl_seat, with an unplugged mouse (and so no pointer). Instead of keeping alive
> the old pointer, we could bind that inert object and wait that the client release
> it (which should happen very quickly as a wl_global_remove should be in the wire).

Personally, I'd like to NAK this one :/

Adding a way to hand out already-dead objects kind of makes me nervous
(perhaps for no good reason).

I think we have to keep the old pointers alive in weston for libinput
backed pointers because we want to retain their position if they go
away/come back.

This could happen on a USB bus reset and not on an intentional
unplug/plug event.

So this doesn't actually simplify compositor code?

The capabilities event from the seat should tell you that your pointer
isn't valid, and that already works.

I guess it's not clear to me what problem this is actually solving.

> 
> [1]: http://ppaalanen.blogspot.fi/2014/07/wayland-protocol-design-object-lifespan.html
> ---
>  src/scanner.c      | 173 +++++++++++++++++++++++++++++++++++++++++++++++++----
>  wayland-scanner.mk |   3 +
>  2 files changed, 166 insertions(+), 10 deletions(-)
> 
> diff --git a/src/scanner.c b/src/scanner.c
> index 1f1e59a..dbdd1f6 100644
> --- a/src/scanner.c
> +++ b/src/scanner.c
> @@ -39,7 +39,7 @@ enum side {
>  static int
>  usage(int ret)
>  {
> -	fprintf(stderr, "usage: ./scanner [client-header|server-header|code]\n");
> +	fprintf(stderr, "usage: ./scanner [client-header|server-header|code|server-inert]\n");
>  	fprintf(stderr, "\n");
>  	fprintf(stderr, "Converts XML protocol descriptions supplied on "
>  			"stdin to client headers,\n"
> @@ -626,6 +626,18 @@ emit_type(struct arg *a)
>  	}
>  }
>  
> +static struct arg *
> +get_return_type(struct message *m)
> +{
> +	struct arg *a, *ret = NULL;
> +
> +	wl_list_for_each(a, &m->arg_list, link) {
> +		if (a->type == NEW_ID)
> +			ret = a;
> +	}
> +	return ret;
> +}
> +
>  static void
>  emit_stubs(struct wl_list *message_list, struct interface *interface)
>  {
> @@ -688,11 +700,7 @@ emit_stubs(struct wl_list *message_list, struct interface *interface)
>  			continue;
>  		}
>  
> -		ret = NULL;
> -		wl_list_for_each(a, &m->arg_list, link) {
> -			if (a->type == NEW_ID)
> -				ret = a;
> -		}
> +		ret = get_return_type(m);
>  
>  		if (ret && ret->interface_name == NULL)
>  			printf("static inline void *\n");
> @@ -1103,8 +1111,7 @@ emit_types(struct protocol *protocol, struct wl_list *message_list)
>  			case NEW_ID:
>  			case OBJECT:
>  				if (a->interface_name)
> -					printf("\t&%s_interface,\n",
> -					       a->interface_name);
> +					printf("\t&%s_interface,\n", a->interface_name);
>  				else
>  					printf("\tNULL,\n");
>  				break;
> @@ -1248,6 +1255,140 @@ emit_code(struct protocol *protocol)
>  	}
>  }
>  
> +static void
> +emit_inert_request(struct protocol *protocol, struct interface *interface, struct wl_list *message_list)
> +{
> +	struct message *m;
> +	struct arg *a, *ret;
> +	const char *newid_name;
> +
> +	wl_list_for_each(m, message_list, link) {
> +		ret = get_return_type(m);
> +
> +		/* forward declaration for the returned object */
> +		if (ret && ret->interface_name) {
> +			printf("static void\n"
> +					"create_inert_%s(struct wl_client *client, uint32_t version, uint32_t id);\n"
> +					"\n",
> +					ret->interface_name);
> +		}
> +
> +		printf("static inline void inert_%s_%s(struct wl_client *client, struct wl_resource *resource",
> +		       interface->name, m->name
> +		       );
> +
> +		wl_list_for_each(a, &m->arg_list, link) {
> +			if (a->type == NEW_ID) {
> +				newid_name = a->name;
> +
> +				if (a->interface_name == NULL) {
> +					printf(", const struct wl_interface *interface"
> +						   ", uint32_t version");
> +					continue;
> +				}
> +			}
> +
> +			if (a->type == OBJECT) {
> +				printf(", struct wl_resource *");
> +			} else {
> +				printf(", ");
> +				emit_type(a);
> +			}
> +			printf("%s", a->name);
> +		}
> +
> +		printf(")\n"
> +		       "{\n");
> +
> +		if (ret && ret->interface_name) {
> +			printf("\tcreate_inert_%s(client, wl_resource_get_version(resource), %s);\n",
> +					ret->interface_name, newid_name);
> +		} else if (m->destructor) {
> +			printf("\twl_resource_destroy(resource);\n");
> +		}
> +		printf("}\n\n");
> +	}
> +}
> +
> +static void
> +emit_inert_interface(struct protocol *protocol, struct interface *i, struct wl_array *types) {
> +	struct message *m;
> +
> +
> +	if(wl_list_length(&i->request_list)) {
> +		emit_inert_request(protocol, i, &i->request_list);
> +
> +		printf ("static const struct %s_interface inert_%s_implementation = {\n",
> +				i->name, i->name);
> +		wl_list_for_each(m, &i->request_list, link) {
> +			printf("\tinert_%s_%s,\n", i->name, m->name);
> +		}
> +		printf ("};\n"
> +				"\n");
> +	}
> +
> +	printf("static inline void\n"
> +			"create_inert_%s(struct wl_client *client, uint32_t version, uint32_t id) {\n",
> +			i->name
> +	);
> +
> +	if(wl_list_length(&i->request_list)) {
> +		/* emit the method body only when there is requests on the object */
> +		printf("\tstruct wl_resource *resource;\n"
> +				"\tresource = wl_resource_create(client, &%s_interface, MIN(version, %d), id);\n"
> +				"\twl_resource_set_implementation(resource, &inert_%s_implementation, NULL, wl_resource_destroy);\n",
> +				i->name, i->version, i->name);
> +	}
> +
> +	printf("}\n"
> +			"\n");
> +
> +}
> +
> +
> +static
> +void emit_inert(struct protocol *protocol) {
> +	struct interface *i;
> +	struct wl_array types;
> +
> +	if (protocol->copyright)
> +		format_copyright(protocol->copyright);
> +
> +	printf("#ifndef __%s_SERVER_INERT__\n"
> +			"#define __%s_SERVER_INERT__\n"
> +			"\n"
> +			"#include \"%s-server-protocol.h\"\n"
> +			"\n"
> +			"#ifdef  __cplusplus\n"
> +			"extern \"C\" {\n"
> +			"#endif\n"
> +			"\n"
> +			"#ifndef MIN\n"
> +			"#define MIN(x,y) (((x) < (y)) ? (x) : (y))\n"
> +			"#endif\n"
> +			"\n",
> +			protocol->uppercase_name,
> +			protocol->uppercase_name,
> +			//protocol->name,
> +			protocol->name
> +			);
> +
> +	wl_list_for_each(i, &protocol->interface_list, link) {
> +		if (!strcmp(i->name, "wl_registry") || !strcmp(i->name, "wl_display"))
> +			continue;
> +
> +		emit_inert_interface(protocol, i, &types);
> +	}
> +
> +	printf("\n"
> +			"#ifdef  __cplusplus\n"
> +			"}\n"
> +			"#endif\n"
> +			"\n"
> +			"#endif\n");
> +
> +}
> +
>  int main(int argc, char *argv[])
>  {
>  	struct parse_context ctx;
> @@ -1257,17 +1398,26 @@ int main(int argc, char *argv[])
>  	enum {
>  		CLIENT_HEADER,
>  		SERVER_HEADER,
> +		SERVER_INERT,
>  		CODE,
>  	} mode;
>  
> -	if (argc != 2)
> +	if (argc < 2) {
>  		usage(EXIT_FAILURE);
> -	else if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0)
> +	}
> +
> +	if (argc > 2) {
> +		stdin = fopen(argv[2], "r");
> +	}
> +
> +	if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0)
>  		usage(EXIT_SUCCESS);
>  	else if (strcmp(argv[1], "client-header") == 0)
>  		mode = CLIENT_HEADER;
>  	else if (strcmp(argv[1], "server-header") == 0)
>  		mode = SERVER_HEADER;
> +	else if (strcmp(argv[1], "server-inert") == 0)
> +		mode = SERVER_INERT;
>  	else if (strcmp(argv[1], "code") == 0)
>  		mode = CODE;
>  	else
> @@ -1317,6 +1467,9 @@ int main(int argc, char *argv[])
>  		case SERVER_HEADER:
>  			emit_header(&protocol, SERVER);
>  			break;
> +		case SERVER_INERT:
> +			emit_inert(&protocol);
> +			break;
>  		case CODE:
>  			emit_code(&protocol);
>  			break;
> diff --git a/wayland-scanner.mk b/wayland-scanner.mk
> index 0a72062..fd994e0 100644
> --- a/wayland-scanner.mk
> +++ b/wayland-scanner.mk
> @@ -6,3 +6,6 @@
>  
>  %-client-protocol.h : $(wayland_protocoldir)/%.xml
>  	$(AM_V_GEN)$(wayland_scanner) client-header < $< > $@
> +
> +%-server-inert.h: $(wayland_protocoldir)/%.xml
> +	$(AM_V_GEN)$(wayland_scanner) server-inert < $< > $@
> \ No newline at end of file
> 



More information about the wayland-devel mailing list