2323#include <poll.h>
2424#include <unistd.h>
2525#include <string/stdstring.h>
26+ #include <dlfcn.h>
2627
2728#include "wayland_common.h"
2829#include "wayland_common_webos.h"
3435#include "../input_keymaps.h"
3536
3637#include "../../gfx/common/wayland/webos-shell.h"
38+
39+ #ifdef HAVE_WEBOS_EXTRA_PROTOS
3740#include "../../gfx/common/wayland/webos-foreign.h"
3841#include "../../gfx/common/wayland/webos-surface-group.h"
3942#include "../../gfx/common/wayland/webos-input-manager.h"
43+ #endif
4044
4145#ifdef HAVE_USERLAND
4246#include <webos-helpers/libhelpers.h>
@@ -260,6 +264,7 @@ static void wl_registry_handle_global_webos(void *data,
260264 wl -> webos_shell = (struct wl_webos_shell * )wl_registry_bind (reg ,
261265 id , & wl_webos_shell_interface , 1 );
262266 }
267+ #ifdef HAVE_WEBOS_EXTRA_PROTOS
263268 else if (string_is_equal (interface , "wl_webos_foreign "))
264269 {
265270 wl -> webos_foreign = (struct wl_webos_foreign * )wl_registry_bind (reg ,
@@ -276,6 +281,7 @@ static void wl_registry_handle_global_webos(void *data,
276281 wl -> webos_input_manager = (struct wl_webos_input_manager * )wl_registry_bind (reg ,
277282 id , & wl_webos_input_manager_interface , 1 );
278283 }
284+ #endif
279285}
280286
281287static void wl_registry_handle_global_remove_webos (void * data ,
@@ -385,12 +391,14 @@ void gfx_ctx_wl_destroy_resources_webos(gfx_ctx_wayland_data_t *wl)
385391 if (wl -> surface )
386392 wl_surface_destroy (wl -> surface );
387393
394+ #ifdef HAVE_WEBOS_EXTRA_PROTOS
388395 if (wl -> webos_input_manager )
389396 wl_webos_input_manager_destroy (wl -> webos_input_manager );
390397 if (wl -> webos_surface_group_compositor )
391398 wl_webos_surface_group_compositor_destroy (wl -> webos_surface_group_compositor );
392399 if (wl -> webos_foreign )
393400 wl_webos_foreign_destroy (wl -> webos_foreign );
401+ #endif
394402 if (wl -> seat )
395403 wl_seat_destroy (wl -> seat );
396404 if (wl -> webos_shell )
@@ -864,3 +872,127 @@ void shutdown_webos_contexts()
864872 }
865873#endif
866874}
875+
876+ /*
877+ Backwards compatibility for older versions of libwayland-client that
878+ do not have wl_proxy_marshal_constructor_versioned and
879+ wl_proxy_marshal_array_constructor_versioned.
880+ */
881+
882+ /* Simple DirectMedia Layer
883+ Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org */
884+ static int parse_msg_signature (const char * signature , int * new_id_index )
885+ {
886+ int count = 0 ;
887+ for (; * signature ; ++ signature ) {
888+ switch (* signature ) {
889+ case 'n' :
890+ * new_id_index = count ;
891+ // Intentional fallthrough
892+ case 'i' :
893+ case 'u' :
894+ case 'f' :
895+ case 's' :
896+ case 'o' :
897+ case 'a' :
898+ case 'h' :
899+ ++ count ;
900+ }
901+ }
902+ return count ;
903+ }
904+
905+ struct wl_proxy * RA_wl_proxy_marshal_constructor_versioned (
906+ struct wl_proxy * proxy , uint32_t opcode ,
907+ const struct wl_interface * iface , uint32_t version , ...)
908+ {
909+ static struct wl_proxy * (* fn )(struct wl_proxy * , uint32_t ,
910+ const struct wl_interface * , uint32_t , ...) = NULL ;
911+ static int dlsym_called = 0 ;
912+
913+ if (!dlsym_called ) {
914+ fn = dlsym (RTLD_NEXT , "wl_proxy_marshal_constructor_versioned" );
915+ dlsym_called = 1 ;
916+ }
917+
918+ if (fn ) {
919+ /* real symbol exists, just call it */
920+ va_list ap ;
921+ va_start (ap , version );
922+ struct wl_proxy * ret = fn (proxy , opcode , iface , version , ap );
923+ va_end (ap );
924+ return ret ;
925+ }
926+
927+ /* fallback path: reconstruct arguments */
928+ void * varargs [WL_CLOSURE_MAX_ARGS ];
929+ int num_args ;
930+ int new_id_index = -1 ;
931+ struct wl_interface * proxy_interface ;
932+ struct wl_proxy * id = wl_proxy_create (proxy , iface );
933+ if (!id )
934+ return NULL ;
935+
936+ proxy_interface = (* (struct wl_interface * * )proxy );
937+ if (opcode > proxy_interface -> method_count )
938+ return NULL ;
939+
940+ num_args = parse_msg_signature (proxy_interface -> methods [opcode ].signature ,
941+ & new_id_index );
942+ if (new_id_index < 0 )
943+ return NULL ;
944+
945+ memset (varargs , 0 , sizeof (varargs ));
946+
947+ va_list ap ;
948+ va_start (ap , version );
949+ for (int i = 0 ; i < num_args ; i ++ )
950+ varargs [i ] = va_arg (ap , void * );
951+ va_end (ap );
952+
953+ varargs [new_id_index ] = id ;
954+
955+ wl_proxy_marshal (proxy , opcode ,
956+ varargs [0 ], varargs [1 ], varargs [2 ], varargs [3 ], varargs [4 ],
957+ varargs [5 ], varargs [6 ], varargs [7 ], varargs [8 ], varargs [9 ],
958+ varargs [10 ], varargs [11 ], varargs [12 ], varargs [13 ], varargs [14 ],
959+ varargs [15 ], varargs [16 ], varargs [17 ], varargs [18 ], varargs [19 ]);
960+
961+ return id ;
962+ }
963+
964+ struct wl_proxy * RA_wl_proxy_marshal_array_constructor_versioned (
965+ struct wl_proxy * proxy , uint32_t opcode ,
966+ union wl_argument * args ,
967+ const struct wl_interface * iface , uint32_t version )
968+ {
969+ static struct wl_proxy * (* fn )(struct wl_proxy * , uint32_t ,
970+ union wl_argument * , const struct wl_interface * , uint32_t ) = NULL ;
971+ static int dlsym_called = 0 ;
972+
973+ if (!dlsym_called ) {
974+ fn = dlsym (RTLD_NEXT , "wl_proxy_marshal_array_constructor_versioned" );
975+ dlsym_called = 1 ;
976+ }
977+
978+ if (!fn ) {
979+ return wl_proxy_marshal_array_constructor (proxy , opcode , args , iface );
980+ }
981+
982+ return fn (proxy , opcode , args , iface , version );
983+ }
984+
985+ struct wl_proxy * wl_proxy_marshal_constructor_versioned (
986+ struct wl_proxy * proxy , uint32_t opcode ,
987+ const struct wl_interface * iface , uint32_t version , ...)
988+ {
989+ return RA_wl_proxy_marshal_constructor_versioned (proxy , opcode , iface , version );
990+ }
991+
992+ struct wl_proxy * wl_proxy_marshal_array_constructor_versioned (
993+ struct wl_proxy * proxy , uint32_t opcode ,
994+ union wl_argument * args ,
995+ const struct wl_interface * iface , uint32_t version )
996+ {
997+ return RA_wl_proxy_marshal_array_constructor_versioned (proxy , opcode , args , iface , version );
998+ }
0 commit comments