diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/UIEvents/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibWeb/UIEvents/BUILD.gn index 3526c39fe13c..5b39283cc32e 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/UIEvents/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/UIEvents/BUILD.gn @@ -5,6 +5,7 @@ source_set("UIEvents") { "//Userland/", # For LibGUI needing WindowServer types ] sources = [ + "CompositionEvent.cpp", "EventNames.cpp", "FocusEvent.cpp", "InputEvent.cpp", diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni index 30b96ea03bf3..dbc18da8d88a 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni @@ -306,6 +306,7 @@ standard_idl_files = [ "//Userland/Libraries/LibWeb/SVG/SVGTransformList.idl", "//Userland/Libraries/LibWeb/SVG/SVGTSpanElement.idl", "//Userland/Libraries/LibWeb/SVG/SVGUseElement.idl", + "//Userland/Libraries/LibWeb/UIEvents/CompositionEvent.idl", "//Userland/Libraries/LibWeb/UIEvents/FocusEvent.idl", "//Userland/Libraries/LibWeb/UIEvents/InputEvent.idl", "//Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.idl", diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index a2bc3f88bf3d..c5da0ec2bb4f 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -51,6 +51,7 @@ Clipboard CloseEvent CloseWatcher Comment +CompositionEvent CountQueuingStrategy Crypto CryptoKey diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index fdf4a2292c3a..ab771105efe3 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -666,6 +666,7 @@ set(SOURCES SVG/TagNames.cpp SVG/ViewBox.cpp Selection/Selection.cpp + UIEvents/CompositionEvent.cpp UIEvents/EventNames.cpp UIEvents/FocusEvent.cpp UIEvents/InputEvent.cpp diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index d322505c91c6..1fa25f596e36 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -120,6 +120,7 @@ #include #include #include +#include #include #include #include @@ -1678,7 +1679,7 @@ WebIDL::ExceptionOr> Document::create_event(StringView i if (Infra::is_ascii_case_insensitive_match(interface, "beforeunloadevent"sv)) { event = Event::create(realm, FlyString {}); // FIXME: Create BeforeUnloadEvent } else if (Infra::is_ascii_case_insensitive_match(interface, "compositionevent"sv)) { - event = Event::create(realm, FlyString {}); // FIXME: Create CompositionEvent + event = UIEvents::CompositionEvent::create(realm, String {}); } else if (Infra::is_ascii_case_insensitive_match(interface, "customevent"sv)) { event = CustomEvent::create(realm, FlyString {}); } else if (Infra::is_ascii_case_insensitive_match(interface, "devicemotionevent"sv)) { @@ -1708,7 +1709,7 @@ WebIDL::ExceptionOr> Document::create_event(StringView i } else if (Infra::is_ascii_case_insensitive_match(interface, "svgevents"sv)) { event = Event::create(realm, FlyString {}); } else if (Infra::is_ascii_case_insensitive_match(interface, "textevent"sv)) { - event = Event::create(realm, FlyString {}); // FIXME: Create CompositionEvent + event = Event::create(realm, FlyString {}); // FIXME: Create TextEvent } else if (Infra::is_ascii_case_insensitive_match(interface, "touchevent"sv)) { event = Event::create(realm, FlyString {}); // FIXME: Create TouchEvent } else if (Infra::is_ascii_case_insensitive_match(interface, "uievent"sv) diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 43bb402b7a10..c83b3561e322 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -684,6 +684,7 @@ class SVGTitleElement; } namespace Web::UIEvents { +class CompositionEvent; class InputEvent; class KeyboardEvent; class MouseEvent; diff --git a/Userland/Libraries/LibWeb/UIEvents/CompositionEvent.cpp b/Userland/Libraries/LibWeb/UIEvents/CompositionEvent.cpp new file mode 100644 index 000000000000..4409ccf88e37 --- /dev/null +++ b/Userland/Libraries/LibWeb/UIEvents/CompositionEvent.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024, Jamie Mansfield + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Web::UIEvents { + +JS_DEFINE_ALLOCATOR(CompositionEvent); + +JS::NonnullGCPtr CompositionEvent::create(JS::Realm& realm, FlyString const& event_name, CompositionEventInit const& event_init) +{ + return realm.heap().allocate(realm, realm, event_name, event_init); +} + +WebIDL::ExceptionOr> CompositionEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, CompositionEventInit const& event_init) +{ + return realm.heap().allocate(realm, realm, event_name, event_init); +} + +CompositionEvent::CompositionEvent(JS::Realm& realm, FlyString const& event_name, CompositionEventInit const& event_init) + : UIEvent(realm, event_name, event_init) + , m_data(event_init.data) +{ +} + +CompositionEvent::~CompositionEvent() = default; + +void CompositionEvent::initialize(JS::Realm& realm) +{ + Base::initialize(realm); + WEB_SET_PROTOTYPE_FOR_INTERFACE(CompositionEvent); +} + +// https://w3c.github.io/uievents/#dom-compositionevent-initcompositionevent +void CompositionEvent::init_composition_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& data) +{ + // Initializes attributes of a CompositionEvent object. This method has the same behavior as UIEvent.initUIEvent(). + // The value of detail remains undefined. + + // 1. If this’s dispatch flag is set, then return. + if (dispatched()) + return; + + // 2. Initialize this with type, bubbles, and cancelable. + initialize_event(type, bubbles, cancelable); + + // Implementation Defined: Initialise other values. + m_view = view; + m_data = data; +} + +} diff --git a/Userland/Libraries/LibWeb/UIEvents/CompositionEvent.h b/Userland/Libraries/LibWeb/UIEvents/CompositionEvent.h new file mode 100644 index 000000000000..ce16a87a3104 --- /dev/null +++ b/Userland/Libraries/LibWeb/UIEvents/CompositionEvent.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024, Jamie Mansfield + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::UIEvents { + +struct CompositionEventInit : public UIEventInit { + String data; +}; + +class CompositionEvent final : public UIEvent { + WEB_PLATFORM_OBJECT(CompositionEvent, UIEvent); + JS_DECLARE_ALLOCATOR(CompositionEvent); + +public: + [[nodiscard]] static JS::NonnullGCPtr create(JS::Realm&, FlyString const& event_name, CompositionEventInit const& = {}); + static WebIDL::ExceptionOr> construct_impl(JS::Realm&, FlyString const& event_name, CompositionEventInit const& event_init); + + virtual ~CompositionEvent() override; + + // https://w3c.github.io/uievents/#dom-compositionevent-data + String data() const { return m_data; } + + void init_composition_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& data); + +private: + CompositionEvent(JS::Realm&, FlyString const& event_name, CompositionEventInit const&); + + virtual void initialize(JS::Realm&) override; + + String m_data; +}; + +} diff --git a/Userland/Libraries/LibWeb/UIEvents/CompositionEvent.idl b/Userland/Libraries/LibWeb/UIEvents/CompositionEvent.idl new file mode 100644 index 000000000000..cbb147ee996f --- /dev/null +++ b/Userland/Libraries/LibWeb/UIEvents/CompositionEvent.idl @@ -0,0 +1,17 @@ +#import + +// https://w3c.github.io/uievents/#compositionevent +[Exposed=Window] +interface CompositionEvent : UIEvent { + constructor(DOMString type, optional CompositionEventInit eventInitDict = {}); + readonly attribute USVString data; + + // https://w3c.github.io/uievents/#dom-compositionevent-initcompositionevent + // FIXME: The spec uses WindowProxy rather than Window (spec bug?). + undefined initCompositionEvent(DOMString typeArg, optional boolean bubblesArg = false, optional boolean cancelableArg = false, optional Window? viewArg = null, optional DOMString dataArg = ""); +}; + +// https://w3c.github.io/uievents/#dictdef-compositioneventinit +dictionary CompositionEventInit : UIEventInit { + DOMString data = ""; +}; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 8af2b9231add..203c6216025c 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -296,6 +296,7 @@ libweb_js_bindings(SVG/SVGTransformList) libweb_js_bindings(SVG/SVGTSpanElement) libweb_js_bindings(SVG/SVGUseElement) libweb_js_bindings(Selection/Selection) +libweb_js_bindings(UIEvents/CompositionEvent) libweb_js_bindings(UIEvents/FocusEvent) libweb_js_bindings(UIEvents/InputEvent) libweb_js_bindings(UIEvents/KeyboardEvent)