@@ -190,6 +190,58 @@ libwayland_shim_get_client_proxy_data (struct wl_proxy *proxy, void* expected_ha
190190 }
191191}
192192
193+ // Returns true if any arguments are proxies created by us (not known to libwayland)
194+ gboolean
195+ args_contains_client_facing_proxy (
196+ struct wl_proxy * proxy ,
197+ uint32_t opcode ,
198+ const struct wl_interface * interface ,
199+ union wl_argument * args )
200+ {
201+ (void )interface ;
202+ const char * sig_iter = proxy -> object .interface -> methods [opcode ].signature ;
203+ int i = 0 ;
204+ while (true) {
205+ struct argument_details arg ;
206+ sig_iter = get_next_argument (sig_iter , & arg );
207+ switch (arg .type ) {
208+ case 'o' :
209+ if (args [i ].o && args [i ].o -> id == client_facing_proxy_id ) {
210+ return TRUE;
211+ }
212+ break ;
213+
214+ case '\0' :
215+ return FALSE;
216+ }
217+ i ++ ;
218+ }
219+ }
220+
221+ // Returns the interface of the proxy object that this request is supposed to create, or NULL if none
222+ const struct wl_interface *
223+ get_interface_of_object_created_by_request (
224+ struct wl_proxy * proxy ,
225+ uint32_t opcode ,
226+ const struct wl_interface * interface )
227+ {
228+ const char * sig_iter = proxy -> object .interface -> methods [opcode ].signature ;
229+ int i = 0 ;
230+ while (true) {
231+ struct argument_details arg ;
232+ sig_iter = get_next_argument (sig_iter , & arg );
233+ switch (arg .type ) {
234+ case 'n' :
235+ g_assert (interface [i ].name );
236+ return interface + i ;
237+
238+ case '\0' :
239+ return NULL ;
240+ }
241+ i ++ ;
242+ }
243+ }
244+
193245// Overrides the function in wayland-client.c in libwayland
194246void
195247wl_proxy_destroy (struct wl_proxy * proxy )
@@ -221,6 +273,8 @@ wl_proxy_marshal_array_flags (
221273{
222274 libwayland_shim_init ();
223275 if (proxy -> object .id == client_facing_proxy_id ) {
276+ // libwayland doesn't know about the object this request is on. It must not find out about this object. If it
277+ // finds out it will be very upset.
224278 struct wrapped_proxy * wrapper = (struct wrapped_proxy * )proxy ;
225279 struct wl_proxy * result = NULL ;
226280 if (wrapper -> handler )
@@ -229,7 +283,26 @@ wl_proxy_marshal_array_flags (
229283 wl_proxy_destroy (proxy );
230284 return result ;
231285 } else {
232- return layer_surface_handle_request (proxy , opcode , interface , version , flags , args );
286+ struct wl_proxy * ret_proxy = NULL ;
287+ if (layer_surface_handle_request (proxy , opcode , interface , version , flags , args , & ret_proxy )) {
288+ // The behavior of the request has been overridden
289+ return ret_proxy ;
290+ } else if (args_contains_client_facing_proxy (proxy , opcode , interface , args )) {
291+ // We can't do the normal thing because one of the arguments is an object libwayand doesn't know about, but
292+ // no override behavior was taken. Hopefully we can safely ignore this request.
293+ const struct wl_interface * created = get_interface_of_object_created_by_request (proxy , opcode , interface );
294+ if (created ) {
295+ // We need to create a stub object to make the client happy, it will ignore all requests and represents
296+ // nothing in libwayland/the server
297+ return libwayland_shim_create_client_proxy (proxy , created , created -> version , NULL , NULL , NULL );
298+ } else {
299+ // Ignore the request
300+ return NULL ;
301+ }
302+ } else {
303+ // Forward the request on to libwayland without modification, this is the most common path
304+ return libwayland_shim_real_wl_proxy_marshal_array_flags (proxy , opcode , interface , version , flags , args );
305+ }
233306 }
234307}
235308
0 commit comments