diff --git a/Tests/LibWeb/Text/expected/UIEvents/custom-keyboard-event.txt b/Tests/LibWeb/Text/expected/UIEvents/custom-keyboard-event.txt new file mode 100644 index 0000000000..55adb7b749 --- /dev/null +++ b/Tests/LibWeb/Text/expected/UIEvents/custom-keyboard-event.txt @@ -0,0 +1,4 @@ +1. "W" +2. true +3. true +4. true diff --git a/Tests/LibWeb/Text/input/UIEvents/custom-keyboard-event.html b/Tests/LibWeb/Text/input/UIEvents/custom-keyboard-event.html new file mode 100644 index 0000000000..badcd44219 --- /dev/null +++ b/Tests/LibWeb/Text/input/UIEvents/custom-keyboard-event.html @@ -0,0 +1,22 @@ + + diff --git a/Userland/Libraries/LibWeb/UIEvents/EventModifier.h b/Userland/Libraries/LibWeb/UIEvents/EventModifier.h index bc0ad5ef9e..8efa337f88 100644 --- a/Userland/Libraries/LibWeb/UIEvents/EventModifier.h +++ b/Userland/Libraries/LibWeb/UIEvents/EventModifier.h @@ -16,6 +16,17 @@ struct EventModifierInit : public UIEventInit { bool shift_key { false }; bool alt_key { false }; bool meta_key { false }; + + bool modifier_alt_graph { false }; + bool modifier_caps_lock { false }; + bool modifier_fn { false }; + bool modifier_fn_lock { false }; + bool modifier_hyper { false }; + bool modifier_num_lock { false }; + bool modifier_scroll_lock { false }; + bool modifier_super { false }; + bool modifier_symbol { false }; + bool modifier_symbol_lock { false }; }; } diff --git a/Userland/Libraries/LibWeb/UIEvents/EventModifier.idl b/Userland/Libraries/LibWeb/UIEvents/EventModifier.idl index 907616c5e1..1d083a5505 100644 --- a/Userland/Libraries/LibWeb/UIEvents/EventModifier.idl +++ b/Userland/Libraries/LibWeb/UIEvents/EventModifier.idl @@ -6,5 +6,14 @@ dictionary EventModifierInit : UIEventInit { boolean altKey = false; boolean metaKey = false; - // FIXME: modifier* fields + boolean modifierAltGraph = false; + boolean modifierCapsLock = false; + boolean modifierFn = false; + boolean modifierFnLock = false; + boolean modifierHyper = false; + boolean modifierNumLock = false; + boolean modifierScrollLock = false; + boolean modifierSuper = false; + boolean modifierSymbol = false; + boolean modifierSymbolLock = false; }; diff --git a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp index 19aac20a26..fbfda1384a 100644 --- a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp +++ b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp @@ -653,16 +653,36 @@ JS::NonnullGCPtr KeyboardEvent::create_from_platform_event(JS::Re return event; } -bool KeyboardEvent::get_modifier_state(String const& key_arg) +bool KeyboardEvent::get_modifier_state(String const& key_arg) const { - if (key_arg == "Alt") - return m_alt_key; if (key_arg == "Control") return m_ctrl_key; if (key_arg == "Shift") return m_shift_key; + if (key_arg == "Alt") + return m_alt_key; if (key_arg == "Meta") return m_meta_key; + if (key_arg == "AltGraph") + return m_modifier_alt_graph; + if (key_arg == "CapsLock") + return m_modifier_caps_lock; + if (key_arg == "Fn") + return m_modifier_fn; + if (key_arg == "FnLock") + return m_modifier_fn_lock; + if (key_arg == "Hyper") + return m_modifier_hyper; + if (key_arg == "NumLock") + return m_modifier_num_lock; + if (key_arg == "ScrollLock") + return m_modifier_scroll_lock; + if (key_arg == "Super") + return m_modifier_super; + if (key_arg == "Symbol") + return m_modifier_symbol; + if (key_arg == "SymbolLock") + return m_modifier_symbol_lock; return false; } @@ -685,6 +705,16 @@ KeyboardEvent::KeyboardEvent(JS::Realm& realm, FlyString const& event_name, Keyb , m_shift_key(event_init.shift_key) , m_alt_key(event_init.alt_key) , m_meta_key(event_init.meta_key) + , m_modifier_alt_graph(event_init.modifier_alt_graph) + , m_modifier_caps_lock(event_init.modifier_caps_lock) + , m_modifier_fn(event_init.modifier_fn) + , m_modifier_fn_lock(event_init.modifier_fn_lock) + , m_modifier_hyper(event_init.modifier_hyper) + , m_modifier_num_lock(event_init.modifier_num_lock) + , m_modifier_scroll_lock(event_init.modifier_scroll_lock) + , m_modifier_super(event_init.modifier_super) + , m_modifier_symbol(event_init.modifier_symbol) + , m_modifier_symbol_lock(event_init.modifier_symbol_lock) , m_repeat(event_init.repeat) , m_is_composing(event_init.is_composing) , m_key_code(event_init.key_code) diff --git a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.h b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.h index e8c40caede..42f0737ee1 100644 --- a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.h +++ b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.h @@ -58,7 +58,7 @@ public: bool repeat() const { return m_repeat; } bool is_composing() const { return m_is_composing; } - bool get_modifier_state(String const& key_arg); + bool get_modifier_state(String const& key_arg) const; virtual u32 which() const override { return m_key_code; } @@ -74,6 +74,16 @@ private: bool m_shift_key { false }; bool m_alt_key { false }; bool m_meta_key { false }; + bool m_modifier_alt_graph { false }; + bool m_modifier_caps_lock { false }; + bool m_modifier_fn { false }; + bool m_modifier_fn_lock { false }; + bool m_modifier_hyper { false }; + bool m_modifier_num_lock { false }; + bool m_modifier_scroll_lock { false }; + bool m_modifier_super { false }; + bool m_modifier_symbol { false }; + bool m_modifier_symbol_lock { false }; bool m_repeat { false }; bool m_is_composing { false }; u32 m_key_code { 0 }; diff --git a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.cpp b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.cpp index 3b5fccad14..79add6e12e 100644 --- a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.cpp +++ b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.cpp @@ -16,7 +16,7 @@ namespace Web::UIEvents { JS_DEFINE_ALLOCATOR(MouseEvent); -MouseEvent::MouseEvent(JS::Realm& realm, FlyString const& event_name, MouseEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y, unsigned modifiers) +MouseEvent::MouseEvent(JS::Realm& realm, FlyString const& event_name, MouseEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y) : UIEvent(realm, event_name, event_init) , m_screen_x(event_init.screen_x) , m_screen_y(event_init.screen_y) @@ -26,10 +26,20 @@ MouseEvent::MouseEvent(JS::Realm& realm, FlyString const& event_name, MouseEvent , m_client_y(event_init.client_y) , m_offset_x(offset_x) , m_offset_y(offset_y) - , m_ctrl_key(modifiers & Mod_Ctrl) - , m_shift_key(modifiers & Mod_Shift) - , m_alt_key(modifiers & Mod_Alt) - , m_meta_key(modifiers & Mod_Super) + , m_ctrl_key(event_init.ctrl_key) + , m_shift_key(event_init.shift_key) + , m_alt_key(event_init.alt_key) + , m_meta_key(event_init.meta_key) + , m_modifier_alt_graph(event_init.modifier_alt_graph) + , m_modifier_caps_lock(event_init.modifier_caps_lock) + , m_modifier_fn(event_init.modifier_fn) + , m_modifier_fn_lock(event_init.modifier_fn_lock) + , m_modifier_hyper(event_init.modifier_hyper) + , m_modifier_num_lock(event_init.modifier_num_lock) + , m_modifier_scroll_lock(event_init.modifier_scroll_lock) + , m_modifier_super(event_init.modifier_super) + , m_modifier_symbol(event_init.modifier_symbol) + , m_modifier_symbol_lock(event_init.modifier_symbol_lock) , m_movement_x(event_init.movement_x) , m_movement_y(event_init.movement_y) , m_button(event_init.button) @@ -46,6 +56,39 @@ void MouseEvent::initialize(JS::Realm& realm) set_prototype(&Bindings::ensure_web_prototype(realm, "MouseEvent"_fly_string)); } +bool MouseEvent::get_modifier_state(String const& key_arg) const +{ + if (key_arg == "Control") + return m_ctrl_key; + if (key_arg == "Shift") + return m_shift_key; + if (key_arg == "Alt") + return m_alt_key; + if (key_arg == "Meta") + return m_meta_key; + if (key_arg == "AltGraph") + return m_modifier_alt_graph; + if (key_arg == "CapsLock") + return m_modifier_caps_lock; + if (key_arg == "Fn") + return m_modifier_fn; + if (key_arg == "FnLock") + return m_modifier_fn_lock; + if (key_arg == "Hyper") + return m_modifier_hyper; + if (key_arg == "NumLock") + return m_modifier_num_lock; + if (key_arg == "ScrollLock") + return m_modifier_scroll_lock; + if (key_arg == "Super") + return m_modifier_super; + if (key_arg == "Symbol") + return m_modifier_symbol; + if (key_arg == "SymbolLock") + return m_modifier_symbol_lock; + return false; +} + // https://www.w3.org/TR/uievents/#dom-mouseevent-button static i16 determine_button(unsigned mouse_button) { @@ -65,14 +108,18 @@ static i16 determine_button(unsigned mouse_button) } } -JS::NonnullGCPtr MouseEvent::create(JS::Realm& realm, FlyString const& event_name, MouseEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y, unsigned modifiers) +JS::NonnullGCPtr MouseEvent::create(JS::Realm& realm, FlyString const& event_name, MouseEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y) { - return realm.heap().allocate(realm, realm, event_name, event_init, page_x, page_y, offset_x, offset_y, modifiers); + return realm.heap().allocate(realm, realm, event_name, event_init, page_x, page_y, offset_x, offset_y); } WebIDL::ExceptionOr> MouseEvent::create_from_platform_event(JS::Realm& realm, FlyString const& event_name, CSSPixelPoint screen, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, Optional movement, unsigned button, unsigned buttons, unsigned modifiers) { MouseEventInit event_init {}; + event_init.ctrl_key = modifiers & Mod_Ctrl; + event_init.shift_key = modifiers & Mod_Shift; + event_init.alt_key = modifiers & Mod_Alt; + event_init.meta_key = modifiers & Mod_Super; event_init.screen_x = screen.x().to_double(); event_init.screen_y = screen.y().to_double(); event_init.client_x = client.x().to_double(); @@ -83,7 +130,7 @@ WebIDL::ExceptionOr> MouseEvent::create_from_platfo } event_init.button = determine_button(button); event_init.buttons = buttons; - auto event = MouseEvent::create(realm, event_name, event_init, page.x().to_double(), page.y().to_double(), offset.x().to_double(), offset.y().to_double(), modifiers); + auto event = MouseEvent::create(realm, event_name, event_init, page.x().to_double(), page.y().to_double(), offset.x().to_double(), offset.y().to_double()); event->set_is_trusted(true); return event; } diff --git a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.h b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.h index 512b444941..813e909ddf 100644 --- a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.h +++ b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.h @@ -29,7 +29,7 @@ class MouseEvent : public UIEvent { JS_DECLARE_ALLOCATOR(MouseEvent); public: - [[nodiscard]] static JS::NonnullGCPtr create(JS::Realm&, FlyString const& event_name, MouseEventInit const& = {}, double page_x = 0, double page_y = 0, double offset_x = 0, double offset_y = 0, unsigned modifiers = 0); + [[nodiscard]] static JS::NonnullGCPtr create(JS::Realm&, FlyString const& event_name, MouseEventInit const& = {}, double page_x = 0, double page_y = 0, double offset_x = 0, double offset_y = 0); static WebIDL::ExceptionOr> create_from_platform_event(JS::Realm&, FlyString const& event_name, CSSPixelPoint screen, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, Optional movement, unsigned button, unsigned buttons, unsigned modifiers); virtual ~MouseEvent() override; @@ -60,10 +60,12 @@ public: i16 button() const { return m_button; } u16 buttons() const { return m_buttons; } + bool get_modifier_state(String const& key_arg) const; + virtual u32 which() const override { return m_button + 1; } protected: - MouseEvent(JS::Realm&, FlyString const& event_name, MouseEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y, unsigned modifiers); + MouseEvent(JS::Realm&, FlyString const& event_name, MouseEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y); virtual void initialize(JS::Realm&) override; @@ -82,6 +84,16 @@ private: bool m_shift_key { false }; bool m_alt_key { false }; bool m_meta_key { false }; + bool m_modifier_alt_graph { false }; + bool m_modifier_caps_lock { false }; + bool m_modifier_fn { false }; + bool m_modifier_fn_lock { false }; + bool m_modifier_hyper { false }; + bool m_modifier_num_lock { false }; + bool m_modifier_scroll_lock { false }; + bool m_modifier_super { false }; + bool m_modifier_symbol { false }; + bool m_modifier_symbol_lock { false }; double m_movement_x { 0 }; double m_movement_y { 0 }; i16 m_button { 0 }; diff --git a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.idl b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.idl index c81c0ab91b..31c4af90ce 100644 --- a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.idl +++ b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.idl @@ -1,4 +1,4 @@ -#import +#import // https://w3c.github.io/uievents/#mouseevent [Exposed=Window] @@ -31,7 +31,7 @@ interface MouseEvent : UIEvent { // FIXME: readonly attribute EventTarget? relatedTarget; - // FIXME: boolean getModifierState(DOMString keyArg); + boolean getModifierState(DOMString keyArg); }; // https://w3c.github.io/uievents/#idl-mouseeventinit diff --git a/Userland/Libraries/LibWeb/UIEvents/WheelEvent.cpp b/Userland/Libraries/LibWeb/UIEvents/WheelEvent.cpp index 5c9a7564e9..21f428b82a 100644 --- a/Userland/Libraries/LibWeb/UIEvents/WheelEvent.cpp +++ b/Userland/Libraries/LibWeb/UIEvents/WheelEvent.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -14,8 +15,8 @@ namespace Web::UIEvents { JS_DEFINE_ALLOCATOR(WheelEvent); -WheelEvent::WheelEvent(JS::Realm& realm, FlyString const& event_name, WheelEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y, unsigned modifiers) - : MouseEvent(realm, event_name, event_init, page_x, page_y, offset_x, offset_y, modifiers) +WheelEvent::WheelEvent(JS::Realm& realm, FlyString const& event_name, WheelEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y) + : MouseEvent(realm, event_name, event_init, page_x, page_y, offset_x, offset_y) , m_delta_x(event_init.delta_x) , m_delta_y(event_init.delta_y) , m_delta_mode(event_init.delta_mode) @@ -31,14 +32,18 @@ void WheelEvent::initialize(JS::Realm& realm) set_prototype(&Bindings::ensure_web_prototype(realm, "WheelEvent"_fly_string)); } -JS::NonnullGCPtr WheelEvent::create(JS::Realm& realm, FlyString const& event_name, WheelEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y, unsigned modifiers) +JS::NonnullGCPtr WheelEvent::create(JS::Realm& realm, FlyString const& event_name, WheelEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y) { - return realm.heap().allocate(realm, realm, event_name, event_init, page_x, page_y, offset_x, offset_y, modifiers); + return realm.heap().allocate(realm, realm, event_name, event_init, page_x, page_y, offset_x, offset_y); } WebIDL::ExceptionOr> WheelEvent::create_from_platform_event(JS::Realm& realm, FlyString const& event_name, CSSPixelPoint screen, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, double delta_x, double delta_y, unsigned button, unsigned buttons, unsigned modifiers) { WheelEventInit event_init {}; + event_init.ctrl_key = modifiers & Mod_Ctrl; + event_init.shift_key = modifiers & Mod_Shift; + event_init.alt_key = modifiers & Mod_Alt; + event_init.meta_key = modifiers & Mod_Super; event_init.screen_x = screen.x().to_double(); event_init.screen_y = screen.y().to_double(); event_init.client_x = client.x().to_double(); @@ -48,7 +53,7 @@ WebIDL::ExceptionOr> WheelEvent::create_from_platfo event_init.delta_x = delta_x; event_init.delta_y = delta_y; event_init.delta_mode = WheelDeltaMode::DOM_DELTA_PIXEL; - auto event = WheelEvent::create(realm, event_name, event_init, page.x().to_double(), page.y().to_double(), offset.x().to_double(), offset.y().to_double(), modifiers); + auto event = WheelEvent::create(realm, event_name, event_init, page.x().to_double(), page.y().to_double(), offset.x().to_double(), offset.y().to_double()); event->set_is_trusted(true); return event; } diff --git a/Userland/Libraries/LibWeb/UIEvents/WheelEvent.h b/Userland/Libraries/LibWeb/UIEvents/WheelEvent.h index a93f35501d..cc82e20962 100644 --- a/Userland/Libraries/LibWeb/UIEvents/WheelEvent.h +++ b/Userland/Libraries/LibWeb/UIEvents/WheelEvent.h @@ -30,7 +30,7 @@ class WheelEvent final : public MouseEvent { JS_DECLARE_ALLOCATOR(WheelEvent); public: - [[nodiscard]] static JS::NonnullGCPtr create(JS::Realm&, FlyString const& event_name, WheelEventInit const& event_init = {}, double page_x = 0, double page_y = 0, double offset_x = 0, double offset_y = 0, unsigned modifiers = 0); + [[nodiscard]] static JS::NonnullGCPtr create(JS::Realm&, FlyString const& event_name, WheelEventInit const& event_init = {}, double page_x = 0, double page_y = 0, double offset_x = 0, double offset_y = 0); static WebIDL::ExceptionOr> create_from_platform_event(JS::Realm&, FlyString const& event_name, CSSPixelPoint screen, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, double delta_x, double delta_y, unsigned button, unsigned buttons, unsigned modifiers); virtual ~WheelEvent() override; @@ -41,7 +41,7 @@ public: unsigned long delta_mode() const { return to_underlying(m_delta_mode); } private: - WheelEvent(JS::Realm&, FlyString const& event_name, WheelEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y, unsigned modifiers); + WheelEvent(JS::Realm&, FlyString const& event_name, WheelEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y); virtual void initialize(JS::Realm&) override;