// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "fuchsia_web/webengine/browser/frame_window_tree_host.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "fuchsia_web/webengine/features.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/client/window_parenting_client.h"
#include "ui/base/ime/input_method.h"
#include "ui/platform_window/platform_window_init_properties.h"
namespace {
fuchsia::ui::views::ViewRef DupViewRef(
const fuchsia::ui::views::ViewRef& view_ref) {
fuchsia::ui::views::ViewRef dup;
zx_status_t status =
view_ref.reference.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup.reference);
ZX_CHECK(status == ZX_OK, status) << "zx_object_duplicate";
return dup;
}
ui::PlatformWindowInitProperties CreatePlatformWindowInitProperties(
ui::ViewRefPair view_ref_pair,
ui::ScenicWindowDelegate* scenic_window_delegate) {
ui::PlatformWindowInitProperties properties;
properties.view_ref_pair = std::move(view_ref_pair);
properties.enable_keyboard =
base::FeatureList::IsEnabled(features::kKeyboardInput);
properties.enable_virtual_keyboard =
base::FeatureList::IsEnabled(features::kVirtualKeyboard);
properties.scenic_window_delegate = scenic_window_delegate;
return properties;
}
} // namespace
class FrameWindowTreeHost::WindowParentingClientImpl
: public aura::client::WindowParentingClient {
public:
explicit WindowParentingClientImpl(aura::Window* root_window)
: root_window_(root_window) {
aura::client::SetWindowParentingClient(root_window_, this);
}
~WindowParentingClientImpl() override {
aura::client::SetWindowParentingClient(root_window_, nullptr);
}
WindowParentingClientImpl(const WindowParentingClientImpl&) = delete;
WindowParentingClientImpl& operator=(const WindowParentingClientImpl&) =
delete;
// WindowParentingClient implementation.
aura::Window* GetDefaultParent(aura::Window* window,
const gfx::Rect& bounds,
const int64_t display_id) override {
return root_window_;
}
private:
aura::Window* root_window_;
};
FrameWindowTreeHost::FrameWindowTreeHost(
fuchsia::ui::views::ViewToken view_token,
ui::ViewRefPair view_ref_pair,
content::WebContents* web_contents,
OnPixelScaleUpdateCallback on_pixel_scale_update)
: view_ref_(DupViewRef(view_ref_pair.view_ref)),
web_contents_(web_contents),
on_pixel_scale_update_(std::move(on_pixel_scale_update)) {
CreateCompositor();
ui::PlatformWindowInitProperties properties =
CreatePlatformWindowInitProperties(std::move(view_ref_pair), this);
properties.view_token = std::move(view_token);
CreateAndSetPlatformWindow(std::move(properties));
window_parenting_client_ =
std::make_unique<WindowParentingClientImpl>(window());
}
FrameWindowTreeHost::FrameWindowTreeHost(
fuchsia::ui::views::ViewCreationToken view_creation_token,
ui::ViewRefPair view_ref_pair,
content::WebContents* web_contents,
OnPixelScaleUpdateCallback on_pixel_scale_update)
: view_ref_(DupViewRef(view_ref_pair.view_ref)),
web_contents_(web_contents),
on_pixel_scale_update_(std::move(on_pixel_scale_update)) {
CreateCompositor();
ui::PlatformWindowInitProperties properties =
CreatePlatformWindowInitProperties(std::move(view_ref_pair), this);
properties.view_creation_token = std::move(view_creation_token);
CreateAndSetPlatformWindow(std::move(properties));
window_parenting_client_ =
std::make_unique<WindowParentingClientImpl>(window());
}
FrameWindowTreeHost::~FrameWindowTreeHost() = default;
fuchsia::ui::views::ViewRef FrameWindowTreeHost::CreateViewRef() {
return DupViewRef(view_ref_);
}
void FrameWindowTreeHost::OnActivationChanged(bool active) {
// Route focus & blur events to the window's focus observer and its
// InputMethod.
if (active) {
aura::client::GetFocusClient(window())->FocusWindow(window());
GetInputMethod()->OnFocus();
} else {
aura::client::GetFocusClient(window())->FocusWindow(nullptr);
GetInputMethod()->OnBlur();
}
}
void FrameWindowTreeHost::OnWindowStateChanged(
ui::PlatformWindowState old_state,
ui::PlatformWindowState new_state) {
// Tell the root aura::Window whether it is shown or hidden.
if (new_state == ui::PlatformWindowState::kMinimized) {
Hide();
web_contents_->WasOccluded();
} else {
Show();
web_contents_->WasShown();
}
}
void FrameWindowTreeHost::OnWindowBoundsChanged(const BoundsChange& bounds) {
aura::WindowTreeHostPlatform::OnBoundsChanged(bounds);
if (web_contents_->GetPrimaryMainFrame()->IsRenderFrameLive()) {
web_contents_->GetPrimaryMainFrame()->GetView()->SetInsets(
bounds.system_ui_overlap);
}
}
void FrameWindowTreeHost::OnScenicPixelScale(ui::PlatformWindow* window,
float scale) {
scenic_pixel_scale_ = scale;
if (on_pixel_scale_update_)
on_pixel_scale_update_.Run(scenic_pixel_scale_);
}