From caa89062671761c1b829054470eb82a1e8d2f6fb Mon Sep 17 00:00:00 2001 From: FireFly Date: Tue, 14 Apr 2026 23:30:39 +0200 Subject: [PATCH] fix: support calls to constructors non-first `new_id` Existing code assumed calls to wayland methods returning proxies (constructors) had the returned `new_id` as its first parameter. Might be better to use a table rather than do list operations on the varargs/rest parameers. --- wau/core/wl_interface.lua | 39 +++++++++++++++++++++++++++++++++++---- wau/core/wl_proxy.lua | 6 +++--- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/wau/core/wl_interface.lua b/wau/core/wl_interface.lua index efc72b6..26bc5a3 100644 --- a/wau/core/wl_interface.lua +++ b/wau/core/wl_interface.lua @@ -13,6 +13,28 @@ void free(void *); local M = { mt = {}, __private = {} } +-- private helper functions + +local function varargs_tail(_, ...) + return ... +end + +local function varargs_set(idx, new_value, x, ...) + if idx == 1 then + return new_value, ... + else + return x, varargs_set(idx - 1, new_value, ...) + end +end + +local function varargs_insert_nil(idx, ...) + if idx == 1 then + return nil, ... + else + return select(1, ...), varargs_insert_nil(idx - 1, varargs_tail(...)) + end +end + -- internal libwayland representation local function parse_types(types) @@ -69,6 +91,7 @@ end local function translate_opcode_to_method(iface, opcode) local method_data = iface.methods[opcode + 1] local type = get_method_type(method_data) + local n_idx = method_data.signature:find("n") if type == mtype.METHOD then return function(other, ...) other:marshal(opcode, ...) @@ -77,7 +100,7 @@ local function translate_opcode_to_method(iface, opcode) elseif type == mtype.CONSTRUCTOR then return function(other, ...) return other:marshal_constructor(opcode, - method_data.types[1], ...) + method_data.types[n_idx], varargs_insert_nil(n_idx, ...)) end elseif type == mtype.DESTRUCTOR then return function(other, ...) @@ -85,9 +108,17 @@ local function translate_opcode_to_method(iface, opcode) raw.wl_proxy_destroy(other) end elseif type == mtype.VERSIONED_CONSTRUCTOR then - return function(other, name, interface, version) - return other:marshal_constructor_versioned(opcode, - interface, version, name, interface.name) + return function(other, ...) + local interface = select(n_idx - 2, ...) + local version = select(n_idx - 1, ...) + + return other:marshal_constructor_versioned( + opcode, interface, version, + varargs_set( + n_idx - 2, + interface.name, + varargs_insert_nil(n_idx, ...))) + end end end diff --git a/wau/core/wl_proxy.lua b/wau/core/wl_proxy.lua index 9058710..bf154b9 100644 --- a/wau/core/wl_proxy.lua +++ b/wau/core/wl_proxy.lua @@ -117,13 +117,13 @@ function M:marshal(opcode, ...) end function M:marshal_constructor(opcode, iface, ...) - local id = raw.wl_proxy_marshal_constructor(self, opcode, iface, nil, ...) + local id = raw.wl_proxy_marshal_constructor(self, opcode, iface, ...) return return_new_proxy(id) end -function M:marshal_constructor_versioned(opcode, iface, version, name, iface_name) +function M:marshal_constructor_versioned(opcode, iface, version, ...) local id = raw.wl_proxy_marshal_constructor_versioned( - self, opcode, iface, version, name, iface_name, version, nil) + self, opcode, iface, version, ...) return return_new_proxy(id) end