diff --git a/Tests/LibWeb/Text/expected/UIEvents/KeyEvent-keypress.txt b/Tests/LibWeb/Text/expected/UIEvents/KeyEvent-keypress.txt new file mode 100644 index 00000000000..3751d2d2ae5 --- /dev/null +++ b/Tests/LibWeb/Text/expected/UIEvents/KeyEvent-keypress.txt @@ -0,0 +1,5 @@ +keydown A +keypress A +keydown Shift +keydown B +keypress B diff --git a/Tests/LibWeb/Text/input/UIEvents/KeyEvent-keypress.html b/Tests/LibWeb/Text/input/UIEvents/KeyEvent-keypress.html new file mode 100644 index 00000000000..16c3eb6988a --- /dev/null +++ b/Tests/LibWeb/Text/input/UIEvents/KeyEvent-keypress.html @@ -0,0 +1,18 @@ + + + diff --git a/Userland/Libraries/LibUnicode/CharacterTypes.cpp b/Userland/Libraries/LibUnicode/CharacterTypes.cpp index f613137fd64..e96e263447c 100644 --- a/Userland/Libraries/LibUnicode/CharacterTypes.cpp +++ b/Userland/Libraries/LibUnicode/CharacterTypes.cpp @@ -113,6 +113,16 @@ bool code_point_has_control_general_category(u32 code_point) return code_point_has_general_category(code_point, U_CONTROL_CHAR); } +bool code_point_has_letter_general_category(u32 code_point) +{ + return code_point_has_general_category(code_point, GENERAL_CATEGORY_LETTER); +} + +bool code_point_has_number_general_category(u32 code_point) +{ + return code_point_has_general_category(code_point, GENERAL_CATEGORY_NUMBER); +} + bool code_point_has_punctuation_general_category(u32 code_point) { return code_point_has_general_category(code_point, GENERAL_CATEGORY_PUNCTUATION); @@ -128,6 +138,11 @@ bool code_point_has_space_separator_general_category(u32 code_point) return code_point_has_general_category(code_point, U_SPACE_SEPARATOR); } +bool code_point_has_symbol_general_category(u32 code_point) +{ + return code_point_has_general_category(code_point, GENERAL_CATEGORY_SYMBOL); +} + static constexpr Property PROPERTY_ANY = UCHAR_BINARY_LIMIT + 1; static constexpr Property PROPERTY_ASCII = UCHAR_BINARY_LIMIT + 2; static constexpr Property PROPERTY_ASSIGNED = UCHAR_BINARY_LIMIT + 3; diff --git a/Userland/Libraries/LibUnicode/CharacterTypes.h b/Userland/Libraries/LibUnicode/CharacterTypes.h index 8843d012518..84dc8b6992a 100644 --- a/Userland/Libraries/LibUnicode/CharacterTypes.h +++ b/Userland/Libraries/LibUnicode/CharacterTypes.h @@ -18,9 +18,12 @@ Optional general_category_from_string(StringView); bool code_point_has_general_category(u32 code_point, GeneralCategory general_category); bool code_point_has_control_general_category(u32 code_point); +bool code_point_has_letter_general_category(u32 code_point); +bool code_point_has_number_general_category(u32 code_point); bool code_point_has_punctuation_general_category(u32 code_point); bool code_point_has_separator_general_category(u32 code_point); bool code_point_has_space_separator_general_category(u32 code_point); +bool code_point_has_symbol_general_category(u32 code_point); Optional property_from_string(StringView); bool code_point_has_property(u32 code_point, Property property); diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index d50cbb8cbc6..0d82898b20c 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -836,6 +837,18 @@ EventResult EventHandler::fire_keyboard_event(FlyString const& event_name, HTML: return target->dispatch_event(event) ? EventResult::Accepted : EventResult::Cancelled; } +// https://w3c.github.io/uievents/#unicode-character-categories +static bool produces_character_value(u32 code_point) +{ + // A subset of the General Category values that are defined for each Unicode code point. This subset contains all + // the Letter (Ll, Lm, Lo, Lt, Lu), Number (Nd, Nl, No), Punctuation (Pc, Pd, Pe, Pf, Pi, Po, Ps) and Symbol (Sc, + // Sk, Sm, So) category values. + return Unicode::code_point_has_letter_general_category(code_point) + || Unicode::code_point_has_number_general_category(code_point) + || Unicode::code_point_has_punctuation_general_category(code_point) + || Unicode::code_point_has_symbol_general_category(code_point); +} + EventResult EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u32 code_point) { if (!m_navigable->active_document()) @@ -847,10 +860,14 @@ EventResult EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u if (dispatch_result != EventResult::Accepted) return dispatch_result; - // FIXME: Work out and implement the difference between this and keydown. - dispatch_result = fire_keyboard_event(UIEvents::EventNames::keypress, m_navigable, key, modifiers, code_point); - if (dispatch_result != EventResult::Accepted) - return dispatch_result; + // 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)) { + dispatch_result = fire_keyboard_event(UIEvents::EventNames::keypress, m_navigable, key, modifiers, code_point); + if (dispatch_result != EventResult::Accepted) + return dispatch_result; + } JS::NonnullGCPtr document = *m_navigable->active_document();