chromium/fuchsia_web/webengine/browser/frame_window_tree_host.cc

// 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_);
}