From 397edbdb31bb6d72b9e1e7aa65b5b9bd56ef5cc6 Mon Sep 17 00:00:00 2001 From: Hannes Schulze Date: Sat, 11 Apr 2026 22:16:58 +0200 Subject: properly handle new objects in events --- lib/CWayland/CWayland.cc | 48 +++++++++++++++++++++++++++--------------------- src/Waylean.lean | 9 +++++++-- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/lib/CWayland/CWayland.cc b/lib/CWayland/CWayland.cc index 940584a..f3c966c 100644 --- a/lib/CWayland/CWayland.cc +++ b/lib/CWayland/CWayland.cc @@ -484,15 +484,12 @@ namespace dispatching_display = src.id; while (wl_display_prepare_read(src.disp)) { - if (wl_display_dispatch_pending(src.disp) == -1) - { - perror("event_loop::poll: wl_display_dispatch_pending"); - } + return ref::steal(io_result_mk_from_errno("")); } if (wl_display_flush(src.disp) == -1) { - perror("event_loop::poll: wl_display_flush"); + return ref::steal(io_result_mk_from_errno("")); } } @@ -504,7 +501,7 @@ namespace while (res == -1 && errno == EINTR); if (res == -1) { - perror("event_loop::poll: poll"); + return ref::steal(io_result_mk_from_errno("")); } // 1. Process signals. @@ -538,12 +535,11 @@ namespace dispatching_display = src.id; if (wl_display_read_events(src.disp) == -1) { - perror("event_loop::poll: wl_display_read_events"); - continue; + return ref::steal(io_result_mk_from_errno("")); } if (wl_display_dispatch_pending(src.disp) == -1) { - perror("event_loop::poll: wl_display_dispatch_pending"); + return ref::steal(io_result_mk_from_errno("")); } } @@ -569,12 +565,12 @@ namespace { auto event = std::move(scheduled.front()); scheduled.pop_front(); - auto option = ref::steal(lean_alloc_ctor(1, 1, 0)); - lean_ctor_set(option.get(), 0, std::move(event.message).release()); - return option; + auto option = lean_alloc_ctor(1, 1, 0); + lean_ctor_set(option, 0, std::move(event.message).release()); + return ref::steal(lean_io_result_mk_ok(option)); } - return ref::steal(lean_box(0)); + return ref::steal(lean_io_result_mk_ok(lean_box(0))); } }; @@ -654,7 +650,7 @@ lean_obj_res waylean_event_loop_poll(b_lean_obj_arg loop_obj) { struct wl_interface x; auto loop = static_cast(lean_get_external_data(loop_obj)); - return lean_io_result_mk_ok(loop->poll().release()); + return loop->poll().release(); } // -- Type Map @@ -844,6 +840,8 @@ lean_obj_res waylean_type_map_register(b_lean_obj_arg map_obj, b_lean_obj_arg if namespace { + ref init_proxy_wrapper(wl_proxy* proxy); + class argument_buffer { enum class type { uninitialized, i32, u32, fixed, string, object, array, fd }; @@ -977,9 +975,11 @@ namespace if (arg.o) { auto res = ref::steal(lean_alloc_ctor(1, 1, 0)); - auto proxy_obj = (lean_object*)(wl_proxy_get_listener((wl_proxy*)arg.o)); // set as dispatcher_data - lean_inc(proxy_obj); - lean_ctor_set(res.get(), 0, proxy_obj); + auto proxy = (wl_proxy*)arg.o; + auto proxy_obj = (signature_type == "n") + ? init_proxy_wrapper(proxy) + : ref{ (lean_object*)(wl_proxy_get_listener(proxy)) }; // set as dispatcher_data + lean_ctor_set(res.get(), 0, std::move(proxy_obj).release()); meta[i].r = std::move(res); } else @@ -1177,6 +1177,7 @@ namespace int dispatcher_func(const void* dispatcher_data, void* target, uint32_t opcode, const wl_message* msg, wl_argument* args) { auto user_data = wl_proxy_get_user_data(static_cast(target)); + if (!user_data) { return 0; } auto handler = ref{ static_cast(user_data) }; auto buffer = new argument_buffer; @@ -1231,6 +1232,14 @@ namespace ); return klass; } + + ref init_proxy_wrapper(wl_proxy* proxy) + { + lean_object* waylean_res = lean_alloc_external(waylean_proxy_class(), proxy); + wl_proxy_add_dispatcher(proxy, dispatcher_func, waylean_res, nullptr); + + return ref::steal(waylean_res); + } } // Proxy.fromDisplay : (display : Display) → IO Proxy @@ -1262,10 +1271,7 @@ lean_obj_res waylean_proxy_send_constructor(b_lean_obj_arg proxy_obj, uint32_t o wl_proxy* res = wl_proxy_marshal_array_constructor(proxy, opcode, buffer->get_args(), &iface->desc); if (!res) { return io_result_mk_from_errno(""); } - lean_object* waylean_res = lean_alloc_external(waylean_proxy_class(), res); - int stat = wl_proxy_add_dispatcher(res, dispatcher_func, waylean_res, nullptr); - - return lean_io_result_mk_ok(waylean_res); + return lean_io_result_mk_ok(init_proxy_wrapper(res).release()); } // Proxy.listen : (proxy : @& Proxy) → (handler : UInt32 → ArgumentBuffer → EventLoop M × M) → IO Unit diff --git a/src/Waylean.lean b/src/Waylean.lean index 8402351..6334301 100644 --- a/src/Waylean.lean +++ b/src/Waylean.lean @@ -25,8 +25,10 @@ def handle (ctx : Context) : RiverWindowManagerV1.Event → DisplayM State Unit DisplayM.liftIO <| IO.println "Another window manager is already running" DisplayM.requestQuit | .finished => do + IO.println "Finished" DisplayM.requestQuit | .manageStart => do + IO.println "Manage Start" let (removedOutputs, aliveOutputs) := (← get).outputs.partition (Function.const _ Output.removed) pure () | .renderStart => pure () @@ -44,7 +46,10 @@ def launch : DisplayM State Unit := do DisplayM.sync do let wm : RiverWindowManagerV1 ← zoomRegistry Registry.bindSingleton let xkbBindings : RiverXkbBindingsV1 ← zoomRegistry Registry.bindSingleton - wm.listen (handle { wm, xkbBindings }) + wm.listen fun ev ↦ do + wm.keep + xkbBindings.keep + handle { wm, xkbBindings } ev def main : IO Unit := - DisplayM.run launch { } + DisplayM.run launch { } (name := "wayland-2") -- cgit v1.3.1