From 1fd920a7aea1bb040c7c028f4bbf0af2ea58e1d1 Mon Sep 17 00:00:00 2001 From: Tim Culverhouse Date: Sat, 9 Nov 2024 06:09:39 -0600 Subject: [PATCH] vxfw: add separate function pointer for event capturing Move capture handling of events to a different method on Widget. Having capturing phase in the same method makes it very easy to accidentally capture an event, producing confusing results. Browsers and GTK both require handlers to explicitly listen to capturing phase events, so there is precedence for having this as a separate method. For applications that want to handle it all within the same function, the signature is the same so they can use the same function for both methods and achieve the same result. --- src/vxfw/App.zig | 2 +- src/vxfw/vxfw.zig | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/vxfw/App.zig b/src/vxfw/App.zig index 06b08ca..7bf0818 100644 --- a/src/vxfw/App.zig +++ b/src/vxfw/App.zig @@ -261,7 +261,7 @@ const MouseHandler = struct { var m_local = mouse; m_local.col = item.local.col; m_local.row = item.local.row; - try item.widget.handleEvent(ctx, .{ .mouse = m_local }); + try item.widget.captureEvent(ctx, .{ .mouse = m_local }); try app.handleCommand(&ctx.cmds); // If the event was consumed, we check if we need to send a mouse_leave and return diff --git a/src/vxfw/vxfw.zig b/src/vxfw/vxfw.zig index 0708285..ab50792 100644 --- a/src/vxfw/vxfw.zig +++ b/src/vxfw/vxfw.zig @@ -196,9 +196,16 @@ pub const MaxSize = struct { /// The Widget interface pub const Widget = struct { userdata: *anyopaque, + captureHandler: ?*const fn (userdata: *anyopaque, ctx: *EventContext, event: Event) anyerror!void = null, eventHandler: ?*const fn (userdata: *anyopaque, ctx: *EventContext, event: Event) anyerror!void = null, drawFn: *const fn (userdata: *anyopaque, ctx: DrawContext) Allocator.Error!Surface, + pub fn captureEvent(self: Widget, ctx: *EventContext, event: Event) anyerror!void { + if (self.captureHandler) |handle| { + return handle(self.userdata, ctx, event); + } + } + pub fn handleEvent(self: Widget, ctx: *EventContext, event: Event) anyerror!void { if (self.eventHandler) |handle| { return handle(self.userdata, ctx, event);