chromium/ui/ozone/platform/flatland/flatland_window.h

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_OZONE_PLATFORM_FLATLAND_FLATLAND_WINDOW_H_
#define UI_OZONE_PLATFORM_FLATLAND_FLATLAND_WINDOW_H_

#include <fidl/fuchsia.ui.input3/cpp/fidl.h>
#include <fuchsia/element/cpp/fidl.h>
#include <fuchsia/ui/composition/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>

#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/component_export.h"
#include "base/fuchsia/fidl_event_handler.h"
#include "base/functional/callback.h"
#include "ui/base/ime/fuchsia/keyboard_client.h"
#include "ui/events/fuchsia/input_event_sink.h"
#include "ui/events/fuchsia/pointer_events_handler.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/flatland/flatland_connection.h"
#include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_delegate.h"
#include "ui/platform_window/platform_window_init_properties.h"

namespace ui {

class FlatlandWindowManager;
class ScenicWindowDelegate;

class COMPONENT_EXPORT(OZONE) FlatlandWindow : public PlatformWindow,
                                               public InputEventSink {
 public:
  // Both |window_manager| and |delegate| must outlive the FlatlandWindow.
  // ViewCreationToken is passed to Flatland to attach it to the scene graph.
  // ViewrefPair will be associated with this window's View, and used to
  // identify it when calling out to other services (e.g. the SemanticsManager).
  FlatlandWindow(FlatlandWindowManager* window_manager,
                 PlatformWindowDelegate* platform_window_delegate,
                 PlatformWindowInitProperties properties);
  ~FlatlandWindow() override;
  FlatlandWindow(const FlatlandWindow&) = delete;
  FlatlandWindow& operator=(const FlatlandWindow&) = delete;

  void ResetSurfaceContent();

  // Embeds the Flatland identified by |token| into the scene graph.
  void AttachSurfaceContent(fuchsia::ui::views::ViewportCreationToken token);

  // Returns a ViewRef associated with this window.
  fuchsia::ui::views::ViewRef CloneViewRef();

  // Used by OzonePlatformFlatland to determine whether to enable on-screen
  // keyboard features when creating the InputMethod for the window.
  bool virtual_keyboard_enabled() const { return is_virtual_keyboard_enabled_; }

  // Test only PlatformWindow implementation.
  gfx::Rect GetBoundsInPixels() const override;
  void SetBoundsInPixels(const gfx::Rect& bounds) override;
  gfx::Rect GetBoundsInDIP() const override;
  void SetBoundsInDIP(const gfx::Rect& bounds) override;

  // PlatformWindow implementation.
  void SetTitle(const std::u16string& title) override;
  void Show(bool inactive) override;
  void Hide() override;
  void Close() override;
  bool IsVisible() const override;
  void PrepareForShutdown() override;
  void SetCapture() override;
  void ReleaseCapture() override;
  bool HasCapture() const override;
  void SetFullscreen(bool fullscreen, int64_t target_display_id) override;
  void Maximize() override;
  void Minimize() override;
  void Restore() override;
  PlatformWindowState GetPlatformWindowState() const override;
  void Activate() override;
  void Deactivate() override;
  void SetUseNativeFrame(bool use_native_frame) override;
  bool ShouldUseNativeFrame() const override;
  void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
  void MoveCursorTo(const gfx::Point& location) override;
  void ConfineCursorToBounds(const gfx::Rect& bounds) override;
  void SetRestoredBoundsInDIP(const gfx::Rect& bounds) override;
  gfx::Rect GetRestoredBoundsInDIP() const override;
  void SetWindowIcons(const gfx::ImageSkia& window_icon,
                      const gfx::ImageSkia& app_icon) override;
  void SizeConstraintsChanged() override;

 private:
  friend class FlatlandWindowTest;

  // Hanging gets from |parent_viewport_watcher_|.
  void OnGetLayout(fuchsia::ui::composition::LayoutInfo info);
  void OnGetStatus(fuchsia::ui::composition::ParentViewportStatus status);

  // Hanging gets from |view_ref_focused_|.
  void OnViewRefFocusedWatchResult(fuchsia::ui::views::FocusState focus_state);

  // Called from link callbacks to handle view properties and metrics
  // changes.
  void OnViewAttachedChanged(bool is_view_attached);

  // InputEventSink implementation.
  void DispatchEvent(ui::Event* event) override;

  void UpdateSize();

  void OnFlatlandError(fuchsia::ui::composition::FlatlandError error);
  void OnViewControllerDisconnected(zx_status_t status);

  FlatlandWindowManager* const manager_;
  PlatformWindowDelegate* const platform_window_delegate_;
  ScenicWindowDelegate* const scenic_window_delegate_;
  gfx::AcceleratedWidget const window_id_;

  fidl::Client<fuchsia_ui_input3::Keyboard> keyboard_fidl_client_;
  base::FidlErrorEventLogger<fuchsia_ui_input3::Keyboard>
      fidl_error_event_logger_;
  std::unique_ptr<KeyboardClient> keyboard_client_;
  std::unique_ptr<PointerEventsHandler> pointer_handler_;

  // Handle to a kernel object which identifies this window's View
  // across the system. ViewRef consumers can access the handle by
  // calling CloneViewRef().
  fuchsia::ui::views::ViewRef view_ref_;

  // Used to coordinate window closure requests with the shell.
  fuchsia::element::ViewControllerPtr view_controller_;

  // Flatland session used for all drawing operations in this View and safely
  // queueing Present() operations.
  FlatlandConnection flatland_;

  fuchsia::ui::composition::TransformId root_transform_id_;
  fuchsia::ui::composition::TransformId surface_transform_id_;
  fuchsia::ui::composition::TransformId shield_transform_id_;

  fuchsia::ui::composition::ContentId surface_content_id_;

  // Pending Viewport creation callback waiting on |logical_size_|.
  base::OnceClosure pending_attach_surface_content_closure_;

  fuchsia::ui::composition::ParentViewportWatcherPtr parent_viewport_watcher_;

  // Protocol for watching focus changes.
  fuchsia::ui::views::ViewRefFocusedPtr view_ref_focused_;

  // Flatland View size in logical pixels.
  std::optional<gfx::Size> logical_size_;

  // The scale between logical pixels and physical pixels, set based on the
  // fuchsia::ui::composition::LayoutInfo. It's used to calculate dimensions of
  // the view in physical pixels in UpdateSize(). This value doesn't affect the
  // device_scale_factor reported by FlatlandScreen for the corresponding
  // display (currently always 1.0, see crbug.com/1215330).
  float device_pixel_ratio_ = 1.f;

  // Current view size in DIPs.
  gfx::SizeF size_dips_;

  // Current view size in device pixels. The size is set to
  // |PlatformWindowInitProperties.bounds.size()| value until
  // |parent_viewport_watcher_| is bound and returns OnGetLayout().
  gfx::Rect bounds_;

  // The offsets between the edges and the visible rectangle of the View, set
  // based on fuchsia::ui::composition::LayoutInfo. Used to set
  // `bounds_.system_ui_overlap` in `UpdateSize()`.
  gfx::Insets view_inset_;

  // False if the View for this window is detached from the View tree, in which
  // case it is definitely not visible.
  bool is_visible_ = false;

  // True if the View occupies the full screen.
  bool is_fullscreen_ = false;

  // True if the on-screen virtual keyboard is available for this window.
  bool is_virtual_keyboard_enabled_ = false;

  // True if |view_| is currently attached to a scene.
  bool is_view_attached_ = false;

  // True if SetCapture() was called. Currently does not reflect capture state
  // in Scenic.
  bool has_capture_ = false;
};

}  // namespace ui

#endif  // UI_OZONE_PLATFORM_FLATLAND_FLATLAND_WINDOW_H_