legacy keyboard and mouse events

This commit is contained in:
Karl Seguin
2025-12-25 18:52:34 +08:00
parent dca99c338e
commit e9ec089f76
7 changed files with 42 additions and 11 deletions

View File

@@ -57,6 +57,7 @@
for (let i = 0; i < expected.length; i++) { for (let i = 0; i < expected.length; i++) {
const ex = expected[i]; const ex = expected[i];
let attribute = attributes[ex.name]; let attribute = attributes[ex.name];
testing.expectEqual('[object Attr]', attribute.toString());
testing.expectEqual(ex.name, attribute.name) testing.expectEqual(ex.name, attribute.name)
testing.expectEqual(ex.value, attribute.value) testing.expectEqual(ex.value, attribute.value)
@@ -246,3 +247,22 @@
}, () => div.toggleAttribute('-invalid')); }, () => div.toggleAttribute('-invalid'));
} }
</script> </script>
<div id=legacy></a>
<script id=legacy>
{
let a = document.getElementById('legacy').attributes;
testing.expectEqual(1, a.length);
testing.expectEqual('[object Attr]', a.item(0).toString());
testing.expectEqual(null, a.item(1));
testing.expectEqual('[object Attr]', a.getNamedItem('id').toString());
testing.expectEqual(null, a.getNamedItem('foo'));
testing.expectEqual('[object Attr]', a.setNamedItem(a.getNamedItem('id')).toString());
testing.expectEqual('id', a['id'].name);
testing.expectEqual('legacy', a['id'].value);
testing.expectEqual(undefined, a['other']);
a[0].value = 'abc123';
testing.expectEqual('abc123', a[0].value);
}
</script>

View File

@@ -32,6 +32,7 @@
testing.expectEqual(true, event.getModifierState("Control")); testing.expectEqual(true, event.getModifierState("Control"));
testing.expectEqual(true, event.getModifierState("Shift")); testing.expectEqual(true, event.getModifierState("Shift"));
testing.expectEqual(true, event.getModifierState("Meta")); testing.expectEqual(true, event.getModifierState("Meta"));
testing.expectEqual(true, event.getModifierState("Accel"));
</script> </script>
<script id=keyDownListener> <script id=keyDownListener>

View File

@@ -32,7 +32,7 @@
testing.expectEqual(true, event.getModifierState("Control")); testing.expectEqual(true, event.getModifierState("Control"));
testing.expectEqual(true, event.getModifierState("Shift")); testing.expectEqual(true, event.getModifierState("Shift"));
testing.expectEqual(true, event.getModifierState("Meta")); testing.expectEqual(true, event.getModifierState("Meta"));
testing.expectEqual(true, event.getModifierState("OS")); testing.expectEqual(false, event.getModifierState("OS"));
testing.expectEqual(true, event.getModifierState("Accel")); testing.expectEqual(true, event.getModifierState("Accel"));
</script> </script>

View File

@@ -16,8 +16,8 @@
testing.expectEqual(0, new_event.button); testing.expectEqual(0, new_event.button);
testing.expectEqual(10, new_event.x); testing.expectEqual(10, new_event.x);
testing.expectEqual(20, new_event.y); testing.expectEqual(20, new_event.y);
testing.expectEqual(10, new_event.screenX); testing.expectEqual(0, new_event.screenX);
testing.expectEqual(20, new_event.screenY); testing.expectEqual(0, new_event.screenY);
</script> </script>
<script id=listener> <script id=listener>

View File

