Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not forward requests to libwayland if they include client-facing objects #53

Merged
merged 2 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions src/layer-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,15 +549,18 @@ gint find_layer_surface_with_wl_surface (gconstpointer layer_surface, gconstpoin
return wl_surface == needle ? 0 : 1;
}

struct wl_proxy *
gboolean
layer_surface_handle_request (
struct wl_proxy *proxy,
uint32_t opcode,
const struct wl_interface *interface,
uint32_t version,
uint32_t flags,
union wl_argument *args)
union wl_argument *args,
struct wl_proxy **ret_proxy)
{
(void)interface;
(void)flags;
const char* type = proxy->object.interface->name;
if (strcmp(type, xdg_wm_base_interface.name) == 0) {
if (opcode == XDG_WM_BASE_GET_XDG_SURFACE) {
Expand All @@ -574,7 +577,8 @@ layer_surface_handle_request (
self);
self->client_facing_xdg_surface = (struct xdg_surface *)xdg_surface;
layer_surface_create_surface_object(self, wl_surface);
return xdg_surface;
*ret_proxy = xdg_surface;
return TRUE;
}
}
} else if (strcmp(type, xdg_surface_interface.name) == 0) {
Expand All @@ -587,13 +591,15 @@ layer_surface_handle_request (
NULL,
(struct xdg_positioner *)args[2].o);
zwlr_layer_surface_v1_get_popup (self->layer_surface, xdg_popup);
return (struct wl_proxy *)xdg_popup;
*ret_proxy = (struct wl_proxy *)xdg_popup;
return TRUE;
} else {
g_critical ("tried to create popup before layer shell surface");
return libwayland_shim_create_client_proxy (proxy, &xdg_popup_interface, version, NULL, NULL, NULL);
*ret_proxy = libwayland_shim_create_client_proxy (proxy, &xdg_popup_interface, version, NULL, NULL, NULL);
return TRUE;
}
}
}
}
return libwayland_shim_real_wl_proxy_marshal_array_flags (proxy, opcode, interface, version, flags, args);
return FALSE;
}
5 changes: 3 additions & 2 deletions src/layer-surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,13 @@ void layer_surface_set_keyboard_mode (LayerSurface *self, GtkLayerShellKeyboardM
const char* layer_surface_get_namespace (LayerSurface *self);

// Used by libwayland wrappers
struct wl_proxy *layer_surface_handle_request (
gboolean layer_surface_handle_request (
struct wl_proxy *proxy,
uint32_t opcode,
const struct wl_interface *interface,
uint32_t version,
uint32_t flags,
union wl_argument *args);
union wl_argument *args,
struct wl_proxy **ret_proxy);

#endif // LAYER_SHELL_SURFACE_H
75 changes: 74 additions & 1 deletion src/libwayland-shim.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,58 @@ libwayland_shim_get_client_proxy_data (struct wl_proxy *proxy, void* expected_ha
}
}

// Returns true if any arguments are proxies created by us (not known to libwayland)
gboolean
args_contains_client_facing_proxy (
struct wl_proxy *proxy,
uint32_t opcode,
const struct wl_interface *interface,
union wl_argument *args)
{
(void)interface;
const char *sig_iter = proxy->object.interface->methods[opcode].signature;
int i = 0;
while (true) {
struct argument_details arg;
sig_iter = get_next_argument(sig_iter, &arg);
switch (arg.type) {
case 'o':
if (args[i].o && args[i].o->id == client_facing_proxy_id) {
return TRUE;
}
break;

case '\0':
return FALSE;
}
i++;
}
}

// Returns the interface of the proxy object that this request is supposed to create, or NULL if none
const struct wl_interface*
get_interface_of_object_created_by_request (
struct wl_proxy *proxy,
uint32_t opcode,
const struct wl_interface *interface)
{
const char *sig_iter = proxy->object.interface->methods[opcode].signature;
int i = 0;
while (true) {
struct argument_details arg;
sig_iter = get_next_argument(sig_iter, &arg);
switch (arg.type) {
case 'n':
g_assert(interface[i].name);
return interface + i;

case '\0':
return NULL;
}
i++;
}
}

// Overrides the function in wayland-client.c in libwayland
void
wl_proxy_destroy (struct wl_proxy *proxy)
Expand Down Expand Up @@ -221,6 +273,8 @@ wl_proxy_marshal_array_flags (
{
libwayland_shim_init ();
if (proxy->object.id == client_facing_proxy_id) {
// libwayland doesn't know about the object this request is on. It must not find out about this object. If it
// finds out it will be very upset.
struct wrapped_proxy *wrapper = (struct wrapped_proxy *)proxy;
struct wl_proxy *result = NULL;
if (wrapper->handler)
Expand All @@ -229,7 +283,26 @@ wl_proxy_marshal_array_flags (
wl_proxy_destroy(proxy);
return result;
} else {
return layer_surface_handle_request (proxy, opcode, interface, version, flags, args);
struct wl_proxy *ret_proxy = NULL;
if (layer_surface_handle_request (proxy, opcode, interface, version, flags, args, &ret_proxy)) {
// The behavior of the request has been overridden
return ret_proxy;
} else if (args_contains_client_facing_proxy (proxy, opcode, interface, args)) {
// We can't do the normal thing because one of the arguments is an object libwayand doesn't know about, but
// no override behavior was taken. Hopefully we can safely ignore this request.
const struct wl_interface *created = get_interface_of_object_created_by_request(proxy, opcode, interface);
if (created) {
// We need to create a stub object to make the client happy, it will ignore all requests and represents
// nothing in libwayland/the server
return libwayland_shim_create_client_proxy (proxy, created, created->version, NULL, NULL, NULL);
} else {
// Ignore the request
return NULL;
}
} else {
// Forward the request on to libwayland without modification, this is the most common path
return libwayland_shim_real_wl_proxy_marshal_array_flags (proxy, opcode, interface, version, flags, args);
}
}
}

Expand Down
8 changes: 0 additions & 8 deletions src/libwayland-shim.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,4 @@ void libwayland_shim_clear_client_proxy_data (struct wl_proxy *proxy);

void *libwayland_shim_get_client_proxy_data (struct wl_proxy *proxy, void* expected_handler);

extern struct wl_proxy * (*libwayland_shim_real_wl_proxy_marshal_array_flags) (
struct wl_proxy *proxy,
uint32_t opcode,
const struct wl_interface *interface,
uint32_t version,
uint32_t flags,
union wl_argument *args);

#endif // LIBWAYLAND_SHIM_H
Loading