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();