Does this help clean up client code? Can you give an example of how a client would use this?
On Wed, Apr 2, 2014 at 10:48 AM, Jason Ekstrand <[email protected]>wrote: > It's worth noting that there is one small backwards-compatability issue > here. Namely, if the client is built against protocol stubs from an > earlier version of libwayland but links against a library built against a > newer version, then all objects created by the client will report a version > of 1. This is because the old api uses wl_proxy_marshal_constructor in > wl_registry_bind so all objects will inherit the protocol version of > wl_display which is 1. The library the client linked against is aware of > the wl_proxy_version function but has no way of knowing that the library > does not. > > One possible solution for this is to set the version of wl_display to zero > and use zero to mean "unversioned". Then, if a library wants to use > something that's not strictly backwards-compatable, it can check for zero > and use whatever it's non-versioned fallback is. > > That said, I'm open to other suggestions. > --Jason Ekstrand > On Apr 2, 2014 12:28 AM, "Jason Ekstrand" <[email protected]> wrote: > >> This provides a standardized mechanism for tracking protocol object >> versions in client code. The wl_display object is created with version 1. >> Every time an object is created from within wl_registry_bind, it gets the >> bound version. Every other time an object is created, it simply inherits >> it's version from the parent object that created it. >> >> >> --- >> I've been meaning to scratch this itch for a while. I've left it as an >> RFC >> for now because it builds, but I don't have any code to test it yet. I've >> got something I'm hoping to hack on this weekend that will use it. For >> now, feel free to comment. >> >> src/scanner.c | 29 +++++++++---- >> src/wayland-client.c | 112 >> +++++++++++++++++++++++++++++++++++++++++++++++---- >> src/wayland-client.h | 13 ++++++ >> 3 files changed, 139 insertions(+), 15 deletions(-) >> >> diff --git a/src/scanner.c b/src/scanner.c >> index e8bfc7c..43b3acf 100644 >> --- a/src/scanner.c >> +++ b/src/scanner.c >> @@ -627,6 +627,14 @@ emit_stubs(struct wl_list *message_list, struct >> interface *interface) >> interface->name, interface->name, interface->name, >> interface->name); >> >> + printf("static inline uint32_t\n" >> + "%s_get_version(struct %s *%s)\n" >> + "{\n" >> + "\treturn wl_proxy_get_version((struct wl_proxy *) %s);\n" >> + "}\n\n", >> + interface->name, interface->name, interface->name, >> + interface->name); >> + >> has_destructor = 0; >> has_destroy = 0; >> wl_list_for_each(m, message_list, link) { >> @@ -698,20 +706,25 @@ emit_stubs(struct wl_list *message_list, struct >> interface *interface) >> >> printf(")\n" >> "{\n"); >> - if (ret) { >> + if (ret && ret->interface_name == NULL) { >> printf("\tstruct wl_proxy *%s;\n\n" >> - "\t%s = wl_proxy_marshal_constructor(" >> + "\t%s = >> wl_proxy_marshal_constructor_versioned(" >> "(struct wl_proxy *) %s,\n" >> - "\t\t\t %s_%s, ", >> + "\t\t\t %s_%s, interface, version", >> ret->name, ret->name, >> interface->name, >> interface->uppercase_name, >> m->uppercase_name); >> - >> - if (ret->interface_name == NULL) >> - printf("interface"); >> - else >> - printf("&%s_interface", >> ret->interface_name); >> + } else if (ret) { >> + printf("\tstruct wl_proxy *%s;\n\n" >> + "\t%s = wl_proxy_marshal_constructor(" >> + "(struct wl_proxy *) %s,\n" >> + "\t\t\t %s_%s, &%s_interface", >> + ret->name, ret->name, >> + interface->name, >> + interface->uppercase_name, >> + m->uppercase_name, >> + ret->interface_name); >> } else { >> printf("\twl_proxy_marshal((struct wl_proxy *) >> %s,\n" >> "\t\t\t %s_%s", >> diff --git a/src/wayland-client.c b/src/wayland-client.c >> index bd40313..5608564 100644 >> --- a/src/wayland-client.c >> +++ b/src/wayland-client.c >> @@ -59,6 +59,7 @@ struct wl_proxy { >> int refcount; >> void *user_data; >> wl_dispatcher_func_t dispatcher; >> + uint32_t version; >> }; >> >> struct wl_global { >> @@ -195,7 +196,8 @@ wl_display_create_queue(struct wl_display *display) >> } >> >> static struct wl_proxy * >> -proxy_create(struct wl_proxy *factory, const struct wl_interface >> *interface) >> +proxy_create(struct wl_proxy *factory, const struct wl_interface >> *interface, >> + uint32_t version) >> { >> struct wl_proxy *proxy; >> struct wl_display *display = factory->display; >> @@ -211,6 +213,7 @@ proxy_create(struct wl_proxy *factory, const struct >> wl_interface *interface) >> proxy->queue = factory->queue; >> proxy->flags = 0; >> proxy->refcount = 1; >> + proxy->version = version; >> >> proxy->object.id = wl_map_insert_new(&display->objects, 0, >> proxy); >> >> @@ -243,7 +246,7 @@ wl_proxy_create(struct wl_proxy *factory, const >> struct wl_interface *interface) >> struct wl_proxy *proxy; >> >> pthread_mutex_lock(&display->mutex); >> - proxy = proxy_create(factory, interface); >> + proxy = proxy_create(factory, interface, factory->version); >> pthread_mutex_unlock(&display->mutex); >> >> return proxy; >> @@ -269,6 +272,7 @@ wl_proxy_create_for_id(struct wl_proxy *factory, >> proxy->queue = factory->queue; >> proxy->flags = 0; >> proxy->refcount = 1; >> + proxy->version = factory->version; >> >> wl_map_insert_at(&display->objects, 0, id, proxy); >> >> @@ -396,7 +400,7 @@ wl_proxy_add_dispatcher(struct wl_proxy *proxy, >> static struct wl_proxy * >> create_outgoing_proxy(struct wl_proxy *proxy, const struct wl_message >> *message, >> union wl_argument *args, >> - const struct wl_interface *interface) >> + const struct wl_interface *interface, uint32_t >> version) >> { >> int i, count; >> const char *signature; >> @@ -410,7 +414,7 @@ create_outgoing_proxy(struct wl_proxy *proxy, const >> struct wl_message *message, >> >> switch (arg.type) { >> case 'n': >> - new_proxy = proxy_create(proxy, interface); >> + new_proxy = proxy_create(proxy, interface, >> version); >> if (new_proxy == NULL) >> return NULL; >> >> @@ -435,7 +439,8 @@ create_outgoing_proxy(struct wl_proxy *proxy, const >> struct wl_message *message, >> * >> * For new-id arguments, this function will allocate a new wl_proxy >> * and send the ID to the server. The new wl_proxy will be returned >> - * on success or NULL on errror with errno set accordingly. >> + * on success or NULL on errror with errno set accordingly. The newly >> + * created proxy will inherit their version from their parent. >> * >> * \note This is intended to be used by language bindings and not in >> * non-generated code. >> @@ -449,6 +454,43 @@ wl_proxy_marshal_array_constructor(struct wl_proxy >> *proxy, >> uint32_t opcode, union wl_argument >> *args, >> const struct wl_interface *interface) >> { >> + return wl_proxy_marshal_array_constructor_versioned(proxy, opcode, >> + args, >> interface, >> + >> proxy->version); >> +} >> + >> + >> +/** Prepare a request to be sent to the compositor >> + * >> + * \param proxy The proxy object >> + * \param opcode Opcode of the request to be sent >> + * \param args Extra arguments for the given request >> + * \param interface The interface to use for the new proxy >> + * \param version The protocol object version for the new proxy >> + * >> + * Translates the request given by opcode and the extra arguments into >> the >> + * wire format and write it to the connection buffer. This version >> takes an >> + * array of the union type wl_argument. >> + * >> + * For new-id arguments, this function will allocate a new wl_proxy >> + * and send the ID to the server. The new wl_proxy will be returned >> + * on success or NULL on errror with errno set accordingly. The newly >> + * created proxy will have the version specified. >> + * >> + * \note This is intended to be used by language bindings and not in >> + * non-generated code. >> + * >> + * \sa wl_proxy_marshal() >> + * >> + * \memberof wl_proxy >> + */ >> +WL_EXPORT struct wl_proxy * >> +wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy, >> + uint32_t opcode, >> + union wl_argument *args, >> + const struct wl_interface >> *interface, >> + uint32_t version) >> +{ >> struct wl_closure *closure; >> struct wl_proxy *new_proxy = NULL; >> const struct wl_message *message; >> @@ -458,7 +500,8 @@ wl_proxy_marshal_array_constructor(struct wl_proxy >> *proxy, >> message = &proxy->object.interface->methods[opcode]; >> if (interface) { >> new_proxy = create_outgoing_proxy(proxy, message, >> - args, interface); >> + args, interface, >> + version); >> if (new_proxy == NULL) >> goto err_unlock; >> } >> @@ -528,7 +571,8 @@ wl_proxy_marshal(struct wl_proxy *proxy, uint32_t >> opcode, ...) >> * >> * For new-id arguments, this function will allocate a new wl_proxy >> * and send the ID to the server. The new wl_proxy will be returned >> - * on success or NULL on errror with errno set accordingly. >> + * on success or NULL on errror with errno set accordingly. The newly >> + * created proxy will inherit their version from their parent. >> * >> * \note This should not normally be used by non-generated code. >> * >> @@ -550,6 +594,46 @@ wl_proxy_marshal_constructor(struct wl_proxy *proxy, >> uint32_t opcode, >> args, interface); >> } >> >> + >> +/** Prepare a request to be sent to the compositor >> + * >> + * \param proxy The proxy object >> + * \param opcode Opcode of the request to be sent >> + * \param interface The interface to use for the new proxy >> + * \param version The protocol object version of the new proxy >> + * \param ... Extra arguments for the given request >> + * \return A new wl_proxy for the new_id argument or NULL on error >> + * >> + * Translates the request given by opcode and the extra arguments into >> the >> + * wire format and write it to the connection buffer. >> + * >> + * For new-id arguments, this function will allocate a new wl_proxy >> + * and send the ID to the server. The new wl_proxy will be returned >> + * on success or NULL on errror with errno set accordingly. The newly >> + * created proxy will have the version specified. >> + * >> + * \note This should not normally be used by non-generated code. >> + * >> + * \memberof wl_proxy >> + */ >> +WL_EXPORT struct wl_proxy * >> +wl_proxy_marshal_constructor_versioned(struct wl_proxy *proxy, uint32_t >> opcode, >> + const struct wl_interface >> *interface, >> + uint32_t version, ...) >> +{ >> + union wl_argument args[WL_CLOSURE_MAX_ARGS]; >> + va_list ap; >> + >> + va_start(ap, version); >> + >> wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature, >> + args, WL_CLOSURE_MAX_ARGS, ap); >> + va_end(ap); >> + >> + return wl_proxy_marshal_array_constructor_versioned(proxy, opcode, >> + args, >> interface, >> + version); >> +} >> + >> /** Prepare a request to be sent to the compositor >> * >> * \param proxy The proxy object >> @@ -730,6 +814,7 @@ wl_display_connect_to_fd(int fd) >> display->proxy.queue = &display->default_queue; >> display->proxy.flags = 0; >> display->proxy.refcount = 1; >> + display->proxy.version = 1; >> >> display->connection = wl_connection_create(display->fd); >> if (display->connection == NULL) >> @@ -1556,6 +1641,19 @@ wl_proxy_get_user_data(struct wl_proxy *proxy) >> return proxy->user_data; >> } >> >> +/** Get the protocol object version of a proxy object >> + * >> + * \param proxy The proxy object >> + * \return The protocol object version of the proxy >> + * >> + * \memberof wl_proxy >> + */ >> +WL_EXPORT uint32_t >> +wl_proxy_get_version(struct wl_proxy *proxy) >> +{ >> + return proxy->version; >> +} >> + >> /** Get the id of a proxy object >> * >> * \param proxy The proxy object >> diff --git a/src/wayland-client.h b/src/wayland-client.h >> index 2a32785..c47b8bf 100644 >> --- a/src/wayland-client.h >> +++ b/src/wayland-client.h >> @@ -130,10 +130,22 @@ struct wl_proxy >> *wl_proxy_marshal_constructor(struct wl_proxy *proxy, >> uint32_t opcode, >> const struct wl_interface >> *interface, >> ...); >> + >> +struct wl_proxy *wl_proxy_marshal_constructor_versioned(struct wl_proxy >> *proxy, >> + uint32_t opcode, >> + const struct >> wl_interface *interface, >> + uint32_t version, >> + ...); >> struct wl_proxy * >> wl_proxy_marshal_array_constructor(struct wl_proxy *proxy, >> uint32_t opcode, union wl_argument >> *args, >> const struct wl_interface *interface); >> +struct wl_proxy * >> +wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy, >> + uint32_t opcode, >> + union wl_argument *args, >> + const struct wl_interface >> *interface, >> + uint32_t version); >> >> void wl_proxy_destroy(struct wl_proxy *proxy); >> int wl_proxy_add_listener(struct wl_proxy *proxy, >> @@ -144,6 +156,7 @@ int wl_proxy_add_dispatcher(struct wl_proxy *proxy, >> const void * dispatcher_data, void *data); >> void wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data); >> void *wl_proxy_get_user_data(struct wl_proxy *proxy); >> +uint32_t wl_proxy_get_version(struct wl_proxy *proxy); >> uint32_t wl_proxy_get_id(struct wl_proxy *proxy); >> const char *wl_proxy_get_class(struct wl_proxy *proxy); >> void wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue >> *queue); >> -- >> 1.9.0 >> >> > _______________________________________________ > wayland-devel mailing list > [email protected] > http://lists.freedesktop.org/mailman/listinfo/wayland-devel > > -- Jasper
_______________________________________________ wayland-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
