diff --git a/src/events/event.zig b/src/events/event.zig index fe939621..56aeb037 100644 --- a/src/events/event.zig +++ b/src/events/event.zig @@ -12,6 +12,7 @@ const parser = @import("../netsurf.zig"); const DOMException = @import("../dom/exceptions.zig").DOMException; const EventTarget = @import("../dom/event_target.zig").EventTarget; const EventTargetUnion = @import("../dom/event_target.zig").Union; +const UIEvent = @import("ui_event.zig").UIEvent; // https://dom.spec.whatwg.org/#event pub const Event = struct { @@ -107,6 +108,7 @@ pub const Event = struct { // Event interfaces pub const Interfaces = generate.Tuple(.{ Event, + UIEvent, }); const Generated = generate.Union.compile(Interfaces); pub const Union = Generated._union; diff --git a/src/events/ui_event.zig b/src/events/ui_event.zig new file mode 100644 index 00000000..c2aad6b8 --- /dev/null +++ b/src/events/ui_event.zig @@ -0,0 +1,51 @@ +const std = @import("std"); + +const jsruntime = @import("jsruntime"); +const Case = jsruntime.test_utils.Case; +const checkCases = jsruntime.test_utils.checkCases; + +const parser = @import("../netsurf.zig"); + +const Event = @import("event.zig").Event; +const Window = @import("../html/window.zig").Window; + +pub const UIEvent = struct { + pub const Self = parser.UIEvent; + pub const mem_guarantied = true; + + pub const UIEventInit = parser.UIEventInit; + + // JS + // -- + + pub fn constructor(typ: []const u8, opts: ?UIEventInit) !*parser.UIEvent { + const evt = try parser.uiEventCreate(); + try parser.uiEventInit(evt, typ, opts orelse UIEventInit{}); + return evt; + } + + pub fn get_detail(self: *parser.UIEvent) !i32 { + return try parser.uiEventDetail(self); + } + + pub fn get_view(self: *parser.UIEvent) !?Window { + return try parser.uiEventView(self); + } +}; + +pub fn testExecFn( + _: std.mem.Allocator, + js_env: *jsruntime.Env, +) anyerror!void { + var ui_event = [_]Case{ + .{ .src = "let content = document.getElementById('content')", .ex = "undefined" }, + .{ .src = "var evt", .ex = "undefined" }, + .{ .src = "content.addEventListener('evt', function(e) {evt = e})", .ex = "undefined" }, + .{ .src = "content.dispatchEvent(new UIEvent('evt'))", .ex = "true" }, + .{ .src = "evt instanceof UIEvent", .ex = "true" }, + .{ .src = "evt.__proto__.constructor.name", .ex = "UIEvent" }, + .{ .src = "evt.detail", .ex = "0" }, + .{ .src = "evt.view", .ex = "null" }, + }; + try checkCases(js_env, &ui_event); +} diff --git a/src/netsurf.zig b/src/netsurf.zig index 7b40363c..a8401d10 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -3,10 +3,14 @@ const std = @import("std"); const c = @cImport({ @cInclude("dom/dom.h"); @cInclude("dom/bindings/hubbub/parser.h"); + @cInclude("events/event.h"); + @cInclude("events/ui_event.h"); }); const Callback = @import("jsruntime").Callback; +const Window = @import("html/window.zig").Window; + // Vtable // ------ @@ -443,6 +447,52 @@ pub fn eventPreventDefault(evt: *Event) !void { try DOMErr(err); } +// UIEvent +pub const UIEvent = c.dom_ui_event; + +pub fn uiEventCreate() !*UIEvent { + var evt: ?*UIEvent = undefined; + const err = c._dom_ui_event_create(&evt); + try DOMErr(err); + return evt.?; +} + +pub const UIEventInit = struct { + bubbles: bool = false, + cancelable: bool = false, + + view: ?Window = null, + detail: i32 = 0, +}; + +pub fn uiEventInit(evt: *UIEvent, typ: []const u8, opts: UIEventInit) !void { + const err = c._dom_ui_event_init( + evt, + try strFromData(typ), + opts.bubbles, + opts.cancelable, + // TODO pass the Window as view. + // opts.view + null, + opts.detail, + ); + try DOMErr(err); +} + +pub fn uiEventDetail(evt: *UIEvent) !i32 { + var res: i32 = undefined; + const err = c._dom_ui_event_get_detail(evt, &res); + try DOMErr(err); + return res; +} + +pub fn uiEventView(_: *UIEvent) !?Window { + // TODO retrieve the Window as view. + // const err = c._dom_ui_event_get_view(evt, &res); + // try DOMErr(err); + return null; +} + // EventHandler fn event_handler_cbk(data: *anyopaque) *Callback { const ptr: *align(@alignOf(*Callback)) anyopaque = @alignCast(data); diff --git a/src/run_tests.zig b/src/run_tests.zig index 22adffe9..d771b508 100644 --- a/src/run_tests.zig +++ b/src/run_tests.zig @@ -22,6 +22,7 @@ const NodeListTestExecFn = @import("dom/nodelist.zig").testExecFn; const AttrTestExecFn = @import("dom/attribute.zig").testExecFn; const EventTargetTestExecFn = @import("dom/event_target.zig").testExecFn; const EventTestExecFn = @import("events/event.zig").testExecFn; +const UIEventTestExecFn = @import("events/ui_event.zig").testExecFn; pub const Types = jsruntime.reflect(apiweb.Interfaces); @@ -77,6 +78,7 @@ fn testsAllExecFn( AttrTestExecFn, EventTargetTestExecFn, EventTestExecFn, + UIEventTestExecFn, }; inline for (testFns) |testFn| {