On Tue, 09 Feb 2016 10:55:57 -0600 Derek Foreman <der...@osg.samsung.com> wrote:
> A pre hook is a wayland library call made on the client side before the > request is sent. > > Until now the wayland library has simply passed requests on without any > knowledge of what they mean, and the receiving compositor has all the > logic. For network transparency to be truly transparent, the library > needs to intercept some things on the client side (buffer set-up, damage > posting) and send along additional information. > > pre-hooks make that possible. > > Signed-off-by: Derek Foreman <der...@osg.samsung.com> > --- > protocol/wayland.dtd | 1 + > src/scanner.c | 108 > +++++++++++++++++++++++++++++++++++++++++++--- > src/wayland-client-core.h | 10 +++++ > src/wayland-client.c | 13 ++++++ > 4 files changed, 126 insertions(+), 6 deletions(-) > > diff --git a/protocol/wayland.dtd b/protocol/wayland.dtd > index 15f20ab..15ca9cc 100644 > --- a/protocol/wayland.dtd > +++ b/protocol/wayland.dtd > @@ -8,6 +8,7 @@ > <!ATTLIST request name CDATA #REQUIRED> > <!ATTLIST request type CDATA #IMPLIED> > <!ATTLIST request since CDATA #IMPLIED> > + <!ATTLIST request hooked CDATA #IMPLIED> > <!ELEMENT event (description?,arg*)> > <!ATTLIST event name CDATA #REQUIRED> > <!ATTLIST event since CDATA #IMPLIED> > diff --git a/src/scanner.c b/src/scanner.c > index 9a74e93..e598200 100644 > --- a/src/scanner.c > +++ b/src/scanner.c > @@ -170,6 +170,7 @@ struct message { > int destructor; > int since; > struct description *description; > + bool hooked; > }; > > enum arg_type { > @@ -609,6 +610,7 @@ start_element(void *data, const char *element_name, const > char **atts) > const char *allow_null = NULL; > const char *enumeration_name = NULL; > const char *bitfield = NULL; > + const char *hooked = NULL; > int i, version = 0; > > ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser); > @@ -636,6 +638,8 @@ start_element(void *data, const char *element_name, const > char **atts) > enumeration_name = atts[i + 1]; > if (strcmp(atts[i], "bitfield") == 0) > bitfield = atts[i + 1]; > + if (strcmp(atts[i], "hooked") == 0) > + hooked = atts[i + 1]; > } > > ctx->character_data_length = 0; > @@ -665,6 +669,15 @@ start_element(void *data, const char *element_name, > const char **atts) > > message = create_message(ctx->loc, name); > > + if (hooked) { > + if (strcmp(hooked, "true") == 0) > + message->hooked = true; > + else if (strcmp(hooked, "false") != 0) > + fail(&ctx->loc, > + "invalid value for hooked attribute (%s)", > + hooked); > + } > + > if (strcmp(element_name, "request") == 0) > wl_list_insert(ctx->interface->request_list.prev, > &message->link); > @@ -938,6 +951,79 @@ emit_type(struct arg *a) > } > > static void > +emit_pre_hook_prototype(struct message *m, struct interface *interface, > struct arg *r) > +{ > + struct arg *a; > + > + if (r) > + printf("void *\n"); > + else > + printf("void\n"); > + > + printf("%s_%s_pre_hook(struct %s *", > + interface->name, m->name, interface->name); > + wl_list_for_each(a, &m->arg_list, link) { > + if (a->type == NEW_ID && a->interface_name == NULL) { > + printf(", const struct wl_interface *interface" > + ", uint32_t version"); > + continue; > + } else if (a->type == NEW_ID) > + continue; > + printf(", "); > + emit_type(a); > + printf("%s", a->name); > + } > + printf(");"); > +} > + > +static void > +emit_pre_hooks(struct wl_list *message_list, struct interface *interface) > +{ > + struct message *m; > + int hooks = 0; > + > + if (wl_list_empty(message_list)) > + return; > + wl_list_for_each(m, message_list, link) { > + struct arg *a, *ret = NULL; > + > + if (!m->hooked) > + continue; > + > + wl_list_for_each(a, &m->arg_list, link) { > + if (a->type == NEW_ID) > + ret = a; > + } > + > + emit_pre_hook_prototype(m, interface, ret); > + hooks++; > + } > + if (hooks) > + printf("\n"); > +} > + > +static void emit_call_pre_hook(struct interface *interface, struct arg *ret, > struct message *m) > +{ > + struct arg *a; > + > + if (ret) { > + printf("\tvoid *hook_data = %s_%s_pre_hook(%s", > interface->name, m->name, interface->name); > + } else > + printf("\t%s_%s_pre_hook(%s", interface->name, m->name, > interface->name); > + wl_list_for_each(a, &m->arg_list, link) { > + if (a->type == NEW_ID && a->interface_name == NULL) { > + printf(", interface" > + ", version"); > + continue; > + } else if (a->type == NEW_ID) > + continue; > + printf(", "); > + printf("%s", a->name); > + } > + printf(");\n"); > +} > + > +static void > emit_stubs(struct wl_list *message_list, struct interface *interface) > { > struct message *m; > @@ -1042,27 +1128,33 @@ emit_stubs(struct wl_list *message_list, struct > interface *interface) > if (ret && ret->interface_name == NULL) { > /* an arg has type ="new_id" but interface is not > * provided, such as in wl_registry.bind */ > - printf("\tstruct wl_proxy *%s;\n\n" > - "\t%s = wl_proxy_marshal_constructor_versioned(" > + printf("\tstruct wl_proxy *%s;\n\n", ret->name); > + if (m->hooked) > + emit_call_pre_hook(interface, ret, m); > + printf("\t%s = wl_proxy_marshal_constructor_versioned(" > "(struct wl_proxy *) %s,\n" > "\t\t\t %s_%s, interface, version", > - ret->name, ret->name, > + ret->name, > interface->name, > interface->uppercase_name, > m->uppercase_name); > } else if (ret) { > /* Normal factory case, an arg has type="new_id" and > * an interface is provided */ > - printf("\tstruct wl_proxy *%s;\n\n" > - "\t%s = wl_proxy_marshal_constructor(" > + printf("\tstruct wl_proxy *%s;\n\n", ret->name); > + if (m->hooked) > + emit_call_pre_hook(interface, ret, m); > + printf("\t%s = wl_proxy_marshal_constructor(" > "(struct wl_proxy *) %s,\n" > "\t\t\t %s_%s, &%s_interface", > - ret->name, ret->name, > + ret->name, > interface->name, > interface->uppercase_name, > m->uppercase_name, > ret->interface_name); > } else { > + if (m->hooked) > + emit_call_pre_hook(interface, ret, m); > /* No args have type="new_id" */ > printf("\twl_proxy_marshal((struct wl_proxy *) %s,\n" > "\t\t\t %s_%s", > @@ -1087,6 +1179,9 @@ emit_stubs(struct wl_list *message_list, struct > interface *interface) > "(struct wl_proxy *) %s);\n", > interface->name); > > + if (ret && m->hooked) > + printf("\twl_proxy_set_hook_data(id, hook_data);\n"); > + > if (ret && ret->interface_name == NULL) > printf("\n\treturn (void *) %s;\n", ret->name); > else if (ret) > @@ -1434,6 +1529,7 @@ emit_header(struct protocol *protocol, enum side side) > emit_structs(&i->event_list, i, side); > emit_opcodes(&i->request_list, i); > emit_opcode_versions(&i->request_list, i); > + emit_pre_hooks(&i->request_list, i); > emit_stubs(&i->request_list, i); > } > > diff --git a/src/wayland-client-core.h b/src/wayland-client-core.h > index 91f7e7b..782b736 100644 > --- a/src/wayland-client-core.h > +++ b/src/wayland-client-core.h > @@ -28,6 +28,7 @@ > > #include "wayland-util.h" > #include "wayland-version.h" > +#include <stdbool.h> > > #ifdef __cplusplus > extern "C" { > @@ -176,6 +177,15 @@ wl_proxy_set_user_data(struct wl_proxy *proxy, void > *user_data); > void * > wl_proxy_get_user_data(struct wl_proxy *proxy); > > +void > +wl_proxy_set_hook_data(struct wl_proxy *proxy, void *hook_data); > + > +void * > +wl_proxy_get_hook_data(struct wl_proxy *proxy); > + > +bool > +wl_proxy_get_remote(struct wl_proxy *proxy); > + > uint32_t > wl_proxy_get_version(struct wl_proxy *proxy); > > diff --git a/src/wayland-client.c b/src/wayland-client.c > index 5c5ecd3..8e7f612 100644 > --- a/src/wayland-client.c > +++ b/src/wayland-client.c > @@ -63,6 +63,7 @@ struct wl_proxy { > void *user_data; > wl_dispatcher_func_t dispatcher; > uint32_t version; > + void *hook_data; > }; > > struct wl_global { > @@ -1856,6 +1857,12 @@ wl_proxy_set_user_data(struct wl_proxy *proxy, void > *user_data) > proxy->user_data = user_data; > } > > +WL_EXPORT void > +wl_proxy_set_hook_data(struct wl_proxy *proxy, void *hook_data) > +{ > + proxy->hook_data = hook_data; > +} > + > /** Get the user data associated with a proxy > * > * \param proxy The proxy object > @@ -1891,6 +1898,12 @@ wl_proxy_get_version(struct wl_proxy *proxy) > return proxy->version; > } > > +WL_EXPORT void * > +wl_proxy_get_hook_data(struct wl_proxy *proxy) > +{ > + return proxy->hook_data; > +} > + > /** Get the id of a proxy object > * > * \param proxy The proxy object Is "hook" the best term? I think I like "intercept" better in this case: consider that something here is "intercepting" the marshallization process and modifying it to contain an additional payload rather than "hooking" it to perform an action. _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel