mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 07:03:29 +00:00
implement KeyboardEvent properties and methods
This commit is contained in:
@@ -18,24 +18,12 @@
|
||||
|
||||
const std = @import("std");
|
||||
const log = @import("../../log.zig");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const netsurf = @import("../netsurf.zig");
|
||||
const Event = @import("event.zig").Event;
|
||||
const JsObject = @import("../env.zig").JsObject;
|
||||
|
||||
const c = @cImport({
|
||||
@cInclude("dom/dom.h");
|
||||
@cInclude("core/pi.h");
|
||||
@cInclude("dom/bindings/hubbub/parser.h");
|
||||
@cInclude("events/event_target.h");
|
||||
@cInclude("events/event.h");
|
||||
@cInclude("events/mouse_event.h");
|
||||
@cInclude("events/keyboard_event.h");
|
||||
@cInclude("utils/validate.h");
|
||||
@cInclude("html/html_element.h");
|
||||
@cInclude("html/html_document.h");
|
||||
});
|
||||
|
||||
// TODO: We currently don't have a UIEvent interface so we skip it in the prototype chain.
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/UIEvent
|
||||
const UIEvent = Event;
|
||||
@@ -45,51 +33,125 @@ pub const KeyboardEvent = struct {
|
||||
pub const Self = netsurf.KeyboardEvent;
|
||||
pub const prototype = *UIEvent;
|
||||
|
||||
pub const KeyLocationCode = enum(u16) {
|
||||
standard = 0x00,
|
||||
left = 0x01,
|
||||
right = 0x02,
|
||||
numpad = 0x03,
|
||||
mobile = 0x04, // Non-standard, deprecated.
|
||||
joystick = 0x05, // Non-standard, deprecated.
|
||||
};
|
||||
|
||||
pub const ConstructorOptions = struct {
|
||||
key: []const u8 = "",
|
||||
code: []const u8 = "",
|
||||
location: KeyLocationCode = .standard,
|
||||
char_code: u32 = 0,
|
||||
key_code: u32 = 0,
|
||||
which: u32 = 0,
|
||||
location: netsurf.KeyboardEventOpts.LocationCode = .standard,
|
||||
repeat: bool = false,
|
||||
ctrl_key: bool = false,
|
||||
shift_key: bool = false,
|
||||
alt_key: bool = false,
|
||||
meta_key: bool = false,
|
||||
is_composing: bool = false,
|
||||
isComposing: bool = false,
|
||||
// Currently not supported but we take as argument.
|
||||
charCode: u32 = 0,
|
||||
// Currently not supported but we take as argument.
|
||||
keyCode: u32 = 0,
|
||||
// Currently not supported but we take as argument.
|
||||
which: u32 = 0,
|
||||
ctrlKey: bool = false,
|
||||
shiftKey: bool = false,
|
||||
altKey: bool = false,
|
||||
metaKey: bool = false,
|
||||
};
|
||||
|
||||
pub fn constructor(event_type: []const u8, maybe_options: ?ConstructorOptions) !*netsurf.KeyboardEvent {
|
||||
const options = maybe_options orelse ConstructorOptions{};
|
||||
const options: ConstructorOptions = maybe_options orelse .{};
|
||||
|
||||
var event = try netsurf.keyboardEventCreate();
|
||||
try netsurf.eventSetInternalType(@ptrCast(&event), .keyboard_event);
|
||||
|
||||
const event = try netsurf.keyboardEventCreate();
|
||||
try netsurf.keyboardEventInit(
|
||||
event,
|
||||
event_type,
|
||||
.{
|
||||
.bubbles = false,
|
||||
.cancelable = false,
|
||||
.key = options.key,
|
||||
.code = options.code,
|
||||
.alt = options.alt_key,
|
||||
.ctrl = options.ctrl_key,
|
||||
.meta = options.meta_key,
|
||||
.shift = options.shift_key,
|
||||
.location = options.location,
|
||||
.repeat = options.repeat,
|
||||
.is_composing = options.isComposing,
|
||||
.ctrl_key = options.ctrlKey,
|
||||
.shift_key = options.shiftKey,
|
||||
.alt_key = options.altKey,
|
||||
.meta_key = options.metaKey,
|
||||
},
|
||||
);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
// Returns the modifier state for given modifier key.
|
||||
pub fn _getModifierState(self: *Self, key: []const u8) bool {
|
||||
// Chrome and Firefox do case-sensitive match, here we prefer the same.
|
||||
if (std.mem.eql(u8, key, "Alt")) {
|
||||
return get_altKey(self);
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, key, "AltGraph")) {
|
||||
return (get_altKey(self) and get_ctrlKey(self));
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, key, "Control")) {
|
||||
return get_ctrlKey(self);
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, key, "Shift")) {
|
||||
return get_shiftKey(self);
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, key, "Meta") or std.mem.eql(u8, key, "OS")) {
|
||||
return get_metaKey(self);
|
||||
}
|
||||
|
||||
// Special case for IE.
|
||||
if (comptime builtin.os.tag == .windows) {
|
||||
if (std.mem.eql(u8, key, "Win")) {
|
||||
return get_metaKey(self);
|
||||
}
|
||||
}
|
||||
|
||||
// getModifierState() also accepts a deprecated virtual modifier named "Accel".
|
||||
// event.getModifierState("Accel") returns true when at least one of
|
||||
// KeyboardEvent.ctrlKey or KeyboardEvent.metaKey is true.
|
||||
//
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/getModifierState#accel_virtual_modifier
|
||||
if (std.mem.eql(u8, key, "Accel")) {
|
||||
return (get_ctrlKey(self) or get_metaKey(self));
|
||||
}
|
||||
|
||||
// TODO: Add support for "CapsLock", "ScrollLock".
|
||||
return false;
|
||||
}
|
||||
|
||||
// Getters.
|
||||
|
||||
pub fn get_altKey(self: *Self) bool {
|
||||
return netsurf.keyboardEventKeyIsSet(self, .alt);
|
||||
}
|
||||
|
||||
pub fn get_ctrlKey(self: *Self) bool {
|
||||
return netsurf.keyboardEventKeyIsSet(self, .ctrl);
|
||||
}
|
||||
|
||||
pub fn get_metaKey(self: *Self) bool {
|
||||
return netsurf.keyboardEventKeyIsSet(self, .meta);
|
||||
}
|
||||
|
||||
pub fn get_shiftKey(self: *Self) bool {
|
||||
return netsurf.keyboardEventKeyIsSet(self, .shift);
|
||||
}
|
||||
|
||||
pub fn get_isComposing(self: *Self) bool {
|
||||
return self.is_composing;
|
||||
}
|
||||
|
||||
pub fn get_location(self: *Self) u32 {
|
||||
return self.location;
|
||||
}
|
||||
|
||||
pub fn get_key(self: *Self) ![]const u8 {
|
||||
return netsurf.keyboardEventGetKey(self);
|
||||
}
|
||||
|
||||
pub fn get_repeat(self: *Self) bool {
|
||||
return self.repeat;
|
||||
}
|
||||
};
|
||||
|
||||
const testing = @import("../../testing.zig");
|
||||
|
||||
@@ -952,15 +952,44 @@ pub fn keyboardEventDestroy(evt: *KeyboardEvent) void {
|
||||
c._dom_keyboard_event_destroy(evt);
|
||||
}
|
||||
|
||||
const KeyboardEventOpts = struct {
|
||||
key: []const u8,
|
||||
code: []const u8,
|
||||
pub inline fn keyboardEventKeyIsSet(
|
||||
evt: *KeyboardEvent,
|
||||
comptime key: enum { ctrl, alt, shift, meta },
|
||||
) bool {
|
||||
var is_set: bool = false;
|
||||
const err = switch (key) {
|
||||
.ctrl => c._dom_keyboard_event_get_ctrl_key(evt, &is_set),
|
||||
.alt => c._dom_keyboard_event_get_alt_key(evt, &is_set),
|
||||
.shift => c._dom_keyboard_event_get_shift_key(evt, &is_set),
|
||||
.meta => c._dom_keyboard_event_get_meta_key(evt, &is_set),
|
||||
};
|
||||
// None of the earlier can fail.
|
||||
std.debug.assert(err == c.DOM_NO_ERR);
|
||||
|
||||
return is_set;
|
||||
}
|
||||
|
||||
pub const KeyboardEventOpts = struct {
|
||||
key: []const u8 = "",
|
||||
code: []const u8 = "",
|
||||
location: LocationCode = .standard,
|
||||
repeat: bool = false,
|
||||
bubbles: bool = false,
|
||||
cancelable: bool = false,
|
||||
ctrl: bool = false,
|
||||
alt: bool = false,
|
||||
shift: bool = false,
|
||||
meta: bool = false,
|
||||
is_composing: bool = false,
|
||||
ctrl_key: bool = false,
|
||||
alt_key: bool = false,
|
||||
shift_key: bool = false,
|
||||
meta_key: bool = false,
|
||||
|
||||
pub const LocationCode = enum(u32) {
|
||||
standard = c.DOM_KEY_LOCATION_STANDARD,
|
||||
left = c.DOM_KEY_LOCATION_LEFT,
|
||||
right = c.DOM_KEY_LOCATION_RIGHT,
|
||||
numpad = c.DOM_KEY_LOCATION_NUMPAD,
|
||||
mobile = 0x04, // Non-standard, deprecated.
|
||||
joystick = 0x05, // Non-standard, deprecated.
|
||||
};
|
||||
};
|
||||
|
||||
pub fn keyboardEventInit(evt: *KeyboardEvent, typ: []const u8, opts: KeyboardEventOpts) !void {
|
||||
@@ -973,13 +1002,13 @@ pub fn keyboardEventInit(evt: *KeyboardEvent, typ: []const u8, opts: KeyboardEve
|
||||
null, // dom_abstract_view* ?
|
||||
try strFromData(opts.key),
|
||||
try strFromData(opts.code),
|
||||
0, // location 0 == standard
|
||||
opts.ctrl,
|
||||
opts.shift,
|
||||
opts.alt,
|
||||
opts.meta,
|
||||
false, // repease
|
||||
false, // is_composiom
|
||||
@intFromEnum(opts.location),
|
||||
opts.ctrl_key,
|
||||
opts.shift_key,
|
||||
opts.alt_key,
|
||||
opts.meta_key,
|
||||
opts.repeat, // repease
|
||||
opts.is_composing, // is_composiom
|
||||
);
|
||||
try DOMErr(err);
|
||||
}
|
||||
|
||||
@@ -942,10 +942,10 @@ pub const Page = struct {
|
||||
.cancelable = true,
|
||||
.key = kbe.key,
|
||||
.code = kbe.code,
|
||||
.alt = kbe.alt,
|
||||
.ctrl = kbe.ctrl,
|
||||
.meta = kbe.meta,
|
||||
.shift = kbe.shift,
|
||||
.alt_key = kbe.alt,
|
||||
.ctrl_key = kbe.ctrl,
|
||||
.meta_key = kbe.meta,
|
||||
.shift_key = kbe.shift,
|
||||
});
|
||||
_ = try parser.elementDispatchEvent(element, @ptrCast(event));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user