LibWeb: Implement requestFullscreen algorithm
The required functionality to exit fullscreen will be in a followup commit.
This commit is contained in:
parent
44e0735d9b
commit
bc17805b2b
16 changed files with 345 additions and 9 deletions
|
|
@ -559,8 +559,7 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla
|
|||
return focused_area && element.is_inclusive_ancestor_of(*focused_area);
|
||||
}
|
||||
case CSS::PseudoClass::Fullscreen: {
|
||||
// FIXME: Add fullscreen support
|
||||
return false;
|
||||
return element.is_fullscreen_element();
|
||||
}
|
||||
case CSS::PseudoClass::FirstChild:
|
||||
if (context.collect_per_element_selector_involvement_metadata) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
* Copyright (c) 2021-2026, Sam Atkins <sam@ladybird.org>
|
||||
* Copyright (c) 2024, Matthew Olsson <mattco@serenityos.org>
|
||||
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
|
||||
* Copyright (c) 2025, Simon Farre <simon.farre.cx@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
|
@ -6797,6 +6798,95 @@ void Document::append_pending_fullscreen_change(PendingFullscreenEvent::Type typ
|
|||
m_pending_fullscreen_events.append(PendingFullscreenEvent { type, element });
|
||||
}
|
||||
|
||||
// https://fullscreen.spec.whatwg.org/#fullscreen-an-element
|
||||
void Document::fullscreen_element_within_doc(GC::Ref<Element> element)
|
||||
{
|
||||
auto const get_hide_until = [&](auto const& popover_list) {
|
||||
return HTML::HTMLElement::topmost_popover_ancestor(element, popover_list, nullptr, HTML::IsPopover::No);
|
||||
};
|
||||
|
||||
// 1. Let hideUntil be the result of running topmost popover ancestor given
|
||||
// element, null, and false.
|
||||
auto hide_until = get_hide_until(showing_hint_popover_list());
|
||||
|
||||
// Finding topmost popover ancestor algorithm takes different parameters than those
|
||||
// described by the fullscreen spec. Since the new algorithm takes 4 parameters, with the new "popover list"
|
||||
// we must also account for the auto popover list.
|
||||
// More can be read about this "spec bug" in https://github.com/whatwg/fullscreen/issues/245
|
||||
if (hide_until == nullptr)
|
||||
hide_until = get_hide_until(showing_auto_popover_list());
|
||||
|
||||
// Our hide_all_popovers_until takes a variant. topmost_popover_ancestor produces a Ptr<HTMLElement>
|
||||
Variant<GC::Ptr<HTML::HTMLElement>, GC::Ptr<Document>> hide_until_argument { hide_until };
|
||||
|
||||
// 2. If hideUntil is null, then set hideUntil to element’s node document.
|
||||
if (hide_until == nullptr)
|
||||
hide_until_argument = element->owner_document();
|
||||
|
||||
// 3. Run hide all popovers until given hideUntil, false, and true.
|
||||
HTML::HTMLElement::hide_all_popovers_until(hide_until_argument, HTML::FocusPreviousElement::No, HTML::FireEvents::Yes);
|
||||
|
||||
// 4. Set element’s fullscreen flag.
|
||||
element->set_fullscreen_flag(true);
|
||||
|
||||
// 5. Remove from the top layer immediately given element.
|
||||
remove_an_element_from_the_top_layer_immediately(element);
|
||||
|
||||
// 6. Add to the top layer given element.
|
||||
add_an_element_to_the_top_layer(element);
|
||||
element->invalidate_style(StyleInvalidationReason::Fullscreen);
|
||||
}
|
||||
|
||||
// https://fullscreen.spec.whatwg.org/#fullscreen-element
|
||||
GC::Ptr<Element> Document::fullscreen_element() const
|
||||
{
|
||||
// All documents have an associated fullscreen element. The fullscreen element is the topmost element in the
|
||||
// document’s top layer whose fullscreen flag is set, if any, and null otherwise.
|
||||
for (auto const& el : top_layer_elements().in_reverse()) {
|
||||
if (el->is_fullscreen_element())
|
||||
return el;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// https://fullscreen.spec.whatwg.org/#dom-document-fullscreenelement
|
||||
GC::Ptr<Element> Document::fullscreen_element_for_bindings() const
|
||||
{
|
||||
GC::Ptr<Element> fullscreen_element = this->fullscreen_element();
|
||||
|
||||
if (!fullscreen_element) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 1. If this is a shadow root and its host is not connected, then return null.
|
||||
// Note: We're not a shadow root. See ShadowRoot::fullscreen_element_for_bindings() instead.
|
||||
// 2. Let candidate be the result of retargeting fullscreen element against this.
|
||||
auto* candidate = retarget(fullscreen_element.ptr(), const_cast<Document*>(this));
|
||||
if (!candidate) {
|
||||
return nullptr;
|
||||
}
|
||||
// 3. If candidate and this are in the same tree, then return candidate.
|
||||
if (auto* retargeted_element = as<Element>(candidate); retargeted_element && &retargeted_element->root() == &root()) {
|
||||
return retargeted_element;
|
||||
}
|
||||
// 4. Return null.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// https://fullscreen.spec.whatwg.org/#dom-document-fullscreen
|
||||
bool Document::fullscreen() const
|
||||
{
|
||||
// The fullscreen getter steps are to return false if this's fullscreen element is null, and true otherwise.
|
||||
return fullscreen_element() != nullptr;
|
||||
}
|
||||
|
||||
// https://fullscreen.spec.whatwg.org/#dom-document-fullscreenenabled
|
||||
bool Document::fullscreen_enabled() const
|
||||
{
|
||||
// FIXME: Implement check policy check and "is supported" check.
|
||||
return is_allowed_to_use_feature(PolicyControlledFeature::Fullscreen);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#document-allow-declarative-shadow-roots
|
||||
void Document::set_allow_declarative_shadow_roots(bool allow)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -977,6 +977,13 @@ public:
|
|||
void run_fullscreen_steps();
|
||||
void append_pending_fullscreen_change(PendingFullscreenEvent::Type type, GC::Ref<Element> element);
|
||||
|
||||
void fullscreen_element_within_doc(GC::Ref<Element> element);
|
||||
GC::Ptr<Element> fullscreen_element() const;
|
||||
GC::Ptr<Element> fullscreen_element_for_bindings() const;
|
||||
|
||||
bool fullscreen() const;
|
||||
bool fullscreen_enabled() const;
|
||||
|
||||
auto& script_blocking_style_sheet_set() { return m_script_blocking_style_sheet_set; }
|
||||
auto const& script_blocking_style_sheet_set() const { return m_script_blocking_style_sheet_set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#import <CSS/StyleSheetList.idl>
|
||||
#import <Fullscreen/DocumentOrShadowRootExtensions.idl>
|
||||
|
||||
// https://dom.spec.whatwg.org/#documentorshadowroot
|
||||
interface mixin DocumentOrShadowRoot {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2024, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2022-2023, Sam Atkins <atkinssj@serenityos.org>
|
||||
* Copyright (c) 2025, Simon Farre <simon.farre.cx@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
|
@ -61,9 +62,11 @@
|
|||
#include <LibWeb/HTML/HTMLBaseElement.h>
|
||||
#include <LibWeb/HTML/HTMLBodyElement.h>
|
||||
#include <LibWeb/HTML/HTMLButtonElement.h>
|
||||
#include <LibWeb/HTML/HTMLDialogElement.h>
|
||||
#include <LibWeb/HTML/HTMLFieldSetElement.h>
|
||||
#include <LibWeb/HTML/HTMLFrameSetElement.h>
|
||||
#include <LibWeb/HTML/HTMLHtmlElement.h>
|
||||
#include <LibWeb/HTML/HTMLIFrameElement.h>
|
||||
#include <LibWeb/HTML/HTMLInputElement.h>
|
||||
#include <LibWeb/HTML/HTMLLIElement.h>
|
||||
#include <LibWeb/HTML/HTMLMenuElement.h>
|
||||
|
|
@ -95,12 +98,15 @@
|
|||
#include <LibWeb/Layout/ListItemBox.h>
|
||||
#include <LibWeb/Layout/TreeBuilder.h>
|
||||
#include <LibWeb/Layout/Viewport.h>
|
||||
#include <LibWeb/MathML/MathMLElement.h>
|
||||
#include <LibWeb/MathML/TagNames.h>
|
||||
#include <LibWeb/Namespace.h>
|
||||
#include <LibWeb/Page/Page.h>
|
||||
#include <LibWeb/Painting/AccumulatedVisualContext.h>
|
||||
#include <LibWeb/Painting/PaintableBox.h>
|
||||
#include <LibWeb/Painting/StackingContext.h>
|
||||
#include <LibWeb/Painting/ViewportPaintable.h>
|
||||
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||
#include <LibWeb/SVG/SVGAElement.h>
|
||||
#include <LibWeb/Selection/Selection.h>
|
||||
#include <LibWeb/TrustedTypes/RequireTrustedTypesForDirective.h>
|
||||
|
|
@ -2419,6 +2425,186 @@ WebIDL::ExceptionOr<void> Element::insert_adjacent_html(String const& position,
|
|||
return {};
|
||||
}
|
||||
|
||||
// Used to signal what message should be shown when the promise for the algorithm rejects..
|
||||
enum class RequestFullscreenError : u8 {
|
||||
False,
|
||||
ElementReadyCheckFailed,
|
||||
UnsupportedElement,
|
||||
NoTransientUserActivation,
|
||||
ElementNodeDocIsNotPendingDoc
|
||||
};
|
||||
|
||||
static constexpr String to_string(RequestFullscreenError error)
|
||||
{
|
||||
switch (error) {
|
||||
// This should never be called with this value
|
||||
case RequestFullscreenError::False:
|
||||
return "false"_string;
|
||||
case RequestFullscreenError::ElementReadyCheckFailed:
|
||||
return "Element ready check failed"_string;
|
||||
case RequestFullscreenError::UnsupportedElement:
|
||||
return "Not supported element"_string;
|
||||
case RequestFullscreenError::NoTransientUserActivation:
|
||||
return "No transient user activation available to consume"_string;
|
||||
case RequestFullscreenError::ElementNodeDocIsNotPendingDoc:
|
||||
return "Element's node document is not pending doc"_string;
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
// step 5 of requestFullscreen:
|
||||
// 5. If any of conditions are false, set error to true
|
||||
static RequestFullscreenError fullscreen_has_error_check(Element const& element)
|
||||
{
|
||||
// This’s namespace is the HTML namespace or this is an SVG svg or MathML math element. [SVG] [MATHML]
|
||||
// FIXME: This likely wants to use is<MathML::MathMLMathElement> instead.
|
||||
if (!(element.namespace_uri() == Namespace::HTML || element.is_svg_svg_element() || (is<MathML::MathMLElement>(element) && element.tag_name() == MathML::TagNames::math)))
|
||||
return RequestFullscreenError::UnsupportedElement;
|
||||
|
||||
// This is not a dialog element
|
||||
if (is<HTML::HTMLDialogElement>(element))
|
||||
return RequestFullscreenError::UnsupportedElement;
|
||||
|
||||
// The fullscreen element ready check for this returns true.
|
||||
if (!element.element_ready_check())
|
||||
return RequestFullscreenError::ElementReadyCheckFailed;
|
||||
// FIXME: Implement 'Fullscreen is supported.' check
|
||||
|
||||
// This’s relevant global object has transient activation or
|
||||
// FIXME: the algorithm is triggered by a user generated orientation change.
|
||||
auto* window = as<HTML::Window>(&HTML::relevant_global_object(element));
|
||||
if (!window->has_transient_activation())
|
||||
return RequestFullscreenError::NoTransientUserActivation;
|
||||
|
||||
return RequestFullscreenError::False;
|
||||
}
|
||||
|
||||
// https://fullscreen.spec.whatwg.org/#fullscreen-element-ready-check
|
||||
bool Element::element_ready_check() const
|
||||
{
|
||||
// A fullscreen element ready check for an element element returns true if all of the following are true, and false otherwise:
|
||||
|
||||
// element is connected.
|
||||
if (!is_connected())
|
||||
return false;
|
||||
|
||||
// element’s node document is allowed to use the "fullscreen" feature.
|
||||
if (!m_document->is_allowed_to_use_feature(PolicyControlledFeature::Fullscreen))
|
||||
return false;
|
||||
|
||||
// element namespace is not the HTML namespace or element’s popover visibility state is hidden.
|
||||
if (namespace_uri() != Namespace::HTML)
|
||||
return true;
|
||||
|
||||
auto const* html_element = as_if<HTML::HTMLElement>(this);
|
||||
return html_element ? (html_element->popover_visibility_state() == HTML::HTMLElement::PopoverVisibilityState::Hidden) : false;
|
||||
}
|
||||
|
||||
// https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen
|
||||
GC::Ref<WebIDL::Promise> Element::request_fullscreen()
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
|
||||
// 1. Let pendingDoc be this’s node document.
|
||||
auto pending_doc = m_document;
|
||||
|
||||
// 2. Let promise be a new promise.
|
||||
auto promise = WebIDL::create_promise(realm);
|
||||
|
||||
// 3. If pendingDoc is not fully active, then reject promise with a TypeError exception and return promise.
|
||||
if (!pending_doc->is_fully_active()) {
|
||||
WebIDL::reject_promise(realm, promise, JS::TypeError::create(realm, "Document not fully active."_string));
|
||||
return promise;
|
||||
}
|
||||
|
||||
// 4. Let error be false.
|
||||
// 5. If any of conditions are false, set error to true
|
||||
auto error = fullscreen_has_error_check(*this);
|
||||
|
||||
// 6. If error is false, then consume user activation given pendingDoc’s relevant global object.
|
||||
if (error == RequestFullscreenError::False) {
|
||||
auto& relevant_global = as<HTML::Window>(relevant_global_object(*pending_doc));
|
||||
relevant_global.consume_user_activation();
|
||||
}
|
||||
|
||||
// 7. Return promise, and run the remaining steps in parallel.
|
||||
Platform::EventLoopPlugin::the().deferred_invoke(GC::create_function(heap(), [&realm, error, pending_doc, requesting_element = GC::Ref { *this }, promise]() mutable {
|
||||
HTML::TemporaryExecutionContext context(realm, HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
|
||||
// N.B: Fullscreen API is affected by site-isolation and will require additional work once site-isolation is implemented.
|
||||
|
||||
// 8. If error is false, then resize pendingDoc’s node navigable’s top-level traversable’s
|
||||
// active document’s viewport’s dimensions FIXME: optionally taking into account options["navigationUI"]:
|
||||
if (error == RequestFullscreenError::False)
|
||||
pending_doc->page().client().page_did_request_fullscreen_window();
|
||||
|
||||
// 9. If any of the following conditions are false, then set error to true:
|
||||
// This’s node document is pendingDoc.
|
||||
// The fullscreen element ready check for this returns true.
|
||||
if (pending_doc != requesting_element->owner_document())
|
||||
error = RequestFullscreenError::ElementNodeDocIsNotPendingDoc;
|
||||
if (!requesting_element->element_ready_check())
|
||||
error = RequestFullscreenError::ElementReadyCheckFailed;
|
||||
|
||||
// 10. If error is true:
|
||||
// Append (fullscreenerror, this) to pendingDoc’s list of pending fullscreen events.
|
||||
// Reject promise with a TypeError exception and terminate these steps.
|
||||
if (error != RequestFullscreenError::False) {
|
||||
pending_doc->append_pending_fullscreen_change(PendingFullscreenEvent::Type::Error, requesting_element);
|
||||
WebIDL::reject_promise(realm, promise, JS::TypeError::create(realm, to_string(error)));
|
||||
return;
|
||||
}
|
||||
|
||||
// 11. Let fullscreenElements be an ordered set initially consisting of this.
|
||||
auto fullscreen_elements = realm.heap().allocate<GC::HeapVector<GC::Ref<Element>>>();
|
||||
fullscreen_elements->elements().append(requesting_element);
|
||||
|
||||
// 12. While true:
|
||||
while (true) {
|
||||
// 1. Let last be the last item of fullscreenElements.
|
||||
auto last = fullscreen_elements->elements().last();
|
||||
|
||||
// 2. Let container be last’s node navigable’s container.
|
||||
auto container = last->navigable()->container();
|
||||
|
||||
// 3. If container is null, then break.
|
||||
if (!container)
|
||||
break;
|
||||
|
||||
// 4. Append container to fullscreenElements.
|
||||
fullscreen_elements->elements().append(*container);
|
||||
}
|
||||
|
||||
// 13. For each element in fullscreenElements:
|
||||
for (auto& element : fullscreen_elements->elements()) {
|
||||
// 1. Let doc be element’s node document.
|
||||
auto& doc = element->document();
|
||||
|
||||
// 2. If element is doc’s fullscreen element, continue.
|
||||
if (doc.fullscreen_element() == element) {
|
||||
// Spec note: No need to notify observers when nothing has changed.
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3. If element is this and this is an iframe element, then set element’s iframe fullscreen flag.
|
||||
if (element == requesting_element && requesting_element->is_html_iframe_element()) {
|
||||
auto& iframe_element = static_cast<HTML::HTMLIFrameElement&>(*element);
|
||||
iframe_element.set_iframe_fullscreen_flag(true);
|
||||
}
|
||||
|
||||
// 4. Fullscreen element within doc.
|
||||
doc.fullscreen_element_within_doc(element);
|
||||
|
||||
// 5. Append (fullscreenchange, element) to doc’s list of pending fullscreen events.
|
||||
doc.append_pending_fullscreen_change(PendingFullscreenEvent::Type::Change, element);
|
||||
}
|
||||
|
||||
// 14. Resolve promise with undefined
|
||||
WebIDL::resolve_promise(realm, promise, JS::js_undefined());
|
||||
}));
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
GC::Ptr<WebIDL::CallbackType> Element::onfullscreenchange()
|
||||
{
|
||||
return event_handler_attribute(HTML::EventNames::fullscreenchange);
|
||||
|
|
|
|||
|
|
@ -262,6 +262,13 @@ public:
|
|||
|
||||
WebIDL::ExceptionOr<void> insert_adjacent_html(String const& position, TrustedTypes::TrustedHTMLOrString const&);
|
||||
|
||||
bool element_ready_check() const;
|
||||
GC::Ref<WebIDL::Promise> request_fullscreen();
|
||||
void removing_steps_fullscreen();
|
||||
|
||||
void set_fullscreen_flag(bool is_fullscreen) { m_fullscreen_flag = is_fullscreen; }
|
||||
bool is_fullscreen_element() const { return m_fullscreen_flag; }
|
||||
|
||||
GC::Ptr<WebIDL::CallbackType> onfullscreenchange();
|
||||
void set_onfullscreenchange(GC::Ptr<WebIDL::CallbackType>);
|
||||
|
||||
|
|
@ -659,6 +666,7 @@ private:
|
|||
bool m_affected_by_sibling_position_or_count_pseudo_class : 1 { false };
|
||||
bool m_affected_by_nth_child_pseudo_class : 1 { false };
|
||||
bool m_affected_by_has_pseudo_class_with_relative_selector_that_has_sibling_combinator : 1 { false };
|
||||
bool m_fullscreen_flag : 1 { false };
|
||||
|
||||
size_t m_sibling_invalidation_distance { 0 };
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <LibWeb/DOM/Event.h>
|
||||
#include <LibWeb/DOM/ShadowRoot.h>
|
||||
#include <LibWeb/DOM/SlotRegistry.h>
|
||||
#include <LibWeb/DOM/Utils.h>
|
||||
#include <LibWeb/HTML/HTMLSlotElement.h>
|
||||
#include <LibWeb/HTML/HTMLTemplateElement.h>
|
||||
#include <LibWeb/HTML/Parser/HTMLParser.h>
|
||||
|
|
@ -40,6 +41,30 @@ void ShadowRoot::finalize()
|
|||
document().unregister_shadow_root({}, *this);
|
||||
}
|
||||
|
||||
// https://fullscreen.spec.whatwg.org/#dom-document-fullscreenelement
|
||||
GC::Ptr<Element> ShadowRoot::fullscreen_element_for_bindings() const
|
||||
{
|
||||
// 1. If this is a shadow root and its host is not connected, then return null.
|
||||
if (!host() || !host()->is_connected())
|
||||
return nullptr;
|
||||
|
||||
// 2. Let candidate be the result of retargeting fullscreen element against this.
|
||||
// Note: ShadowRoot does not have it's own top layer. But the algorithm says to get the fullscreen
|
||||
// element from the top layer, so it's grabbed from this' document.
|
||||
|
||||
auto* candidate = retarget(const_cast<ShadowRoot*>(this)->document().fullscreen_element().ptr(), const_cast<ShadowRoot*>(this));
|
||||
|
||||
if (!candidate)
|
||||
return nullptr;
|
||||
|
||||
// 3. If candidate and this are in the same tree, then return candidate.
|
||||
if (auto* retargeted_element = as<Element>(candidate); &retargeted_element->root() == &root())
|
||||
return retargeted_element;
|
||||
|
||||
// 4. Return null.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ShadowRoot::initialize(JS::Realm& realm)
|
||||
{
|
||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(ShadowRoot);
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@ public:
|
|||
|
||||
virtual void finalize() override;
|
||||
|
||||
GC::Ptr<Element> fullscreen_element_for_bindings() const;
|
||||
|
||||
protected:
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
// https://fullscreen.spec.whatwg.org/#ref-for-document
|
||||
partial interface Document {
|
||||
[LegacyLenientSetter] readonly attribute boolean fullscreenEnabled;
|
||||
[LegacyLenientSetter, Unscopable] readonly attribute boolean fullscreen; // historical
|
||||
|
||||
attribute EventHandler onfullscreenchange;
|
||||
attribute EventHandler onfullscreenerror;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
#import <DOM/Element.idl>
|
||||
|
||||
// https://fullscreen.spec.whatwg.org/#ref-for-documentorshadowroot
|
||||
partial interface mixin DocumentOrShadowRoot {
|
||||
[LegacyLenientSetter, ImplementedAs=fullscreen_element_for_bindings] readonly attribute Element? fullscreenElement;
|
||||
};
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
// https://fullscreen.spec.whatwg.org/#ref-for-element
|
||||
partial interface Element {
|
||||
Promise<undefined> requestFullscreen();
|
||||
|
||||
attribute EventHandler onfullscreenchange;
|
||||
attribute EventHandler onfullscreenerror;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ public:
|
|||
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
void set_iframe_fullscreen_flag(bool iframe_fullscreen_flag) { m_iframe_fullscreen_flag = iframe_fullscreen_flag; }
|
||||
bool iframe_fullscreen_flag() const { return m_iframe_fullscreen_flag; }
|
||||
|
||||
private:
|
||||
HTMLIFrameElement(DOM::Document&, DOM::QualifiedName);
|
||||
|
||||
|
|
@ -68,6 +71,9 @@ private:
|
|||
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#current-navigation-was-lazy-loaded
|
||||
bool m_current_navigation_was_lazy_loaded { false };
|
||||
|
||||
// https://fullscreen.spec.whatwg.org/#iframe-fullscreen-flag
|
||||
bool m_iframe_fullscreen_flag { false };
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#iframe-pending-resource-timing-start-time
|
||||
Optional<HighResolutionTime::DOMHighResTimeStamp> m_pending_resource_start_time = {};
|
||||
|
||||
|
|
|
|||
|
|
@ -687,12 +687,13 @@ void WebContentClient::did_request_minimize_window(u64 page_id)
|
|||
}
|
||||
}
|
||||
|
||||
void WebContentClient::did_request_fullscreen_window(u64 page_id)
|
||||
Messages::WebContentClient::DidRequestFullscreenWindowResponse WebContentClient::did_request_fullscreen_window(u64 page_id)
|
||||
{
|
||||
if (auto view = view_for_page_id(page_id); view.has_value()) {
|
||||
if (view->on_fullscreen_window)
|
||||
view->on_fullscreen_window();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebContentClient::did_request_exit_fullscreen(u64 page_id)
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ private:
|
|||
virtual void did_request_resize_window(u64 page_id, Gfx::IntSize) override;
|
||||
virtual void did_request_maximize_window(u64 page_id) override;
|
||||
virtual void did_request_minimize_window(u64 page_id) override;
|
||||
virtual void did_request_fullscreen_window(u64 page_id) override;
|
||||
virtual Messages::WebContentClient::DidRequestFullscreenWindowResponse did_request_fullscreen_window(u64 page_id) override;
|
||||
virtual void did_request_exit_fullscreen(u64 page_id) override;
|
||||
virtual void did_request_file(u64 page_id, ByteString path, i32) override;
|
||||
virtual void did_request_color_picker(u64 page_id, Color current_color) override;
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ endpoint WebContentClient
|
|||
did_request_resize_window(u64 page_id, Gfx::IntSize size) =|
|
||||
did_request_maximize_window(u64 page_id) =|
|
||||
did_request_minimize_window(u64 page_id) =|
|
||||
did_request_fullscreen_window(u64 page_id) =|
|
||||
did_request_fullscreen_window(u64 page_id) => (bool success)
|
||||
did_request_exit_fullscreen(u64 page_id) =|
|
||||
did_request_file(u64 page_id, ByteString path, i32 request_id) =|
|
||||
did_request_color_picker(u64 page_id, Color current_color) =|
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ Harness status: OK
|
|||
|
||||
Found 17 tests
|
||||
|
||||
14 Pass
|
||||
3 Fail
|
||||
16 Pass
|
||||
1 Fail
|
||||
Pass String attribute setter should throw if this value is invalid
|
||||
Pass String attribute setter should treat no arguments as undefined
|
||||
Pass String attribute setter called with undefined should behave in the same way as no arguments
|
||||
|
|
@ -17,7 +17,7 @@ Pass [Replaceable] setter called with other value should just work
|
|||
Fail [LegacyLenientThis] setter should not throw even if this value is invalid, regardless of the arguments count
|
||||
Pass [LegacyLenientThis] setter should treat no arguments as undefined
|
||||
Pass [LegacyLenientThis] setter called with undefined should behave in the same way as no arguments
|
||||
Fail [LegacyLenientSetter] setter should treat no arguments as undefined
|
||||
Fail [LegacyLenientSetter] setter called with undefined should behave in the same way as no arguments
|
||||
Pass [LegacyLenientSetter] setter should treat no arguments as undefined
|
||||
Pass [LegacyLenientSetter] setter called with undefined should behave in the same way as no arguments
|
||||
Pass [PutForward] setter should treat no arguments as undefined
|
||||
Pass [PutForward] setter called with undefined should behave in the same way as no arguments
|
||||
Loading…
Reference in a new issue