vxfw: remove handles_mouse from Surface

Don't require that surfaces explicitly declare mouse handling. We either
pass an event to the eventHandler or we don't. Along with this, we
remove all native widget passthrough events (IE we never pass an event
to a child). Native widgets which don't handle events also set
eventHandler to null, which prevents any null pointer issues also
This commit is contained in:
Tim Culverhouse 2024-11-23 18:13:43 -06:00
parent 62854672ef
commit 18cc67c604
8 changed files with 1 additions and 41 deletions

View file

@ -110,7 +110,6 @@ pub fn draw(self: *Button, ctx: vxfw.DrawContext) Allocator.Error!vxfw.Surface {
var button_surf = try vxfw.Surface.initWithChildren(ctx.arena, self.widget(), surf.size, surf.children);
@memset(button_surf.buffer, .{ .style = style });
button_surf.handles_mouse = true;
button_surf.focusable = true;
return button_surf;
}

View file

@ -12,16 +12,10 @@ child: vxfw.Widget,
pub fn widget(self: *const Center) vxfw.Widget {
return .{
.userdata = @constCast(self),
.eventHandler = typeErasedEventHandler,
.drawFn = typeErasedDrawFn,
};
}
fn typeErasedEventHandler(ptr: *anyopaque, ctx: *vxfw.EventContext, event: vxfw.Event) anyerror!void {
const self: *const Center = @ptrCast(@alignCast(ptr));
return self.child.handleEvent(ctx, event);
}
fn typeErasedDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) Allocator.Error!vxfw.Surface {
const self: *const Center = @ptrCast(@alignCast(ptr));
return self.draw(ctx);

View file

@ -109,20 +109,6 @@ pub fn handleEvent(self: *ListView, ctx: *vxfw.EventContext, event: vxfw.Event)
self.ensureScroll();
return ctx.consumeAndRedraw();
}
// All other keypresses go to our focused child
switch (self.children) {
.slice => |slice| {
if (slice.len == 0) return;
const child = slice[self.cursor];
return child.handleEvent(ctx, event);
},
.builder => |builder| {
if (builder.itemAtIdx(self.cursor, self.cursor)) |child| {
return child.handleEvent(ctx, event);
}
},
}
},
else => {},
}
@ -307,7 +293,6 @@ fn drawBuilder(self: *ListView, ctx: vxfw.DrawContext, builder: Builder) Allocat
// Set state
{
surface.focusable = true;
surface.handles_mouse = true;
// Assume we have more. We only know we don't after drawing
self.scroll.has_more = true;
}

View file

@ -43,16 +43,10 @@ pub fn vertical(padding: u16) PadValues {
pub fn widget(self: *const Padding) vxfw.Widget {
return .{
.userdata = @constCast(self),
.eventHandler = typeErasedEventHandler,
.drawFn = typeErasedDrawFn,
};
}
fn typeErasedEventHandler(ptr: *anyopaque, ctx: *vxfw.EventContext, event: vxfw.Event) anyerror!void {
const self: *const Padding = @ptrCast(@alignCast(ptr));
return self.child.handleEvent(ctx, event);
}
fn typeErasedDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) Allocator.Error!vxfw.Surface {
const self: *const Padding = @ptrCast(@alignCast(ptr));
return self.draw(ctx);

View file

@ -13,16 +13,10 @@ size: vxfw.Size,
pub fn widget(self: *const SizedBox) vxfw.Widget {
return .{
.userdata = @constCast(self),
.eventHandler = typeErasedEventHandler,
.drawFn = typeErasedDrawFn,
};
}
fn typeErasedEventHandler(ptr: *anyopaque, ctx: *vxfw.EventContext, event: vxfw.Event) anyerror!void {
const self: *const SizedBox = @ptrCast(@alignCast(ptr));
return self.child.handleEvent(ctx, event);
}
fn typeErasedDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) Allocator.Error!vxfw.Surface {
const self: *const SizedBox = @ptrCast(@alignCast(ptr));
const max: vxfw.MaxSize = .{

View file

@ -129,7 +129,6 @@ fn typeErasedDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) Allocator.Error!vxfw
}
var surface = try vxfw.Surface.initWithChildren(ctx.arena, self.widget(), max, &self.children);
surface.handles_mouse = true;
for (0..max.height) |row| {
surface.writeCell(self.width + 1, @intCast(row), .{
.char = .{ .grapheme = "", .width = 1 },

View file

@ -207,7 +207,6 @@ pub fn draw(self: *TextField, ctx: vxfw.DrawContext) Allocator.Error!vxfw.Surfac
.{ .width = max_width, .height = @max(ctx.min.height, 1) },
);
surface.focusable = true;
surface.handles_mouse = true;
const base: vaxis.Cell = .{ .style = .{} };
@memset(surface.buffer, base);

View file

@ -267,8 +267,6 @@ pub const Surface = struct {
/// If this widget / Surface is focusable
focusable: bool = false,
/// If this widget can handle mouse events
handles_mouse: bool = false,
/// Cursor state
cursor: ?CursorState = null,
@ -332,7 +330,6 @@ pub const Surface = struct {
.buffer = self.buffer[0 .. self.size.width * height],
.children = self.children,
.focusable = self.focusable,
.handles_mouse = self.handles_mouse,
};
}
@ -340,8 +337,7 @@ pub const Surface = struct {
/// always be translated to local Surface coordinates. Asserts that this Surface does contain Point
pub fn hitTest(self: Surface, list: *std.ArrayList(HitResult), point: Point) Allocator.Error!void {
assert(point.col < self.size.width and point.row < self.size.height);
if (self.handles_mouse)
try list.append(.{ .local = point, .widget = self.widget });
try list.append(.{ .local = point, .widget = self.widget });
for (self.children) |child| {
if (!child.containsPoint(point)) continue;
const child_point: Point = .{