move everything to global_event_handlers.zig

This commit is contained in:
Halil Durak
2026-02-04 16:05:06 +03:00
parent 39c9024747
commit b19debff14
4 changed files with 159 additions and 129 deletions

View File

@@ -65,6 +65,9 @@ const timestamp = @import("../datetime.zig").timestamp;
const milliTimestamp = @import("../datetime.zig").milliTimestamp; const milliTimestamp = @import("../datetime.zig").milliTimestamp;
const WebApiURL = @import("webapi/URL.zig"); const WebApiURL = @import("webapi/URL.zig");
const global_event_handlers = @import("webapi/global_event_handlers.zig");
const GlobalEventHandlersLookup = global_event_handlers.Lookup;
const GlobalEventHandler = global_event_handlers.Handler;
var default_url = WebApiURL{ ._raw = "about:blank" }; var default_url = WebApiURL{ ._raw = "about:blank" };
pub var default_location: Location = Location{ ._url = &default_url }; pub var default_location: Location = Location{ ._url = &default_url };
@@ -119,7 +122,7 @@ _element_assigned_slots: Element.AssignedSlotLookup = .{},
/// ```js /// ```js
/// img.setAttribute("onload", "(() => { ... })()"); /// img.setAttribute("onload", "(() => { ... })()");
/// ``` /// ```
_element_attr_listeners: Element.AttrListenerLookup = .{}, _element_attr_listeners: GlobalEventHandlersLookup = .{},
_script_manager: ScriptManager, _script_manager: ScriptManager,
@@ -1215,7 +1218,7 @@ pub fn getElementByIdFromNode(self: *Page, node: *Node, id: []const u8) ?*Elemen
pub fn setAttrListener( pub fn setAttrListener(
self: *Page, self: *Page,
element: *Element, element: *Element,
listener_type: Element.KnownListener, listener_type: GlobalEventHandler,
listener_callback: JS.Function.Global, listener_callback: JS.Function.Global,
) !void { ) !void {
if (comptime IS_DEBUG) { if (comptime IS_DEBUG) {
@@ -1225,7 +1228,7 @@ pub fn setAttrListener(
}); });
} }
const key = element.calcAttrListenerKey(listener_type); const key = global_event_handlers.calculateKey(element.asEventTarget(), listener_type);
const gop = try self._element_attr_listeners.getOrPut(self.arena, key); const gop = try self._element_attr_listeners.getOrPut(self.arena, key);
gop.value_ptr.* = listener_callback; gop.value_ptr.* = listener_callback;
} }
@@ -1234,9 +1237,10 @@ pub fn setAttrListener(
pub fn getAttrListener( pub fn getAttrListener(
self: *const Page, self: *const Page,
element: *Element, element: *Element,
listener_type: Element.KnownListener, listener_type: GlobalEventHandler,
) ?JS.Function.Global { ) ?JS.Function.Global {
return self._element_attr_listeners.get(element.calcAttrListenerKey(listener_type)); const key = global_event_handlers.calculateKey(element.asEventTarget(), listener_type);
return self._element_attr_listeners.get(key);
} }
pub fn registerPerformanceObserver(self: *Page, observer: *PerformanceObserver) !void { pub fn registerPerformanceObserver(self: *Page, observer: *PerformanceObserver) !void {

View File

@@ -49,129 +49,6 @@ pub const RelListLookup = std.AutoHashMapUnmanaged(*Element, *collections.DOMTok
pub const ShadowRootLookup = std.AutoHashMapUnmanaged(*Element, *ShadowRoot); pub const ShadowRootLookup = std.AutoHashMapUnmanaged(*Element, *ShadowRoot);
pub const AssignedSlotLookup = std.AutoHashMapUnmanaged(*Element, *Html.Slot); pub const AssignedSlotLookup = std.AutoHashMapUnmanaged(*Element, *Html.Slot);
/// Better to discriminate it since not directly a pointer int.
///
/// See `calcAttrListenerKey` to obtain one.
const AttrListenerKey = u64;
/// Use `getAttrListenerKey` to create a key.
pub const AttrListenerLookup = std.AutoHashMapUnmanaged(AttrListenerKey, js.Function.Global);
/// Enum of known event listeners; increasing the size of it (u7)
/// can cause `AttrListenerKey` to behave incorrectly.
pub const KnownListener = enum(u7) {
onabort,
onanimationcancel,
onanimationend,
onanimationiteration,
onanimationstart,
onauxclick,
onbeforeinput,
onbeforematch,
onbeforetoggle,
onblur,
oncancel,
oncanplay,
oncanplaythrough,
onchange,
onclick,
onclose,
oncommand,
oncontentvisibilityautostatechange,
oncontextlost,
oncontextmenu,
oncontextrestored,
oncopy,
oncuechange,
oncut,
ondblclick,
ondrag,
ondragend,
ondragenter,
ondragexit,
ondragleave,
ondragover,
ondragstart,
ondrop,
ondurationchange,
onemptied,
onended,
onerror,
onfocus,
onformdata,
onfullscreenchange,
onfullscreenerror,
ongotpointercapture,
oninput,
oninvalid,
onkeydown,
onkeypress,
onkeyup,
onload,
onloadeddata,
onloadedmetadata,
onloadstart,
onlostpointercapture,
onmousedown,
onmousemove,
onmouseout,
onmouseover,
onmouseup,
onpaste,
onpause,
onplay,
onplaying,
onpointercancel,
onpointerdown,
onpointerenter,
onpointerleave,
onpointermove,
onpointerout,
onpointerover,
onpointerrawupdate,
onpointerup,
onprogress,
onratechange,
onreset,
onresize,
onscroll,
onscrollend,
onsecuritypolicyviolation,
onseeked,
onseeking,
onselect,
onselectionchange,
onselectstart,
onslotchange,
onstalled,
onsubmit,
onsuspend,
ontimeupdate,
ontoggle,
ontransitioncancel,
ontransitionend,
ontransitionrun,
ontransitionstart,
onvolumechange,
onwaiting,
onwheel,
};
/// Calculates a lookup key (`AttrListenerKey`) to use with `AttrListenerLookup` for an element.
/// NEVER use generated key to retrieve a pointer back. Portability is not guaranteed.
pub fn calcAttrListenerKey(self: *Element, event_type: KnownListener) AttrListenerKey {
// We can use `Element` for the key too; `EventTarget` is strict about
// its size and alignment, though.
const target = self.asEventTarget();
// Check if we have 3 bits available from alignment of 8.
lp.assert(@alignOf(@TypeOf(target)) == 8, "calcAttrListenerKey: incorrect alignment", .{
.event_target_alignment = @alignOf(@TypeOf(target)),
});
const ptr = @intFromPtr(target) >> 3;
lp.assert(ptr < (1 << 57), "calcAttrListenerKey: pointer overflow", .{ .ptr = ptr });
return ptr | (@as(u64, @intFromEnum(event_type)) << 57);
}
pub const Namespace = enum(u8) { pub const Namespace = enum(u8) {
html, html,
svg, svg,

View File

@@ -21,6 +21,10 @@ const js = @import("../../js/js.zig");
const reflect = @import("../../reflect.zig"); const reflect = @import("../../reflect.zig");
const log = @import("../../../log.zig"); const log = @import("../../../log.zig");
const global_event_handlers = @import("../global_event_handlers.zig");
const GlobalEventHandlersLookup = global_event_handlers.Lookup;
const GlobalEventHandler = global_event_handlers.Handler;
const Page = @import("../../Page.zig"); const Page = @import("../../Page.zig");
const Node = @import("../Node.zig"); const Node = @import("../Node.zig");
const Element = @import("../Element.zig"); const Element = @import("../Element.zig");
@@ -335,7 +339,7 @@ pub fn click(self: *HtmlElement, page: *Page) !void {
fn getAttributeFunction( fn getAttributeFunction(
self: *HtmlElement, self: *HtmlElement,
listener_type: Element.KnownListener, listener_type: GlobalEventHandler,
page: *Page, page: *Page,
) !?js.Function.Global { ) !?js.Function.Global {
const element = self.asElement(); const element = self.asElement();

View File

@@ -0,0 +1,145 @@
// Copyright (C) 2023-2026 Lightpanda (Selecy SAS)
//
// Francis Bouvier <francis@lightpanda.io>
// Pierre Tachoire <pierre@lightpanda.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
const std = @import("std");
const lp = @import("lightpanda");
const js = @import("../js/js.zig");
const EventTarget = @import("EventTarget.zig");
/// Better to discriminate it since not directly a pointer int.
///
/// See `calculateKey` to obtain one.
const Key = u64;
/// Use `calculateKey` to create a key.
pub const Lookup = std.AutoHashMapUnmanaged(Key, js.Function.Global);
/// Enum of known event listeners; increasing the size of it (u7)
/// can cause `Key` to behave incorrectly.
pub const Handler = enum(u7) {
onabort,
onanimationcancel,
onanimationend,
onanimationiteration,
onanimationstart,
onauxclick,
onbeforeinput,
onbeforematch,
onbeforetoggle,
onblur,
oncancel,
oncanplay,
oncanplaythrough,
onchange,
onclick,
onclose,
oncommand,
oncontentvisibilityautostatechange,
oncontextlost,
oncontextmenu,
oncontextrestored,
oncopy,
oncuechange,
oncut,
ondblclick,
ondrag,
ondragend,
ondragenter,
ondragexit,
ondragleave,
ondragover,
ondragstart,
ondrop,
ondurationchange,
onemptied,
onended,
onerror,
onfocus,
onformdata,
onfullscreenchange,
onfullscreenerror,
ongotpointercapture,
oninput,
oninvalid,
onkeydown,
onkeypress,
onkeyup,
onload,
onloadeddata,
onloadedmetadata,
onloadstart,
onlostpointercapture,
onmousedown,
onmousemove,
onmouseout,
onmouseover,
onmouseup,
onpaste,
onpause,
onplay,
onplaying,
onpointercancel,
onpointerdown,
onpointerenter,
onpointerleave,
onpointermove,
onpointerout,
onpointerover,
onpointerrawupdate,
onpointerup,
onprogress,
onratechange,
onreset,
onresize,
onscroll,
onscrollend,
onsecuritypolicyviolation,
onseeked,
onseeking,
onselect,
onselectionchange,
onselectstart,
onslotchange,
onstalled,
onsubmit,
onsuspend,
ontimeupdate,
ontoggle,
ontransitioncancel,
ontransitionend,
ontransitionrun,
ontransitionstart,
onvolumechange,
onwaiting,
onwheel,
};
/// Calculates a lookup key to use with lookup for event target.
/// NEVER use generated key to retrieve a pointer back. Portability is not guaranteed.
pub fn calculateKey(event_target: *EventTarget, handler_type: Handler) Key {
// Check if we have 3 bits available from alignment of 8.
lp.assert(@alignOf(EventTarget) == 8, "calculateKey: incorrect alignment", .{
.event_target_alignment = @alignOf(EventTarget),
});
const ptr = @intFromPtr(event_target) >> 3;
lp.assert(ptr < (1 << 57), "calculateKey: pointer overflow", .{ .ptr = ptr });
return ptr | (@as(Key, @intFromEnum(handler_type)) << 57);
}