From 3862e43779d464fb5bd321e849185adcca9a3a6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 9 Aug 2010 21:25:50 -0400 Subject: [PATCH] Generate client side marshal stubs from protocol spec --- TODO | 2 - protocol.xml | 24 +++---- scanner.c | 167 ++++++++++++++++++++++++++++++++++++++--------- wayland-client.c | 125 +++++------------------------------ wayland-client.h | 27 -------- 5 files changed, 165 insertions(+), 180 deletions(-) diff --git a/TODO b/TODO index 84fad7cd..50d0f4a2 100644 --- a/TODO +++ b/TODO @@ -3,8 +3,6 @@ Core wayland protocol - generate pointer_focus on raise/lower, move windows, all kinds of changes in surface stacking. - - generate marshal stubs as static inline functions. - - don't store globals on client side, require global_handler like everything else. diff --git a/protocol.xml b/protocol.xml index 63927be6..be2e79b1 100644 --- a/protocol.xml +++ b/protocol.xml @@ -13,7 +13,7 @@ - + @@ -25,7 +25,7 @@ - + @@ -50,12 +50,12 @@ - + - + @@ -71,14 +71,14 @@ - - + + - - + + @@ -88,7 +88,7 @@ - + @@ -100,7 +100,7 @@ - + @@ -141,7 +141,7 @@ - + @@ -150,7 +150,7 @@ - + diff --git a/scanner.c b/scanner.c index 47e13ee8..9493f146 100644 --- a/scanner.c +++ b/scanner.c @@ -88,7 +88,7 @@ enum arg_type { struct arg { char *name; enum arg_type type; - char *object_name; + char *interface_name; struct wl_list link; }; @@ -119,12 +119,13 @@ start_element(void *data, const char *element_name, const char **atts) struct interface *interface; struct message *message; struct arg *arg; - const char *name, *type; + const char *name, *type, *interface_name; int i, version; - name = 0; - type = 0; + name = NULL; + type = NULL; version = 0; + interface_name = NULL; for (i = 0; atts[i]; i += 2) { if (strcmp(atts[i], "name") == 0) name = atts[i + 1]; @@ -132,6 +133,8 @@ start_element(void *data, const char *element_name, const char **atts) version = atoi(atts[i + 1]); if (strcmp(atts[i], "type") == 0) type = atts[i + 1]; + if (strcmp(atts[i], "interface") == 0) + interface_name = atts[i + 1]; } if (strcmp(element_name, "interface") == 0) { @@ -178,9 +181,7 @@ start_element(void *data, const char *element_name, const char **atts) arg = malloc(sizeof *arg); arg->name = strdup(name); - if (strcmp(type, "new_id") == 0) - arg->type = NEW_ID; - else if (strcmp(type, "int") == 0) + if (strcmp(type, "int") == 0) arg->type = INT; else if (strcmp(type, "uint") == 0) arg->type = UNSIGNED; @@ -188,9 +189,23 @@ start_element(void *data, const char *element_name, const char **atts) arg->type = STRING; else if (strcmp(type, "array") == 0) arg->type = ARRAY; - else { + else if (strcmp(type, "new_id") == 0) { + if (interface_name == NULL) { + fprintf(stderr, "no interface name given\n"); + exit(EXIT_FAILURE); + } + arg->type = NEW_ID; + arg->interface_name = strdup(interface_name); + } else if (strcmp(type, "object") == 0) { + if (interface_name == NULL) { + fprintf(stderr, "no interface name given\n"); + exit(EXIT_FAILURE); + } arg->type = OBJECT; - arg->object_name = strdup(type); + arg->interface_name = strdup(interface_name); + } else { + fprintf(stderr, "unknown type: %s\n", type); + exit(EXIT_FAILURE); } wl_list_insert(ctx->message->arg_list.prev, @@ -215,6 +230,96 @@ emit_opcodes(struct wl_list *message_list, struct interface *interface) printf("\n"); } +static void +emit_type(struct arg *a) +{ + switch (a->type) { + default: + case INT: + printf("int32_t "); + break; + case NEW_ID: + case UNSIGNED: + printf("uint32_t "); + break; + case STRING: + printf("const char *"); + break; + case OBJECT: + printf("struct wl_%s *", a->interface_name); + break; + case ARRAY: + printf("struct wl_array *"); + break; + } +} + +static void +emit_stubs(struct wl_list *message_list, struct interface *interface) +{ + struct message *m; + struct arg *a, *ret; + + if (wl_list_empty(message_list)) + return; + + wl_list_for_each(m, message_list, link) { + ret = NULL; + wl_list_for_each(a, &m->arg_list, link) { + if (a->type == NEW_ID) + ret = a; + } + + if (ret) + printf("static inline struct wl_%s *\n", + ret->interface_name); + else + printf("static inline void\n"); + + printf("wl_%s_%s(struct wl_%s *%s", + interface->name, m->name, + interface->name, interface->name); + + wl_list_for_each(a, &m->arg_list, link) { + if (a->type == NEW_ID) + continue; + printf(", "); + emit_type(a); + printf("%s", a->name); + } + + printf(")\n" + "{\n"); + if (ret) + printf("\tstruct wl_proxy *%s;\n\n" + "\t%s = wl_proxy_create(" + "(struct wl_proxy *) %s, &wl_%s_interface);\n" + "\tif (!%s)\n" + "\t\treturn NULL;\n\n", + ret->name, + ret->name, + interface->name, ret->interface_name, + ret->name); + + printf("\twl_proxy_marshal((struct wl_proxy *) %s, WL_%s_%s", + interface->name, + interface->uppercase_name, + m->uppercase_name); + + wl_list_for_each(a, &m->arg_list, link) { + printf(", "); + printf("%s", a->name); + } + printf(");\n"); + + if (ret) + printf("\n\treturn (struct wl_%s *) %s;\n", + ret->interface_name, ret->name); + + printf("}\n\n"); + } +} + static void emit_structs(struct wl_list *message_list, struct interface *interface) { @@ -222,6 +327,9 @@ emit_structs(struct wl_list *message_list, struct interface *interface) struct arg *a; int is_interface; + if (wl_list_empty(message_list)) + return; + is_interface = message_list == &interface->request_list; printf("struct wl_%s_%s {\n", interface->name, is_interface ? "interface" : "listener"); @@ -241,25 +349,7 @@ emit_structs(struct wl_list *message_list, struct interface *interface) printf(", "); wl_list_for_each(a, &m->arg_list, link) { - switch (a->type) { - default: - case INT: - printf("int32_t "); - break; - case NEW_ID: - case UNSIGNED: - printf("uint32_t "); - break; - case STRING: - printf("const char *"); - break; - case OBJECT: - printf("struct wl_%s *", a->object_name); - break; - case ARRAY: - printf("struct wl_array *"); - break; - } + emit_type(a); printf("%s%s", a->name, a->link.next == &m->arg_list ? "" : ", "); @@ -292,6 +382,22 @@ emit_header(struct protocol *protocol, int server) printf("struct wl_%s;\n", i->name); printf("\n"); + if (!server) + printf("struct wl_proxy;\n\n" + "extern void\n" + "wl_proxy_marshal(struct wl_proxy *p, " + "uint32_t opcode, ...);\n" + "extern struct wl_proxy *\n" + "wl_proxy_create(struct wl_proxy *factory, " + "const struct wl_interface *interface);\n\n"); + + wl_list_for_each(i, &protocol->interface_list, link) { + printf("extern const struct wl_interface " + "wl_%s_interface;\n", + i->name); + } + printf("\n"); + wl_list_for_each(i, &protocol->interface_list, link) { if (server) { @@ -300,11 +406,8 @@ emit_header(struct protocol *protocol, int server) } else { emit_structs(&i->event_list, i); emit_opcodes(&i->request_list, i); + emit_stubs(&i->request_list, i); } - - printf("extern const struct wl_interface " - "wl_%s_interface;\n\n", - i->name); } printf("#ifdef __cplusplus\n" diff --git a/wayland-client.c b/wayland-client.c index 8fcc8095..f2cf7a06 100644 --- a/wayland-client.c +++ b/wayland-client.c @@ -202,6 +202,23 @@ wl_proxy_create_for_global(struct wl_display *display, return proxy; } +WL_EXPORT struct wl_proxy * +wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface) +{ + struct wl_proxy *proxy; + + proxy = malloc(sizeof *proxy); + if (proxy == NULL) + return NULL; + + proxy->base.interface = interface; + proxy->base.id = wl_display_allocate_id(factory->display); + proxy->display = factory->display; + wl_hash_table_insert(factory->display->objects, proxy->base.id, proxy); + + return proxy; +} + static int wl_proxy_add_listener(struct wl_proxy *proxy, void (**implementation)(void), void *data) { @@ -218,7 +235,7 @@ wl_proxy_add_listener(struct wl_proxy *proxy, void (**implementation)(void), voi return 0; } -static void +WL_EXPORT void wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...) { va_list ap; @@ -248,24 +265,6 @@ wl_shell_add_listener(struct wl_shell *shell, (void (**)(void)) listener, data); } -WL_EXPORT void -wl_shell_move(struct wl_shell *shell, - struct wl_surface *surface, struct wl_input_device *device, - uint32_t time) -{ - wl_proxy_marshal(&shell->proxy, - WL_SHELL_MOVE, surface, device, time); -} - -WL_EXPORT void -wl_shell_resize(struct wl_shell *shell, - struct wl_surface *surface, struct wl_input_device *device, - uint32_t time, uint32_t edges) -{ - wl_proxy_marshal(&shell->proxy, - WL_SHELL_RESIZE, surface, device, time, edges); -} - WL_EXPORT int wl_drm_add_listener(struct wl_drm *drm, const struct wl_drm_listener *listener, @@ -275,40 +274,6 @@ wl_drm_add_listener(struct wl_drm *drm, (void (**)(void)) listener, data); } -WL_EXPORT void -wl_drm_authenticate(struct wl_drm *drm, uint32_t id) -{ - wl_proxy_marshal(&drm->proxy, WL_DRM_AUTHENTICATE, id); -} - -WL_EXPORT struct wl_buffer * -wl_drm_create_buffer(struct wl_drm *drm, uint32_t name, - int32_t width, int32_t height, - uint32_t stride, struct wl_visual *visual) -{ - struct wl_buffer *buffer; - - buffer = malloc(sizeof *buffer); - if (buffer == NULL) - return NULL; - - buffer->proxy.base.interface = &wl_buffer_interface; - buffer->proxy.base.id = wl_display_allocate_id(drm->proxy.display); - buffer->proxy.display = drm->proxy.display; - wl_hash_table_insert(drm->proxy.display->objects, - drm->proxy.base.id, buffer); - wl_proxy_marshal(&drm->proxy, WL_DRM_CREATE_BUFFER, - buffer, name, width, height, stride, visual); - - return buffer; -} - -WL_EXPORT void -wl_buffer_destroy(struct wl_buffer *buffer) -{ - wl_proxy_marshal(&buffer->proxy, WL_BUFFER_DESTROY); -} - static void add_visual(struct wl_display *display, struct wl_global *global) { @@ -610,60 +575,6 @@ wl_compositor_add_listener(struct wl_compositor *compositor, (void (**)(void)) listener, data); } -WL_EXPORT struct wl_surface * -wl_compositor_create_surface(struct wl_compositor *compositor) -{ - struct wl_surface *surface; - - surface = malloc(sizeof *surface); - if (surface == NULL) - return NULL; - - surface->proxy.base.interface = &wl_surface_interface; - surface->proxy.base.id = wl_display_allocate_id(compositor->proxy.display); - surface->proxy.display = compositor->proxy.display; - wl_hash_table_insert(compositor->proxy.display->objects, - surface->proxy.base.id, surface); - wl_proxy_marshal(&compositor->proxy, - WL_COMPOSITOR_CREATE_SURFACE, surface); - - return surface; -} - -WL_EXPORT void -wl_compositor_commit(struct wl_compositor *compositor, uint32_t key) -{ - wl_proxy_marshal(&compositor->proxy, WL_COMPOSITOR_COMMIT, key); -} - -WL_EXPORT void -wl_surface_destroy(struct wl_surface *surface) -{ - wl_proxy_marshal(&surface->proxy, WL_SURFACE_DESTROY); -} - -WL_EXPORT void -wl_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer) -{ - wl_proxy_marshal(&surface->proxy, WL_SURFACE_ATTACH, buffer); -} - -WL_EXPORT void -wl_surface_map(struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - wl_proxy_marshal(&surface->proxy, - WL_SURFACE_MAP, x, y, width, height); -} - -WL_EXPORT void -wl_surface_damage(struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - wl_proxy_marshal(&surface->proxy, - WL_SURFACE_DAMAGE, x, y, width, height); -} - WL_EXPORT void wl_surface_set_user_data(struct wl_surface *surface, void *user_data) { diff --git a/wayland-client.h b/wayland-client.h index 572adc01..ec6a3ca4 100644 --- a/wayland-client.h +++ b/wayland-client.h @@ -66,10 +66,6 @@ wl_display_get_premultiplied_argb_visual(struct wl_display *display); struct wl_visual * wl_display_get_rgb_visual(struct wl_display *display); -struct wl_surface * -wl_compositor_create_surface(struct wl_compositor *compositor); -void -wl_compositor_commit(struct wl_compositor *compositor, uint32_t key); int wl_compositor_add_listener(struct wl_compositor *compostior, const struct wl_compositor_listener *listener, @@ -79,33 +75,10 @@ int wl_shell_add_listener(struct wl_shell *shell, const struct wl_shell_listener *listener, void *data); -void -wl_shell_move(struct wl_shell *shell, - struct wl_surface *surface, struct wl_input_device *device, - uint32_t time); -void -wl_shell_resize(struct wl_shell *shell, - struct wl_surface *surface, struct wl_input_device *device, - uint32_t time, uint32_t edges); - int wl_drm_add_listener(struct wl_drm *drm, const struct wl_drm_listener *listener, void *data); -void -wl_drm_authenticate(struct wl_drm *drm, uint32_t id); -struct wl_buffer * -wl_drm_create_buffer(struct wl_drm *drm, uint32_t name, - int32_t width, int32_t height, - uint32_t stride, struct wl_visual *visual); -void wl_buffer_destroy(struct wl_buffer *buffer); - -void wl_surface_destroy(struct wl_surface *surface); -void wl_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer); -void wl_surface_map(struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height); -void wl_surface_damage(struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height); void wl_surface_set_user_data(struct wl_surface *surface, void *user_data); void *wl_surface_get_user_data(struct wl_surface *surface);