summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-09-19 20:50:33 +0200
committerAndreas Kling <kling@serenityos.org>2022-09-20 10:32:14 +0200
commitd4acdac3175da4edf0ca88c246a9e58307e3eefd (patch)
treec56fc149669558ce170029bf2aabdcfa64513c32 /Userland/Libraries
parent5908873b45ecf6dd43411b7df55701576b8e63a6 (diff)
downloadserenity-d4acdac3175da4edf0ca88c246a9e58307e3eefd.zip
LibWeb+WebContent+Browser: Plumb visibility state from GUI to web pages
OOPWV now reacts to show/hide events and informs LibWeb about the state change. This makes visibilitychange events fire when switching tabs. :^)
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.cpp33
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.h8
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp51
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContext.h8
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp6
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/VisibilityState.h16
-rw-r--r--Userland/Libraries/LibWebView/OutOfProcessWebView.cpp10
-rw-r--r--Userland/Libraries/LibWebView/OutOfProcessWebView.h2
9 files changed, 125 insertions, 11 deletions
diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp
index 35b6444e34..8397ef9e93 100644
--- a/Userland/Libraries/LibWeb/DOM/Document.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Document.cpp
@@ -647,6 +647,8 @@ void Document::set_title(String const& title)
void Document::attach_to_browsing_context(Badge<HTML::BrowsingContext>, HTML::BrowsingContext& browsing_context)
{
m_browsing_context = browsing_context;
+
+ update_the_visibility_state(browsing_context.system_visibility_state());
}
void Document::detach_from_browsing_context(Badge<HTML::BrowsingContext>, HTML::BrowsingContext& browsing_context)
@@ -1587,11 +1589,17 @@ bool Document::hidden() const
// https://html.spec.whatwg.org/multipage/interaction.html#dom-document-visibilitystate
String Document::visibility_state() const
{
- return m_visibility_state;
+ switch (m_visibility_state) {
+ case HTML::VisibilityState::Hidden:
+ return "hidden"sv;
+ case HTML::VisibilityState::Visible:
+ return "visible"sv;
+ }
+ VERIFY_NOT_REACHED();
}
// https://html.spec.whatwg.org/multipage/interaction.html#update-the-visibility-state
-void Document::update_the_visibility_state(String visibility_state)
+void Document::update_the_visibility_state(HTML::VisibilityState visibility_state)
{
// 1. If document's visibility state equals visibilityState, then return.
if (m_visibility_state == visibility_state)
@@ -1985,4 +1993,25 @@ HTML::PolicyContainer Document::policy_container() const
return m_policy_container;
}
+// https://html.spec.whatwg.org/multipage/browsers.html#list-of-the-descendant-browsing-contexts
+Vector<NonnullRefPtr<HTML::BrowsingContext>> Document::list_of_descendant_browsing_contexts() const
+{
+ // 1. Let list be an empty list.
+ Vector<NonnullRefPtr<HTML::BrowsingContext>> list;
+
+ // 2. For each browsing context container container,
+ // whose nested browsing context is non-null and whose shadow-including root is d, in shadow-including tree order:
+
+ // NOTE: We already store our browsing contexts in a tree structure, so we can simply collect all the descendants
+ // of this document's browsing context.
+ if (browsing_context()) {
+ browsing_context()->for_each_in_subtree([&](auto& context) {
+ list.append(context);
+ return IterationDecision::Continue;
+ });
+ }
+
+ return list;
+}
+
}
diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h
index 8be46b9dc1..230d810f71 100644
--- a/Userland/Libraries/LibWeb/DOM/Document.h
+++ b/Userland/Libraries/LibWeb/DOM/Document.h
@@ -31,6 +31,7 @@
#include <LibWeb/HTML/Origin.h>
#include <LibWeb/HTML/SandboxingFlagSet.h>
#include <LibWeb/HTML/Scripting/Environments.h>
+#include <LibWeb/HTML/VisibilityState.h>
#include <LibWeb/HTML/Window.h>
namespace Web::DOM {
@@ -319,7 +320,7 @@ public:
String visibility_state() const;
// https://html.spec.whatwg.org/multipage/interaction.html#update-the-visibility-state
- void update_the_visibility_state(String visibility_state);
+ void update_the_visibility_state(HTML::VisibilityState);
void run_the_resize_steps();
void run_the_scroll_steps();
@@ -382,6 +383,9 @@ public:
// https://html.spec.whatwg.org/multipage/dom.html#concept-document-policy-container
HTML::PolicyContainer policy_container() const;
+ // https://html.spec.whatwg.org/multipage/browsers.html#list-of-the-descendant-browsing-contexts
+ Vector<NonnullRefPtr<HTML::BrowsingContext>> list_of_descendant_browsing_contexts() const;
+
protected:
virtual void visit_edges(Cell::Visitor&) override;
@@ -527,7 +531,7 @@ private:
HTML::PolicyContainer m_policy_container;
// https://html.spec.whatwg.org/multipage/interaction.html#visibility-state
- String m_visibility_state { "hidden" };
+ HTML::VisibilityState m_visibility_state { HTML::VisibilityState::Hidden };
};
}
diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp
index cb0e82e47b..f25f38c466 100644
--- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp
+++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp
@@ -1113,7 +1113,7 @@ DOM::ExceptionOr<void> BrowsingContext::traverse_the_history(size_t entry_index,
new_document->set_page_showing(true);
// 3. Update the visibility state of newDocument to "hidden".
- new_document->update_the_visibility_state("hidden");
+ new_document->update_the_visibility_state(VisibilityState::Hidden);
// 4. Fire a page transition event named pageshow at newDocument's relevant global object with true.
auto& window = verify_cast<HTML::Window>(relevant_global_object(*new_document));
@@ -1248,18 +1248,55 @@ BrowsingContext const* BrowsingContext::the_one_permitted_sandboxed_navigator()
}
// https://html.spec.whatwg.org/multipage/browsers.html#document-family
-bool BrowsingContext::document_family_contains(DOM::Document const& document) const
+Vector<JS::Handle<DOM::Document>> BrowsingContext::document_family() const
{
- HashTable<DOM::Document const*> family;
-
+ HashTable<DOM::Document*> documents;
for (auto& entry : m_session_history) {
if (!entry.document)
continue;
- if (family.set(entry.document) == AK::HashSetResult::ReplacedExistingEntry)
+ if (documents.set(entry.document.ptr()) == AK::HashSetResult::ReplacedExistingEntry)
continue;
- // FIXME: The document family of a Document object consists of the union of all the document families of the browsing contexts in the list of the descendant browsing contexts of the Document object.
+ for (auto& context : entry.document->list_of_descendant_browsing_contexts()) {
+ for (auto& document : context->document_family()) {
+ documents.set(document.ptr());
+ }
+ }
+ }
+
+ Vector<JS::Handle<DOM::Document>> family;
+ for (auto* document : documents) {
+ family.append(*document);
}
+ return family;
+}
+
+// https://html.spec.whatwg.org/multipage/browsers.html#document-family
+bool BrowsingContext::document_family_contains(DOM::Document const& document) const
+{
+ return document_family().first_matching([&](auto& entry) { return entry.ptr() == &document; }).has_value();
+}
+
+VisibilityState BrowsingContext::system_visibility_state() const
+{
+ return m_system_visibility_state;
+}
- return family.contains(&document);
+// https://html.spec.whatwg.org/multipage/interaction.html#system-visibility-state
+void BrowsingContext::set_system_visibility_state(VisibilityState visibility_state)
+{
+ if (m_system_visibility_state == visibility_state)
+ return;
+ m_system_visibility_state = visibility_state;
+
+ // When a user-agent determines that the system visibility state for top-level browsing context context
+ // has changed to newState, it must queue a task on the user interaction task source to update
+ // the visibility state of all the Document objects in the top-level browsing context's document family with newState.
+ auto document_family = top_level_browsing_context().document_family();
+ queue_global_task(Task::Source::UserInteraction, Bindings::main_thread_vm().current_realm()->global_object(), [visibility_state, document_family = move(document_family)]() mutable {
+ for (auto& document : document_family) {
+ document->update_the_visibility_state(visibility_state);
+ }
+ });
}
+
}
diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h
index ac841455b2..05c986f636 100644
--- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h
+++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h
@@ -18,6 +18,7 @@
#include <LibWeb/HTML/HistoryHandlingBehavior.h>
#include <LibWeb/HTML/Origin.h>
#include <LibWeb/HTML/SessionHistoryEntry.h>
+#include <LibWeb/HTML/VisibilityState.h>
#include <LibWeb/Loader/FrameLoader.h>
#include <LibWeb/Page/EventHandler.h>
#include <LibWeb/Platform/Timer.h>
@@ -158,8 +159,12 @@ public:
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#traverse-the-history
DOM::ExceptionOr<void> traverse_the_history(size_t entry_index, HistoryHandlingBehavior = HistoryHandlingBehavior::Default, bool explicit_history_navigation = false);
+ Vector<JS::Handle<DOM::Document>> document_family() const;
bool document_family_contains(DOM::Document const&) const;
+ VisibilityState system_visibility_state() const;
+ void set_system_visibility_state(VisibilityState);
+
private:
explicit BrowsingContext(Page&, HTML::BrowsingContextContainer*);
@@ -205,6 +210,9 @@ private:
// https://html.spec.whatwg.org/multipage/browsers.html#tlbc-group
RefPtr<BrowsingContextGroup> m_group;
+
+ // https://html.spec.whatwg.org/multipage/interaction.html#system-visibility-state
+ VisibilityState m_system_visibility_state { VisibilityState::Hidden };
};
HTML::Origin determine_the_origin(BrowsingContext const& browsing_context, Optional<AK::URL> url, SandboxingFlagSet sandbox_flags, Optional<HTML::Origin> invocation_origin);
diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp
index 52ad2f8abf..48ed8132a4 100644
--- a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp
+++ b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp
@@ -18,6 +18,12 @@
namespace Web::HTML {
+HashTable<BrowsingContextContainer*>& BrowsingContextContainer::all_instances()
+{
+ static HashTable<BrowsingContextContainer*> set;
+ return set;
+}
+
BrowsingContextContainer::BrowsingContextContainer(DOM::Document& document, DOM::QualifiedName qualified_name)
: HTMLElement(document, move(qualified_name))
{
diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h
index 7009a3867a..f1b14c246a 100644
--- a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h
+++ b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h
@@ -16,6 +16,8 @@ class BrowsingContextContainer : public HTMLElement {
public:
virtual ~BrowsingContextContainer() override;
+ static HashTable<BrowsingContextContainer*>& all_instances();
+
BrowsingContext* nested_browsing_context() { return m_nested_browsing_context; }
BrowsingContext const* nested_browsing_context() const { return m_nested_browsing_context; }
diff --git a/Userland/Libraries/LibWeb/HTML/VisibilityState.h b/Userland/Libraries/LibWeb/HTML/VisibilityState.h
new file mode 100644
index 0000000000..002f893748
--- /dev/null
+++ b/Userland/Libraries/LibWeb/HTML/VisibilityState.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+namespace Web::HTML {
+
+enum VisibilityState {
+ Hidden,
+ Visible,
+};
+
+}
diff --git a/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp b/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp
index 88bb329817..4ece205b89 100644
--- a/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp
+++ b/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp
@@ -540,4 +540,14 @@ void OutOfProcessWebView::focusout_event(GUI::FocusEvent&)
client().async_set_has_focus(false);
}
+void OutOfProcessWebView::show_event(GUI::ShowEvent&)
+{
+ client().async_set_system_visibility_state(true);
+}
+
+void OutOfProcessWebView::hide_event(GUI::HideEvent&)
+{
+ client().async_set_system_visibility_state(false);
+}
+
}
diff --git a/Userland/Libraries/LibWebView/OutOfProcessWebView.h b/Userland/Libraries/LibWebView/OutOfProcessWebView.h
index 2132fbf290..d5990d8ebb 100644
--- a/Userland/Libraries/LibWebView/OutOfProcessWebView.h
+++ b/Userland/Libraries/LibWebView/OutOfProcessWebView.h
@@ -131,6 +131,8 @@ private:
virtual void screen_rects_change_event(GUI::ScreenRectsChangeEvent&) override;
virtual void focusin_event(GUI::FocusEvent&) override;
virtual void focusout_event(GUI::FocusEvent&) override;
+ virtual void show_event(GUI::ShowEvent&) override;
+ virtual void hide_event(GUI::HideEvent&) override;
// ^AbstractScrollableWidget
virtual void did_scroll() override;