diff --git a/Tests/LibWeb/Text/expected/focus-events.txt b/Tests/LibWeb/Text/expected/focus-events.txt
new file mode 100644
index 0000000000..1fddba0e4c
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/focus-events.txt
@@ -0,0 +1,6 @@
+ focus target=
+focusin target=
+blur target=
+focusout target=
+focus target=
+focusin target=
diff --git a/Tests/LibWeb/Text/input/focus-events.html b/Tests/LibWeb/Text/input/focus-events.html
new file mode 100644
index 0000000000..bfe053e870
--- /dev/null
+++ b/Tests/LibWeb/Text/input/focus-events.html
@@ -0,0 +1,54 @@
+
+
+
+
+
diff --git a/Userland/Libraries/LibWeb/DOM/EventHandler.idl b/Userland/Libraries/LibWeb/DOM/EventHandler.idl
index afdc2d0082..bbdf381925 100644
--- a/Userland/Libraries/LibWeb/DOM/EventHandler.idl
+++ b/Userland/Libraries/LibWeb/DOM/EventHandler.idl
@@ -41,6 +41,8 @@ interface mixin GlobalEventHandlers {
attribute EventHandler onended;
attribute OnErrorEventHandler onerror;
attribute EventHandler onfocus;
+ attribute EventHandler onfocusin;
+ attribute EventHandler onfocusout;
attribute EventHandler onformdata;
attribute EventHandler oninput;
attribute EventHandler oninvalid;
diff --git a/Userland/Libraries/LibWeb/HTML/AttributeNames.h b/Userland/Libraries/LibWeb/HTML/AttributeNames.h
index d26321d555..6bee2a2248 100644
--- a/Userland/Libraries/LibWeb/HTML/AttributeNames.h
+++ b/Userland/Libraries/LibWeb/HTML/AttributeNames.h
@@ -141,6 +141,8 @@ namespace AttributeNames {
__ENUMERATE_HTML_ATTRIBUTE(onended) \
__ENUMERATE_HTML_ATTRIBUTE(onerror) \
__ENUMERATE_HTML_ATTRIBUTE(onfocus) \
+ __ENUMERATE_HTML_ATTRIBUTE(onfocusin) \
+ __ENUMERATE_HTML_ATTRIBUTE(onfocusout) \
__ENUMERATE_HTML_ATTRIBUTE(onformdata) \
__ENUMERATE_HTML_ATTRIBUTE(onhashchange) \
__ENUMERATE_HTML_ATTRIBUTE(oninput) \
diff --git a/Userland/Libraries/LibWeb/HTML/EventNames.h b/Userland/Libraries/LibWeb/HTML/EventNames.h
index bd162483e6..731d22470f 100644
--- a/Userland/Libraries/LibWeb/HTML/EventNames.h
+++ b/Userland/Libraries/LibWeb/HTML/EventNames.h
@@ -51,6 +51,8 @@ namespace Web::HTML::EventNames {
__ENUMERATE_HTML_EVENT(error) \
__ENUMERATE_HTML_EVENT(finish) \
__ENUMERATE_HTML_EVENT(focus) \
+ __ENUMERATE_HTML_EVENT(focusin) \
+ __ENUMERATE_HTML_EVENT(focusout) \
__ENUMERATE_HTML_EVENT(formdata) \
__ENUMERATE_HTML_EVENT(hashchange) \
__ENUMERATE_HTML_EVENT(input) \
diff --git a/Userland/Libraries/LibWeb/HTML/Focus.cpp b/Userland/Libraries/LibWeb/HTML/Focus.cpp
index 12e1d7ef09..7fc25b38d8 100644
--- a/Userland/Libraries/LibWeb/HTML/Focus.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Focus.cpp
@@ -79,6 +79,11 @@ static void run_focus_update_steps(Vector> old_chain, Vect
blur_event->set_related_target(related_blur_target);
blur_event_target->dispatch_event(blur_event);
}
+
+ auto focusout_event = UIEvents::FocusEvent::create(blur_event_target->realm(), HTML::EventNames::focusout);
+ focusout_event->set_bubbles(true);
+ focusout_event->set_related_target(related_blur_target);
+ blur_event_target->dispatch_event(focusout_event);
}
// FIXME: 3. Apply any relevant platform-specific conventions for focusing new focus target.
@@ -123,6 +128,11 @@ static void run_focus_update_steps(Vector> old_chain, Vect
auto focus_event = UIEvents::FocusEvent::create(focus_event_target->realm(), HTML::EventNames::focus);
focus_event->set_related_target(related_focus_target);
focus_event_target->dispatch_event(focus_event);
+
+ auto focusin_event = UIEvents::FocusEvent::create(focus_event_target->realm(), HTML::EventNames::focusin);
+ focusin_event->set_bubbles(true);
+ focusin_event->set_related_target(related_focus_target);
+ focus_event_target->dispatch_event(focusin_event);
}
}
}
diff --git a/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h b/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h
index 9206c140fb..79e7d48b8b 100644
--- a/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h
+++ b/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h
@@ -34,6 +34,8 @@
E(onended, HTML::EventNames::ended) \
E(onerror, HTML::EventNames::error) \
E(onfocus, HTML::EventNames::focus) \
+ E(onfocusin, HTML::EventNames::focusin) \
+ E(onfocusout, HTML::EventNames::focusout) \
E(onformdata, HTML::EventNames::formdata) \
E(oninput, HTML::EventNames::input) \
E(oninvalid, HTML::EventNames::invalid) \