diff --git a/Libraries/LibWeb/Page/EventHandler.cpp b/Libraries/LibWeb/Page/EventHandler.cpp index d25f436e09c..e64658b93c9 100644 --- a/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Libraries/LibWeb/Page/EventHandler.cpp @@ -1068,6 +1068,18 @@ static bool produces_character_value(u32 code_point) || Unicode::code_point_has_symbol_general_category(code_point); } +// https://github.com/w3c/uievents/issues/183#issuecomment-448091687 +static bool is_enter_key_or_interoperable_enter_key_combo(UIEvents::KeyCode key, u32 modifiers) +{ + if (key != UIEvents::KeyCode::Key_Return) + return false; + if (!modifiers) + return true; + if (modifiers & (UIEvents::KeyModifier::Mod_Shift | UIEvents::KeyModifier::Mod_Ctrl)) + return true; + return false; +} + EventResult EventHandler::input_event(FlyString const& event_name, FlyString const& input_type, HTML::Navigable& navigable, u32 code_point) { auto document = navigable.active_document(); @@ -1115,7 +1127,10 @@ EventResult EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u // https://w3c.github.io/uievents/#event-type-keypress // If supported by a user agent, this event MUST be dispatched when a key is pressed down, if and only if that key // normally produces a character value. - if (produces_character_value(code_point)) { + // AD-HOC: For web compat and for interop with other engines, we make an exception here for the Enter key. See: + // https://github.com/w3c/uievents/issues/183#issuecomment-448091687 and + // https://github.com/w3c/uievents/issues/266#issuecomment-1887917756 + if (produces_character_value(code_point) || is_enter_key_or_interoperable_enter_key_combo(key, modifiers)) { dispatch_result = fire_keyboard_event(UIEvents::EventNames::keypress, m_navigable, key, modifiers, code_point, repeat); if (dispatch_result != EventResult::Accepted) return dispatch_result; diff --git a/Tests/LibWeb/Text/expected/UIEvents/KeyEvent-keypress.txt b/Tests/LibWeb/Text/expected/UIEvents/KeyEvent-keypress.txt index 4d4617ea838..5c74fa59aeb 100644 --- a/Tests/LibWeb/Text/expected/UIEvents/KeyEvent-keypress.txt +++ b/Tests/LibWeb/Text/expected/UIEvents/KeyEvent-keypress.txt @@ -3,3 +3,12 @@ keypress key=A charCode=65 keydown key=Shift charCode=0 keydown key=B charCode=0 keypress key=B charCode=66 +keydown key=Enter charCode=0 +keypress key=Enter charCode=0 +keydown key=Enter charCode=0 modifiers=Alt +keydown key=Enter charCode=0 modifiers=Control +keypress key=Enter charCode=0 modifiers=Control +keydown key=Enter charCode=0 modifiers=Shift +keypress key=Enter charCode=0 modifiers=Shift +keydown key=Enter charCode=0 +keydown key=Enter charCode=0 diff --git a/Tests/LibWeb/Text/input/UIEvents/KeyEvent-keypress.html b/Tests/LibWeb/Text/input/UIEvents/KeyEvent-keypress.html index 459f2cf66b0..4653c2259e7 100644 --- a/Tests/LibWeb/Text/input/UIEvents/KeyEvent-keypress.html +++ b/Tests/LibWeb/Text/input/UIEvents/KeyEvent-keypress.html @@ -4,15 +4,39 @@ test(() => { let input = document.getElementById("input"); + const modifierKeys = ['Alt', 'Control', 'Shift', 'Super', 'NumLock']; input.addEventListener("keydown", e => { - println(`keydown key=${e.key} charCode=${e.charCode}`); + const activeModifiers = modifierKeys.filter(modifier => e.getModifierState(modifier)); + if (activeModifiers.length > 0) { + println(`keydown key=${e.key} charCode=${e.charCode} modifiers=${activeModifiers.join(', ')}`); + } else { + println(`keydown key=${e.key} charCode=${e.charCode}`); + } }); input.addEventListener("keypress", e => { - println(`keypress key=${e.key} charCode=${e.charCode}`); + const activeModifiers = modifierKeys.filter(modifier => e.getModifierState(modifier)); + if (activeModifiers.length > 0) { + println(`keypress key=${e.key} charCode=${e.charCode} modifiers=${activeModifiers.join(', ')}`); + } else { + println(`keypress key=${e.key} charCode=${e.charCode}`); + } }); internals.sendText(input, "A"); internals.sendKey(input, "LeftShift"); internals.sendText(input, "B"); + + internals.sendKey(input, "Return"); + + let modifiers = 1 << 0; // Mod_Alt + internals.sendKey(input, "Return", modifiers); + modifiers = 1 << 1; // Mod_Ctrl + internals.sendKey(input, "Return", modifiers); + modifiers = 1 << 2; // Mod_Shift + internals.sendKey(input, "Return", modifiers); + modifiers = 1 << 3; // Mod_Super + internals.sendKey(input, "Return", modifiers); + modifiers = 1 << 4; // Mod_Keypad + internals.sendKey(input, "Return", modifiers); });