@@ -46,7 +46,7 @@ pub fn format(self: *const Attribute, writer: *std.Io.Writer) !void {
} }
pub fn className(_: *const Attribute) []const u8 { pub fn className(_: *const Attribute) []const u8 {
return "Attr"; return "[object Attr]";
} }
pub fn getName(self: *const Attribute) []const u8 { pub fn getName(self: *const Attribute) []const u8 {
@@ -60,13 +60,13 @@ pub fn getValue(self: *const Attribute) []const u8 {
pub fn setValue(self: *Attribute, data_: ?[]const u8, page: *Page) !void { pub fn setValue(self: *Attribute, data_: ?[]const u8, page: *Page) !void {
const data = data_ orelse ""; const data = data_ orelse "";
const el = self._element orelse { const el = self._element orelse {
self._value = try page.arena.dupe(u8, data); self._value = try page.dupeString(data);
return; return;
}; };
// this takes ownership of the data // this takes ownership of the data
try el.setAttribute(self._name, data, page); try el.setAttribute(self._name, data, page);
// not the most efficient, but we don't expect this to be called oftens // not the most efficient, but we don't expect this to be called often
self._value = (try el.getAttribute(self._name, page)) orelse ""; self._value = (try el.getAttribute(self._name, page)) orelse "";
} }
@@ -97,7 +97,7 @@ pub const JsApi = struct {
pub const name = bridge.accessor(Attribute.getName, null, .{}); pub const name = bridge.accessor(Attribute.getName, null, .{});
pub const localName = bridge.accessor(Attribute.getName, null, .{}); pub const localName = bridge.accessor(Attribute.getName, null, .{});
pub const value = bridge.accessor(Attribute.getValue, null, .{}); pub const value = bridge.accessor(Attribute.getValue, Attribute.setValue, .{});
pub const namespaceURI = bridge.accessor(Attribute.getNamespaceURI, null, .{}); pub const namespaceURI = bridge.accessor(Attribute.getNamespaceURI, null, .{});
pub const ownerElement = bridge.accessor(Attribute.getOwnerElement, null, .{}); pub const ownerElement = bridge.accessor(Attribute.getOwnerElement, null, .{});
}; };
@@ -447,7 +447,7 @@ pub const NamedNodeMap = struct {
// Whenever the NamedNodeMap creates an Attribute, it needs to provide the // Whenever the NamedNodeMap creates an Attribute, it needs to provide the
// "ownerElement". // "ownerElement".
_element: ?*Element = null, _element: *Element,
pub fn length(self: *const NamedNodeMap) u32 { pub fn length(self: *const NamedNodeMap) u32 {
return @intCast(self._list._list.len()); return @intCast(self._list._list.len());
@@ -477,6 +477,11 @@ pub const NamedNodeMap = struct {
return self._list.getAttribute(name, self._element, page); return self._list.getAttribute(name, self._element, page);
} }
pub fn setByName(self: *const NamedNodeMap, attribute: *Attribute, page: *Page) !?*Attribute {
attribute._element = null; // just a requirement of list.putAttribute, it'll re-set it.
return self._list.putAttribute(attribute, self._element, page);
}
pub fn iterator(self: *const NamedNodeMap, page: *Page) !*Iterator { pub fn iterator(self: *const NamedNodeMap, page: *Page) !*Iterator {
return .init(.{ .list = self }, page); return .init(.{ .list = self }, page);
} }
@@ -505,6 +510,7 @@ pub const NamedNodeMap = struct {
pub const @"[int]" = bridge.indexed(NamedNodeMap.getAtIndex, .{ .null_as_undefined = true }); pub const @"[int]" = bridge.indexed(NamedNodeMap.getAtIndex, .{ .null_as_undefined = true });
pub const @"[str]" = bridge.namedIndexed(NamedNodeMap.getByName, null, null, .{ .null_as_undefined = true }); pub const @"[str]" = bridge.namedIndexed(NamedNodeMap.getByName, null, null, .{ .null_as_undefined = true });
pub const getNamedItem = bridge.function(NamedNodeMap.getByName, .{}); pub const getNamedItem = bridge.function(NamedNodeMap.getByName, .{});
pub const setNamedItem = bridge.function(NamedNodeMap.setByName, .{});
pub const item = bridge.function(_item, .{}); pub const item = bridge.function(_item, .{});
fn _item(self: *const NamedNodeMap, index: i32, page: *Page) !?*Attribute { fn _item(self: *const NamedNodeMap, index: i32, page: *Page) !?*Attribute {
// the bridge.indexed handles this, so if we want // the bridge.indexed handles this, so if we want

View File

@@ -177,7 +177,7 @@ pub const KeyboardEventOptions = struct {
metaKey: bool = false, metaKey: bool = false,
}; };
pub const Options = Event.inheritOptions( const Options = Event.inheritOptions(
KeyboardEvent, KeyboardEvent,
KeyboardEventOptions, KeyboardEventOptions,
); );
@@ -253,8 +253,12 @@ pub fn getModifierState(self: *const KeyboardEvent, str: []const u8, page: *Page
.Shift => return self._shift_key, .Shift => return self._shift_key,
.Control => return self._ctrl_key, .Control => return self._ctrl_key,
.Meta => return self._meta_key, .Meta => return self._meta_key,
else => return false, .standard => |s| if (std.mem.eql(u8, s, "Accel")) {
return self._ctrl_key or self._meta_key;
},
else => {},
} }
return false;
} }
pub const JsApi = struct { pub const JsApi = struct {

View File

@@ -63,7 +63,7 @@ pub const MouseEventOptions = struct {
relatedTarget: ?*EventTarget = null, relatedTarget: ?*EventTarget = null,
}; };
pub const Options = Event.inheritOptions( const Options = Event.inheritOptions(
MouseEvent, MouseEvent,
MouseEventOptions, MouseEventOptions,
); );