diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c index 96d03c978..fbc42ec32 100644 --- a/src/wayland/meta-wayland-data-device.c +++ b/src/wayland/meta-wayland-data-device.c @@ -1174,7 +1174,8 @@ data_device_start_drag (struct wl_client *client, if (icon_resource && !meta_wayland_surface_assign_role (icon_surface, - META_TYPE_WAYLAND_SURFACE_ROLE_DND)) + META_TYPE_WAYLAND_SURFACE_ROLE_DND, + NULL)) { wl_resource_post_error (resource, WL_DATA_DEVICE_ERROR_ROLE, "wl_surface@%d already has a different role", diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index d16a0bc73..d919330d5 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -1005,7 +1005,8 @@ pointer_set_cursor (struct wl_client *client, if (surface && !meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR)) + META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR, + NULL)) { wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE, "wl_surface@%d already has a different role", diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index c3505d2cb..f4dfd1f77 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -29,6 +29,7 @@ #include #include +#include #include #include "gtk-shell-server-protocol.h" @@ -168,13 +169,92 @@ static void meta_wayland_surface_role_shell_surface_managed (MetaWaylandSurfaceRoleShellSurface *shell_surface_role, MetaWindow *window); +static void +unset_param_value (GParameter *param) +{ + g_value_unset (¶m->value); +} + +static GArray * +role_assignment_valist_to_params (GType role_type, + const char *first_property_name, + va_list var_args) +{ + GObjectClass *object_class; + const char *property_name = first_property_name; + GArray *params; + + object_class = g_type_class_ref (role_type); + + params = g_array_new (FALSE, FALSE, sizeof (GParameter)); + g_array_set_clear_func (params, (GDestroyNotify) unset_param_value); + + while (property_name) + { + GParameter param = { + .name = property_name, + .value = G_VALUE_INIT + }; + GParamSpec *pspec; + GType ptype; + gchar *error = NULL; + + pspec = g_object_class_find_property (object_class, + property_name); + g_assert (pspec); + + ptype = G_PARAM_SPEC_VALUE_TYPE (pspec); + G_VALUE_COLLECT_INIT (¶m.value, ptype, var_args, 0, &error); + g_assert (!error); + + g_array_append_val (params, param); + + property_name = va_arg (var_args, const char *); + } + + g_type_class_unref (object_class); + + return params; +} + gboolean meta_wayland_surface_assign_role (MetaWaylandSurface *surface, - GType role_type) + GType role_type, + const char *first_property_name, + ...) { + va_list var_args; + if (!surface->role) { - surface->role = g_object_new (role_type, "surface", surface, NULL); + if (first_property_name) + { + GArray *params; + GParameter param; + + va_start (var_args, first_property_name); + params = role_assignment_valist_to_params (role_type, + first_property_name, + var_args); + va_end (var_args); + + param = (GParameter) { + .name = "surface", + .value = G_VALUE_INIT + }; + g_value_init (¶m.value, META_TYPE_WAYLAND_SURFACE); + g_value_set_object (¶m.value, surface); + g_array_append_val (params, param); + + surface->role = g_object_newv (role_type, params->len, + (GParameter *) params->data); + + g_array_unref (params); + } + else + { + surface->role = g_object_new (role_type, "surface", surface, NULL); + } meta_wayland_surface_role_assigned (surface->role); @@ -193,6 +273,11 @@ meta_wayland_surface_assign_role (MetaWaylandSurface *surface, } else { + va_start (var_args, first_property_name); + g_object_set_valist (G_OBJECT (surface->role), + first_property_name, var_args); + va_end (var_args); + return TRUE; } } @@ -1599,7 +1684,8 @@ wl_subcompositor_get_subsurface (struct wl_client *client, } if (!meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_SURFACE_ROLE_SUBSURFACE)) + META_TYPE_WAYLAND_SURFACE_ROLE_SUBSURFACE, + NULL)) { /* FIXME: There is no subcompositor "role" error yet, so lets just use something * similar until there is. diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index fd1ef415e..967b56fb8 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -243,7 +243,9 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit guint32 id); gboolean meta_wayland_surface_assign_role (MetaWaylandSurface *surface, - GType role_type); + GType role_type, + const char *first_property_name, + ...); MetaWaylandBuffer *meta_wayland_surface_get_buffer (MetaWaylandSurface *surface); diff --git a/src/wayland/meta-wayland-tablet-tool.c b/src/wayland/meta-wayland-tablet-tool.c index 88efdb058..c3df2d971 100644 --- a/src/wayland/meta-wayland-tablet-tool.c +++ b/src/wayland/meta-wayland-tablet-tool.c @@ -443,7 +443,8 @@ tool_set_cursor (struct wl_client *client, if (surface && !meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_SURFACE_ROLE_TABLET_CURSOR)) + META_TYPE_WAYLAND_SURFACE_ROLE_TABLET_CURSOR, + NULL)) { wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE, "wl_surface@%d already has a different role", diff --git a/src/wayland/meta-wayland-wl-shell.c b/src/wayland/meta-wayland-wl-shell.c index 29b89f654..927c593f6 100644 --- a/src/wayland/meta-wayland-wl-shell.c +++ b/src/wayland/meta-wayland-wl-shell.c @@ -518,7 +518,8 @@ wl_shell_get_shell_surface (struct wl_client *client, } if (!meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_WL_SHELL_SURFACE)) + META_TYPE_WAYLAND_WL_SHELL_SURFACE, + NULL)) { wl_resource_post_error (resource, WL_SHELL_ERROR_ROLE, "wl_surface@%d already has a different role", diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c index 5321467a6..0adc3df0c 100644 --- a/src/wayland/meta-wayland-xdg-shell.c +++ b/src/wayland/meta-wayland-xdg-shell.c @@ -767,7 +767,8 @@ xdg_shell_get_xdg_surface (struct wl_client *client, return; } - if (!meta_wayland_surface_assign_role (surface, META_TYPE_WAYLAND_XDG_SURFACE)) + if (!meta_wayland_surface_assign_role (surface, META_TYPE_WAYLAND_XDG_SURFACE, + NULL)) { wl_resource_post_error (resource, XDG_SHELL_ERROR_ROLE, "wl_surface@%d already has a different role", @@ -821,7 +822,8 @@ xdg_shell_get_xdg_popup (struct wl_client *client, return; } - if (!meta_wayland_surface_assign_role (surface, META_TYPE_WAYLAND_XDG_POPUP)) + if (!meta_wayland_surface_assign_role (surface, META_TYPE_WAYLAND_XDG_POPUP, + NULL)) { wl_resource_post_error (resource, XDG_SHELL_ERROR_ROLE, "wl_surface@%d already has a different role", diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c index 0cf966ef9..b40bbcf81 100644 --- a/src/wayland/meta-xwayland.c +++ b/src/wayland/meta-xwayland.c @@ -56,7 +56,8 @@ associate_window_with_surface (MetaWindow *window, MetaDisplay *display = window->display; if (!meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_SURFACE_ROLE_XWAYLAND)) + META_TYPE_WAYLAND_SURFACE_ROLE_XWAYLAND, + NULL)) { wl_resource_post_error (surface->resource, WL_DISPLAY_ERROR_INVALID_OBJECT,