Commit 288c7ce9 authored by Kevin Marshall's avatar Kevin Marshall Committed by Commit Bot

[fuchsia] Add render size override support to WebEngine.

Allows embedders to specify a virtual resolution used when rendering
web content. Web content will be laid out differently, either
supersampled or subsampled depending on whether the overridden
resolution is smaller or larger relative to the View's native
resolution.

The virtual resolution is then scaled to fit the View.

The GPU surface resolution will remain unaffected; it is the same as
the View's native resolution.

Bug: b/144361044,b/144725868
Change-Id: Iefaa0059235319420dc1e050d33d706c1d96ab18
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1977001
Commit-Queue: Kevin Marshall <kmarshall@chromium.org>
Reviewed-by: default avatarSergey Ulanov <sergeyu@chromium.org>
Reviewed-by: default avatardanakj <danakj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#738457}
parent 0ff6496e
......@@ -20,7 +20,10 @@ fidl_library("cast_fidl") {
"fidl/cast/url_request_rewriter.fidl",
]
public_deps = [ "//third_party/fuchsia-sdk/sdk:fuchsia-web" ]
public_deps = [
"//third_party/fuchsia-sdk/sdk:fuchsia-ui-gfx",
"//third_party/fuchsia-sdk/sdk:fuchsia-web",
]
}
# Used by the top-level "gn_all" target to discover Fuchsia build targets.
......
......@@ -132,6 +132,8 @@ component("web_engine_core") {
"browser/discarding_event_filter.h",
"browser/frame_impl.cc",
"browser/frame_impl.h",
"browser/fuchsia_layout_manager.cc",
"browser/fuchsia_layout_manager.h",
"browser/navigation_controller_impl.cc",
"browser/navigation_controller_impl.h",
"browser/url_request_rewrite_rules_manager.cc",
......
......@@ -4,6 +4,7 @@
#include "fuchsia/engine/browser/frame_impl.h"
#include <fuchsia/ui/gfx/cpp/fidl.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h>
......@@ -27,6 +28,7 @@
#include "fuchsia/base/message_port.h"
#include "fuchsia/engine/browser/accessibility_bridge.h"
#include "fuchsia/engine/browser/context_impl.h"
#include "fuchsia/engine/browser/fuchsia_layout_manager.h"
#include "fuchsia/engine/browser/web_engine_devtools_controller.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/system/platform_handle.h"
......@@ -34,7 +36,6 @@
#include "third_party/blink/public/common/logging/logging_utils.h"
#include "third_party/blink/public/common/messaging/web_message_port.h"
#include "ui/aura/client/window_parenting_client.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host_platform.h"
#include "ui/base/ime/input_method_base.h"
......@@ -64,60 +65,6 @@ class PopupFrameCreationInfoUserData : public base::SupportsUserData::Data {
fuchsia::web::PopupFrameCreationInfo info;
};
// Layout manager used for the root window that hosts the WebContents window.
// The main WebContents window is stretched to occupy the whole parent. Note
// that the root window may host other windows (particularly menus for drop-down
// boxes). These windows get the location and size they request. The main
// window for the web content is identified by window.type() ==
// WINDOW_TYPE_CONTROL (set in WebContentsViewAura).
class LayoutManagerImpl : public aura::LayoutManager {
public:
LayoutManagerImpl() = default;
~LayoutManagerImpl() override = default;
// aura::LayoutManager implementation.
void OnWindowResized() override {
// Resize the child to match the size of the parent.
if (main_child_) {
SetChildBoundsDirect(main_child_,
gfx::Rect(main_child_->parent()->bounds().size()));
}
}
void OnWindowAddedToLayout(aura::Window* child) override {
if (child->type() == aura::client::WINDOW_TYPE_CONTROL) {
DCHECK(!main_child_);
main_child_ = child;
SetChildBoundsDirect(main_child_,
gfx::Rect(main_child_->parent()->bounds().size()));
}
}
void OnWillRemoveWindowFromLayout(aura::Window* child) override {
if (child->type() == aura::client::WINDOW_TYPE_CONTROL) {
DCHECK_EQ(child, main_child_);
main_child_ = nullptr;
}
}
void OnWindowRemovedFromLayout(aura::Window* child) override {}
void OnChildWindowVisibilityChanged(aura::Window* child,
bool visible) override {}
void SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) override {
if (child != main_child_)
SetChildBoundsDirect(child, requested_bounds);
}
private:
// The main window used for the WebContents.
aura::Window* main_child_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(LayoutManagerImpl);
};
class FrameFocusRules : public wm::BaseFocusRules {
public:
FrameFocusRules() = default;
......@@ -791,7 +738,12 @@ void FrameImpl::SetWindowTreeHost(
aura::client::SetFocusClient(root_window(), focus_controller_.get());
wm::SetActivationClient(root_window(), focus_controller_.get());
root_window()->SetLayoutManager(new LayoutManagerImpl());
layout_manager_ = new FuchsiaLayoutManager;
root_window()->SetLayoutManager(layout_manager_); // Transfers ownership.
if (!render_size_override_.IsEmpty())
layout_manager_->ForceContentDimensions(render_size_override_);
root_window()->AddChild(web_contents_->GetNativeView());
web_contents_->GetNativeView()->Show();
......@@ -802,6 +754,27 @@ void FrameImpl::SetMediaSessionId(uint64_t session_id) {
audio_consumer_provider_service_.set_session_id(session_id);
}
void FrameImpl::ForceContentDimensions(
std::unique_ptr<fuchsia::ui::gfx::vec2> web_dips) {
if (!web_dips) {
render_size_override_ = {};
if (layout_manager_)
layout_manager_->ForceContentDimensions({});
return;
}
gfx::Size web_dips_converted(web_dips->x, web_dips->y);
if (web_dips_converted.IsEmpty()) {
LOG(WARNING) << "Rejecting zero-area size for ForceContentDimensions().";
CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS);
return;
}
render_size_override_ = web_dips_converted;
if (layout_manager_)
layout_manager_->ForceContentDimensions(web_dips_converted);
}
void FrameImpl::CloseContents(content::WebContents* source) {
DCHECK_EQ(source, web_contents_.get());
context_->DestroyFrame(this);
......
......@@ -39,6 +39,7 @@ class FromRenderFrameHost;
} // namespace content
class ContextImpl;
class FuchsiaLayoutManager;
// Implementation of fuchsia.web.Frame based on content::WebContents.
class FrameImpl : public fuchsia::web::Frame,
......@@ -164,6 +165,8 @@ class FrameImpl : public fuchsia::web::Frame,
void EnableHeadlessRendering() override;
void DisableHeadlessRendering() override;
void SetMediaSessionId(uint64_t session_id) override;
void ForceContentDimensions(
std::unique_ptr<fuchsia::ui::gfx::vec2> web_dips) override;
// content::WebContentsDelegate implementation.
void CloseContents(content::WebContents* source) override;
......@@ -198,14 +201,18 @@ class FrameImpl : public fuchsia::web::Frame,
const GURL& validated_url) override;
std::unique_ptr<aura::WindowTreeHost> window_tree_host_;
const std::unique_ptr<content::WebContents> web_contents_;
// Dependents of |window_tree_host_|.
std::unique_ptr<wm::FocusController> focus_controller_;
DiscardingEventFilter discarding_event_filter_;
FuchsiaLayoutManager* layout_manager_ = nullptr;
const std::unique_ptr<content::WebContents> web_contents_;
ContextImpl* const context_;
std::unique_ptr<AccessibilityBridge> accessibility_bridge_;
fuchsia::accessibility::semantics::SemanticsManagerPtr
semantics_manager_for_test_;
DiscardingEventFilter discarding_event_filter_;
NavigationControllerImpl navigation_controller_;
logging::LogSeverity log_level_;
std::map<uint64_t, OriginScopedScript> before_load_scripts_;
......@@ -218,6 +225,7 @@ class FrameImpl : public fuchsia::web::Frame,
fuchsia::web::PopupFrameCreationListenerPtr popup_listener_;
std::list<std::unique_ptr<content::WebContents>> pending_popups_;
bool popup_ack_outstanding_ = false;
gfx::Size render_size_override_;
fidl::Binding<fuchsia::web::Frame> binding_;
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "fuchsia/engine/browser/fuchsia_layout_manager.h"
#include "ui/aura/window_tree_host.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/transform.h"
namespace {
// The background color that is shown when the main window does not fully
// fill the View.
constexpr SkColor kLetterboxBackgroundColor = SK_ColorBLACK;
// Returns a scaling factor that will allow |inset| to fit fully inside
// |container| without clipping.
float ProportionalScale(gfx::Size inset, gfx::Size container) {
gfx::SizeF inset_f(inset);
gfx::SizeF container_f(container);
const float container_aspect_ratio =
container_f.width() / container_f.height();
const float inset_aspect_ratio = inset_f.width() / inset_f.height();
if (container_aspect_ratio > inset_aspect_ratio) {
// Height is constraining.
return container_f.height() / inset_f.height();
} else {
// Width is constraining.
return container_f.width() / inset_f.width();
}
}
} // namespace
FuchsiaLayoutManager::FuchsiaLayoutManager() {}
FuchsiaLayoutManager::~FuchsiaLayoutManager() {}
void FuchsiaLayoutManager::ForceContentDimensions(gfx::Size size) {
render_size_override_ = size;
UpdateContentBounds();
}
void FuchsiaLayoutManager::OnWindowResized() {
// Resize the child to match the size of the parent.
UpdateContentBounds();
}
void FuchsiaLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
if (child->type() == aura::client::WINDOW_TYPE_CONTROL) {
DCHECK(!main_child_);
main_child_ = child;
SetChildBoundsDirect(main_child_,
gfx::Rect(main_child_->parent()->bounds().size()));
UpdateContentBounds();
}
}
void FuchsiaLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
if (child->type() == aura::client::WINDOW_TYPE_CONTROL) {
DCHECK_EQ(child, main_child_);
main_child_ = nullptr;
}
}
void FuchsiaLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {}
void FuchsiaLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
bool visible) {}
void FuchsiaLayoutManager::SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) {
if (child != main_child_)
SetChildBoundsDirect(child, requested_bounds);
}
void FuchsiaLayoutManager::UpdateContentBounds() {
if (!main_child_)
return;
const gfx::Size actual_size(main_child_->parent()->bounds().size());
if (render_size_override_.IsEmpty()) {
// Use all of the area available to the View.
SetChildBoundsDirect(main_child_, gfx::Rect(actual_size));
main_child_->SetTransform(gfx::Transform());
return;
}
SetChildBoundsDirect(main_child_, gfx::Rect(render_size_override_));
// Scale the window to fit in the View without clipping.
const float scale = ProportionalScale(render_size_override_, actual_size);
gfx::Transform transform;
transform.Scale(scale, scale);
// Center the window.
const float center_x_offset =
(actual_size.width() - (render_size_override_.width() * scale)) / 2.0;
const float center_y_offset =
(actual_size.height() - (render_size_override_.height() * scale)) / 2.0;
transform.Translate(center_x_offset, center_y_offset);
main_child_->SetTransform(transform);
main_child_->parent()->GetHost()->compositor()->SetBackgroundColor(
kLetterboxBackgroundColor);
}
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FUCHSIA_ENGINE_BROWSER_FUCHSIA_LAYOUT_MANAGER_H_
#define FUCHSIA_ENGINE_BROWSER_FUCHSIA_LAYOUT_MANAGER_H_
#include "base/macros.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/window.h"
// Layout manager used for the root window that hosts the WebContents window.
// The main WebContents window is stretched to occupy the whole parent. Note
// that the root window may host other windows (particularly menus for drop-down
// boxes). These windows get the location and size they request. The main
// window for the web content is identified by window.type() ==
// WINDOW_TYPE_CONTROL (set in WebContentsViewAura).
class FuchsiaLayoutManager : public aura::LayoutManager {
public:
FuchsiaLayoutManager();
~FuchsiaLayoutManager() override;
// Renders web content within a virtual window of a given |size|, which is
// proportionately scaled to fit within the View.
void ForceContentDimensions(gfx::Size size);
private:
// Sizes the main window to fit inside its container.
// Sets the window's internal resolution to |render_size_override_|, if set,
// and adjusts its scaling factor so that it fits inside the container without
// clipping.
void UpdateContentBounds();
// aura::LayoutManager implementation.
void OnWindowResized() override;
void OnWindowAddedToLayout(aura::Window* child) override;
void OnWillRemoveWindowFromLayout(aura::Window* child) override;
void OnWindowRemovedFromLayout(aura::Window* child) override;
void OnChildWindowVisibilityChanged(aura::Window* child,
bool visible) override;
void SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) override;
// The main window used for the WebContents.
aura::Window* main_child_ = nullptr;
gfx::Size render_size_override_;
DISALLOW_COPY_AND_ASSIGN(FuchsiaLayoutManager);
};
#endif // FUCHSIA_ENGINE_BROWSER_FUCHSIA_LAYOUT_MANAGER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment