summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp3
-rw-r--r--Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h3
-rw-r--r--Userland/Libraries/LibWeb/CMakeLists.txt1
-rw-r--r--Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.h47
-rw-r--r--Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.idl13
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.cpp40
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.h6
-rw-r--r--Userland/Libraries/LibWeb/DOM/Window.cpp4
-rw-r--r--Userland/Libraries/LibWeb/Forward.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp5
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]