diff options
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.h | 47 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.idl | 13 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.cpp | 40 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.h | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Window.cpp | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Forward.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp | 5 |
10 files changed, 122 insertions, 2 deletions
diff --git a/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp b/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp index cefc244352..c7d4a067b9 100644 --- a/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp +++ b/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp @@ -10,6 +10,7 @@ #include <LibWeb/Bindings/EventWrapper.h> #include <LibWeb/Bindings/EventWrapperFactory.h> #include <LibWeb/Bindings/KeyboardEventWrapper.h> +#include <LibWeb/Bindings/MediaQueryListEventWrapper.h> #include <LibWeb/Bindings/MessageEventWrapper.h> #include <LibWeb/Bindings/MouseEventWrapper.h> #include <LibWeb/Bindings/PageTransitionEventWrapper.h> @@ -22,6 +23,8 @@ EventWrapper* wrap(JS::GlobalObject& global_object, DOM::Event& event) { if (is<DOM::CustomEvent>(event)) return static_cast<CustomEventWrapper*>(wrap_impl(global_object, static_cast<DOM::CustomEvent&>(event))); + if (is<CSS::MediaQueryListEvent>(event)) + return static_cast<MediaQueryListEventWrapper*>(wrap_impl(global_object, static_cast<CSS::MediaQueryListEvent&>(event))); if (is<HTML::CloseEvent>(event)) return static_cast<CloseEventWrapper*>(wrap_impl(global_object, static_cast<HTML::CloseEvent&>(event))); if (is<HTML::MessageEvent>(event)) diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h index 6f13e48230..2ecdfbb0fb 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h @@ -204,6 +204,8 @@ #include <LibWeb/Bindings/ImageDataConstructor.h> #include <LibWeb/Bindings/ImageDataPrototype.h> #include <LibWeb/Bindings/MediaQueryListConstructor.h> +#include <LibWeb/Bindings/MediaQueryListEventConstructor.h> +#include <LibWeb/Bindings/MediaQueryListEventPrototype.h> #include <LibWeb/Bindings/MediaQueryListPrototype.h> #include <LibWeb/Bindings/MessageChannelConstructor.h> #include <LibWeb/Bindings/MessageChannelPrototype.h> @@ -371,6 +373,7 @@ ADD_WINDOW_OBJECT_INTERFACE(HTMLVideoElement) \ ADD_WINDOW_OBJECT_INTERFACE(ImageData) \ ADD_WINDOW_OBJECT_INTERFACE(MediaQueryList) \ + ADD_WINDOW_OBJECT_INTERFACE(MediaQueryListEvent) \ ADD_WINDOW_OBJECT_INTERFACE(MessageChannel) \ ADD_WINDOW_OBJECT_INTERFACE(MessageEvent) \ ADD_WINDOW_OBJECT_INTERFACE(MouseEvent) \ diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 066755a9dd..9fca241964 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -354,6 +354,7 @@ libweb_js_wrapper(CSS/CSSStyleDeclaration) libweb_js_wrapper(CSS/CSSStyleRule) libweb_js_wrapper(CSS/CSSStyleSheet) libweb_js_wrapper(CSS/MediaQueryList) +libweb_js_wrapper(CSS/MediaQueryListEvent) libweb_js_wrapper(CSS/Screen) libweb_js_wrapper(CSS/StyleSheet) libweb_js_wrapper(CSS/StyleSheetList) diff --git a/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.h b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.h new file mode 100644 index 0000000000..b15089497b --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibWeb/DOM/Event.h> + +namespace Web::CSS { + +struct MediaQueryListEventInit : public DOM::EventInit { + String media { "" }; + bool matches { false }; +}; + +class MediaQueryListEvent : public DOM::Event { +public: + using WrapperType = Bindings::MediaQueryListEventWrapper; + + static NonnullRefPtr<MediaQueryListEvent> create(FlyString const& event_name, MediaQueryListEventInit const& event_init = {}) + { + return adopt_ref(*new MediaQueryListEvent(event_name, event_init)); + } + static NonnullRefPtr<MediaQueryListEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, MediaQueryListEventInit const& event_init) + { + return MediaQueryListEvent::create(event_name, event_init); + } + + virtual ~MediaQueryListEvent() override = default; + + String const& media() const { return m_media; } + bool matches() const { return m_matches; } + +protected: + MediaQueryListEvent(FlyString const& event_name, MediaQueryListEventInit const& event_init) + : DOM::Event(event_name, event_init) + , m_media(event_init.media) + , m_matches(event_init.matches) + { + } + + String m_media; + bool m_matches; +}; +} diff --git a/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.idl b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.idl new file mode 100644 index 0000000000..7ea6ae1963 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.idl @@ -0,0 +1,13 @@ +#import <DOM/Event.idl> + +interface MediaQueryListEvent : Event { + constructor(CSSOMString type, optional MediaQueryListEventInit eventInitDict = {}); + + readonly attribute CSSOMString media; + readonly attribute boolean matches; +}; + +dictionary MediaQueryListEventInit : EventInit { + CSSOMString media = ""; + boolean matches = false; +}; diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index cdff35cc2d..93e5eadb74 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -2,6 +2,7 @@ * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> * Copyright (c) 2021, Linus Groh <linusg@serenityos.org> * Copyright (c) 2021, Luke Wilde <lukew@serenityos.org> + * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -15,6 +16,7 @@ #include <LibJS/Runtime/FunctionObject.h> #include <LibWeb/Bindings/MainThreadVM.h> #include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/CSS/MediaQueryListEvent.h> #include <LibWeb/CSS/StyleComputer.h> #include <LibWeb/Cookie/ParsedCookie.h> #include <LibWeb/DOM/Comment.h> @@ -1105,4 +1107,42 @@ void Document::run_the_resize_steps() update_layout(); } +void Document::add_media_query_list(NonnullRefPtr<CSS::MediaQueryList>& media_query_list) +{ + m_media_query_lists.append(media_query_list); +} + +// https://drafts.csswg.org/cssom-view/#evaluate-media-queries-and-report-changes +void Document::evaluate_media_queries_and_report_changes() +{ + // NOTE: Not in the spec, but we take this opportunity to prune null WeakPtrs. + m_media_query_lists.remove_all_matching([](auto& it) { + return it.is_null(); + }); + + // 1. For each MediaQueryList object target that has doc as its document, + // in the order they were created, oldest first, run these substeps: + for (auto& media_query_list_ptr : m_media_query_lists) { + // 1.1. If target’s matches state has changed since the last time these steps + // were run, fire an event at target using the MediaQueryListEvent constructor, + // with its type attribute initialized to change, its isTrusted attribute + // initialized to true, its media attribute initialized to target’s media, + // and its matches attribute initialized to target’s matches state. + if (media_query_list_ptr.is_null()) + continue; + auto media_query_list = media_query_list_ptr.strong_ref(); + bool did_match = media_query_list->matches(); + bool now_matches = media_query_list->evaluate(); + + if (did_match != now_matches) { + CSS::MediaQueryListEventInit init; + init.media = media_query_list->media(); + init.matches = now_matches; + auto event = CSS::MediaQueryListEvent::create(HTML::EventNames::change, init); + event->set_is_trusted(true); + media_query_list->dispatch_event(event); + } + } +} + } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index b871c0e813..c78908f15e 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -303,6 +303,9 @@ public: void run_the_resize_steps(); + void evaluate_media_queries_and_report_changes(); + void add_media_query_list(NonnullRefPtr<CSS::MediaQueryList>&); + private: explicit Document(const AK::URL&); @@ -393,6 +396,9 @@ private: // Used by run_the_resize_steps(). Gfx::IntSize m_last_viewport_size; + + // Used by evaluate_media_queries_and_report_changes(). + Vector<WeakPtr<CSS::MediaQueryList>> m_media_query_lists; }; } diff --git a/Userland/Libraries/LibWeb/DOM/Window.cpp b/Userland/Libraries/LibWeb/DOM/Window.cpp index 0c48fb471f..8c2d1f7a74 100644 --- a/Userland/Libraries/LibWeb/DOM/Window.cpp +++ b/Userland/Libraries/LibWeb/DOM/Window.cpp @@ -285,7 +285,9 @@ NonnullRefPtr<CSS::CSSStyleDeclaration> Window::get_computed_style(DOM::Element& NonnullRefPtr<CSS::MediaQueryList> Window::match_media(String media) { - return CSS::MediaQueryList::create(associated_document(), parse_media_query_list(CSS::ParsingContext(associated_document()), media)); + auto media_query_list = CSS::MediaQueryList::create(associated_document(), parse_media_query_list(CSS::ParsingContext(associated_document()), media)); + associated_document().add_media_query_list(media_query_list); + return media_query_list; } RefPtr<CSS::StyleValue> Window::query_media_feature(FlyString const& name) const diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 1a7c2e43e6..6fc6fd757d 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -31,6 +31,7 @@ class Length; class MediaList; class MediaQuery; class MediaQueryList; +class MediaQueryListEvent; class PropertyOwningCSSStyleDeclaration; class Screen; class Selector; @@ -375,6 +376,7 @@ class ImageDataWrapper; class KeyboardEventWrapper; class LocationObject; class MediaQueryListWrapper; +class MediaQueryListEventWrapper; class MessageChannelWrapper; class MessageEventWrapper; class MessagePortWrapper; diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp index 129ff9174c..1fd5acfb18 100644 --- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp +++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp @@ -164,7 +164,10 @@ void EventLoop::process() // FIXME: 8. For each fully active Document in docs, run the scroll steps for that Document, passing in now as the timestamp. [CSSOMVIEW] - // FIXME: 9. For each fully active Document in docs, evaluate media queries and report changes for that Document, passing in now as the timestamp. [CSSOMVIEW] + // 9. For each fully active Document in docs, evaluate media queries and report changes for that Document, passing in now as the timestamp. [CSSOMVIEW] + for_each_fully_active_document_in_docs([&](DOM::Document& document) { + document.evaluate_media_queries_and_report_changes(); + }); // FIXME: 10. For each fully active Document in docs, update animations and send events for that Document, passing in now as the timestamp. [WEBANIMATIONS] |