// Copyright (c) 2012 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 UI_AURA_WINDOW_TREE_HOST_H_
#define UI_AURA_WINDOW_TREE_HOST_H_

#include <stdint.h>

#include <memory>
#include <string>

#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "ui/aura/aura_export.h"
#include "ui/aura/window.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/ime/input_method_delegate.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/display/display_observer.h"
#include "ui/events/event_source.h"
#include "ui/events/platform_event.h"
#include "ui/gfx/native_widget_types.h"

namespace gfx {
class Point;
class Rect;
class Size;
class Transform;
}

namespace ui {
class Compositor;
enum class DomCode;
class EventSink;
class InputMethod;
class ViewProp;
struct PlatformWindowInitProperties;
}

namespace aura {

namespace test {
class WindowTreeHostTestApi;
}

class Env;
class ScopedKeyboardHook;
class WindowEventDispatcher;
class WindowTreeHostObserver;

// WindowTreeHost bridges between a native window and the embedded RootWindow.
// It provides the accelerated widget and maps events from the native os to
// aura.
class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate,
                                   public ui::EventSource,
                                   public display::DisplayObserver,
                                   public ui::CompositorObserver {
 public:
  ~WindowTreeHost() override;

  // Creates a new WindowTreeHost with the specified |properties| and an
  // optional |env|. If |env| is null, the default Env::GetInstance() is used.
  static std::unique_ptr<WindowTreeHost> Create(
      ui::PlatformWindowInitProperties properties,
      Env* env = nullptr);

  // Returns the WindowTreeHost for the specified accelerated widget, or NULL
  // if there is none associated.
  static WindowTreeHost* GetForAcceleratedWidget(gfx::AcceleratedWidget widget);

  void InitHost();

  void AddObserver(WindowTreeHostObserver* observer);
  void RemoveObserver(WindowTreeHostObserver* observer);
  bool HasObserver(const WindowTreeHostObserver* observer) const;

  Window* window() { return window_; }
  const Window* window() const { return window_; }

  // TODO(msw): Remove this, callers should use GetEventSink().
  ui::EventSink* event_sink();

  WindowEventDispatcher* dispatcher() {
    return const_cast<WindowEventDispatcher*>(
        const_cast<const WindowTreeHost*>(this)->dispatcher());
  }
  const WindowEventDispatcher* dispatcher() const { return dispatcher_.get(); }

  ui::Compositor* compositor() { return compositor_.get(); }

  base::WeakPtr<WindowTreeHost> GetWeakPtr();

  // Gets/Sets the root window's transform.
  virtual gfx::Transform GetRootTransform() const;
  virtual void SetRootTransform(const gfx::Transform& transform);
  virtual gfx::Transform GetInverseRootTransform() const;

  // These functions are used in event translation for translating the local
  // coordinates of LocatedEvents. Default implementation calls to non-local
  // ones (e.g. GetRootTransform()).
  virtual gfx::Transform GetRootTransformForLocalEventCoordinates() const;
  virtual gfx::Transform GetInverseRootTransformForLocalEventCoordinates()
      const;

  // Updates the root window's size using |host_size_in_pixels|, current
  // transform and outsets.
  // TODO(ccameron): Make this function no longer public. The interaction
  // between this call, GetBounds, and OnHostResizedInPixels is ambiguous and
  // allows for inconsistencies.
  void UpdateRootWindowSizeInPixels();

  // Converts |point| from the root window's coordinate system to native
  // screen's.
  void ConvertDIPToScreenInPixels(gfx::Point* point) const;

  // Converts |point| from native screen coordinate system to the root window's.
  void ConvertScreenInPixelsToDIP(gfx::Point* point) const;

  // Converts |point| from the root window's coordinate system to the
  // host window's.
  virtual void ConvertDIPToPixels(gfx::Point* point) const;

  // Converts |point| from the host window's coordinate system to the
  // root window's.
  virtual void ConvertPixelsToDIP(gfx::Point* point) const;

  // Cursor.
  // Sets the currently-displayed cursor. If the cursor was previously hidden
  // via ShowCursor(false), it will remain hidden until ShowCursor(true) is
  // called, at which point the cursor that was last set via SetCursor() will be
  // used.
  void SetCursor(gfx::NativeCursor cursor);

  // Invoked when the cursor's visibility has changed.
  void OnCursorVisibilityChanged(bool visible);

  // Moves the cursor to the specified location relative to the root window.
  void MoveCursorToLocationInDIP(const gfx::Point& location_in_dip);

  // Moves the cursor to the |location_in_pixels| given in host coordinates.
  void MoveCursorToLocationInPixels(const gfx::Point& location_in_pixels);

  gfx::NativeCursor last_cursor() const { return last_cursor_; }

  // Gets the InputMethod instance, if NULL, creates & owns it.
  ui::InputMethod* GetInputMethod();
  bool has_input_method() const { return input_method_ != nullptr; }

  // Sets a shared unowned InputMethod. This is used when there is a singleton
  // InputMethod shared between multiple WindowTreeHost instances.
  //
  // This is used for Ash only. There are 2 reasons:
  // 1) ChromeOS virtual keyboard needs to receive ShowVirtualKeyboardIfEnabled
  // notification from InputMethod. Multiple InputMethod instances makes it hard
  // to register/unregister the observer for that notification. 2) For Ozone,
  // there is no native focus state for the root window and WindowTreeHost. See
  // DrmWindowHost::CanDispatchEvent, the key events always goes to the primary
  // WindowTreeHost. And after InputMethod processed the key event and continue
  // dispatching it, WindowTargeter::FindTargetForEvent may re-dispatch it to a
  // different WindowTreeHost. So the singleton InputMethod can make sure the
  // correct InputMethod instance processes the key event no matter which
  // WindowTreeHost is the target for event. Please refer to the test:
  // ExtendedDesktopTest.KeyEventsOnLockScreen.
  //
  // TODO(shuchen): remove this method after above reasons become invalid.
  // A possible solution is to make sure DrmWindowHost can find the correct
  // WindowTreeHost to dispatch events.
  void SetSharedInputMethod(ui::InputMethod* input_method);

  // Overridden from ui::internal::InputMethodDelegate:
  ui::EventDispatchDetails DispatchKeyEventPostIME(
      ui::KeyEvent* event,
      base::OnceCallback<void(bool)> ack_callback) final;

  // Overridden from ui::EventSource:
  ui::EventSink* GetEventSink() override;

  // Returns the id of the display. Default implementation queries Screen.
  virtual int64_t GetDisplayId();

  // Returns the EventSource responsible for dispatching events to the window
  // tree.
  virtual ui::EventSource* GetEventSource() = 0;

  // Returns the accelerated widget.
  virtual gfx::AcceleratedWidget GetAcceleratedWidget() = 0;

  // Shows the WindowTreeHost.
  void Show();

  // Hides the WindowTreeHost.
  void Hide();

  // Sets/Gets the bounds of the WindowTreeHost (in pixels). Note that a call to
  // GetBoundsInPixels() immediately following a SetBoundsInPixels() can return
  // the old bounds, because SetBoundsInPixels() can take effect asynchronously,
  // depending on the platform. The |local_surface_id| takes effect when (and
  // if) the new size is confirmed (potentially asynchronously) by the platform.
  // If |local_surface_id| is invalid, then a new LocalSurfaceId is allocated
  // when the size change takes effect.
  virtual void SetBoundsInPixels(
      const gfx::Rect& bounds_in_pixels,
      const viz::LocalSurfaceIdAllocation& local_surface_id_allocation =
          viz::LocalSurfaceIdAllocation()) = 0;
  virtual gfx::Rect GetBoundsInPixels() const = 0;

  // Sets the OS capture to the root window.
  virtual void SetCapture() = 0;

  // Releases OS capture of the root window.
  virtual void ReleaseCapture() = 0;

  // Returns the device scale assumed by the WindowTreeHost (set during the
  // most recent call to OnHostResizedInPixels).
  float device_scale_factor() const { return device_scale_factor_; }

  // Requests that |keys| be intercepted at the platform level and routed
  // directly to the web content.  If |codes| is empty, all keys will be
  // intercepted.  Returns a ScopedKeyboardHook instance which stops capturing
  // system key events when destroyed.
  std::unique_ptr<ScopedKeyboardHook> CaptureSystemKeyEvents(
      base::Optional<base::flat_set<ui::DomCode>> codes);

  // Returns a map of KeyboardEvent code to KeyboardEvent key values.
  virtual base::flat_map<std::string, std::string> GetKeyboardLayoutMap() = 0;

  // Returns true if KeyEvents should be send to IME. This is called from
  // WindowEventDispatcher during event dispatch.
  virtual bool ShouldSendKeyEventToIme();

  // Enables native window occlusion tracking for the native window this host
  // represents.
  virtual void EnableNativeWindowOcclusionTracking();

  // Disables native window occlusion tracking for the native window this host
  // represents.
  virtual void DisableNativeWindowOcclusionTracking();

  // Remembers the current occlusion state, and if it has changed, notifies
  // observers of the change.
  virtual void SetNativeWindowOcclusionState(Window::OcclusionState state);

 protected:
  friend class ScopedKeyboardHook;
  friend class TestScreen;  // TODO(beng): see if we can remove/consolidate.

  explicit WindowTreeHost(std::unique_ptr<Window> window = nullptr);

  // Set the cached display device scale factor. This should only be called
  // during subclass initialization, when the value is needed before InitHost().
  void IntializeDeviceScaleFactor(float device_scale_factor);

  void DestroyCompositor();
  void DestroyDispatcher();

  // If frame_sink_id is not passed in, one will be grabbed from
  // ContextFactoryPrivate. |are_events_in_pixels| indicates if events are
  // received in pixels. If |are_events_in_pixels| is false, events are
  // received in DIPs. See Compositor() for details on |trace_environment_name|.
  void CreateCompositor(
      const viz::FrameSinkId& frame_sink_id = viz::FrameSinkId(),
      bool force_software_compositor = false,
      bool external_begin_frames_enabled = false,
      bool are_events_in_pixels = true,
      const char* trace_environment_name = nullptr);

  void InitCompositor();
  void OnAcceleratedWidgetAvailable();

  // Returns the location of the RootWindow on native screen.
  virtual gfx::Point GetLocationOnScreenInPixels() const = 0;

  void OnHostMovedInPixels(const gfx::Point& new_location_in_pixels);
  void OnHostResizedInPixels(
      const gfx::Size& new_size_in_pixels,
      const viz::LocalSurfaceIdAllocation& local_surface_id_allocation =
          viz::LocalSurfaceIdAllocation());
  void OnHostWorkspaceChanged();
  void OnHostDisplayChanged();
  void OnHostCloseRequested();
  void OnHostLostWindowCapture();

  // Sets the currently displayed cursor.
  virtual void SetCursorNative(gfx::NativeCursor cursor) = 0;

  // Moves the cursor to the specified location relative to the root window.
  virtual void MoveCursorToScreenLocationInPixels(
      const gfx::Point& location_in_pixels) = 0;

  // Called when the cursor visibility has changed.
  virtual void OnCursorVisibilityChangedNative(bool show) = 0;

  // Shows the WindowTreeHost.
  virtual void ShowImpl() = 0;

  // Hides the WindowTreeHost.
  virtual void HideImpl() = 0;

  // display::DisplayObserver implementation.
  void OnDisplayMetricsChanged(const display::Display& display,
                               uint32_t metrics) override;

  // Begins capturing system key events.  Returns true if successful.
  virtual bool CaptureSystemKeyEventsImpl(
      base::Optional<base::flat_set<ui::DomCode>> dom_codes) = 0;

  // Stops capturing system keyboard events.
  virtual void ReleaseSystemKeyEventCapture() = 0;

  // True if |dom_code| is reserved for an active KeyboardLock request.
  virtual bool IsKeyLocked(ui::DomCode dom_code) = 0;

  virtual gfx::Rect GetTransformedRootWindowBoundsInPixels(
      const gfx::Size& size_in_pixels) const;

  const base::ObserverList<WindowTreeHostObserver>::Unchecked& observers()
      const {
    return observers_;
  }

 private:
  friend class test::WindowTreeHostTestApi;

  // Moves the cursor to the specified location. This method is internally used
  // by MoveCursorToLocationInDIP() and MoveCursorToLocationInPixels().
  void MoveCursorToInternal(const gfx::Point& root_location,
                            const gfx::Point& host_location);

  // Overrided from CompositorObserver:
  void OnCompositingDidCommit(ui::Compositor* compositor) override;
  void OnCompositingStarted(ui::Compositor* compositor,
                            base::TimeTicks start_time) override;
  void OnCompositingEnded(ui::Compositor* compositor) override;
  void OnCompositingChildResizing(ui::Compositor* compositor) override;
  void OnCompositingShuttingDown(ui::Compositor* compositor) override;

  // We don't use a std::unique_ptr for |window_| since we need this ptr to be
  // valid during its deletion. (Window's dtor notifies observers that may
  // attempt to reach back up to access this object which will be valid until
  // the end of the dtor).
  Window* window_;  // Owning.

  // Keeps track of the occlusion state of the host, and used to send
  // notifications to observers when it changes.
  Window::OcclusionState occlusion_state_;

  base::ObserverList<WindowTreeHostObserver>::Unchecked observers_;

  std::unique_ptr<WindowEventDispatcher> dispatcher_;

  std::unique_ptr<ui::Compositor> compositor_;

  // The device scale factor is snapshotted in OnHostResizedInPixels.
  // NOTE: this value is cached rather than looked up from the Display as it is
  // entirely possible for the Display to be updated *after* |this|. For
  // example, display changes on Windows first result in the HWND bounds
  // changing and are then followed by changes to the set of displays
  //
  // TODO(ccameron): The size and location from OnHostResizedInPixels and
  // OnHostMovedInPixels should be snapshotted here as well.
  float device_scale_factor_ = 1.f;

  // Last cursor set.  Used for testing.
  gfx::NativeCursor last_cursor_;
  gfx::Point last_cursor_request_position_in_host_;

  std::unique_ptr<ui::ViewProp> prop_;

  // The InputMethod instance used to process key events.
  // If owned it, it is created in GetInputMethod() method;
  // If not owned it, it is passed in through SetSharedInputMethod() method.
  ui::InputMethod* input_method_;

  // Whether the InputMethod instance is owned by this WindowTreeHost.
  bool owned_input_method_;

  // Set to the time the synchronization event began.
  base::TimeTicks synchronization_start_time_;

  // Set to true if this WindowTreeHost is currently holding pointer moves.
  bool holding_pointer_moves_ = false;

  base::WeakPtrFactory<WindowTreeHost> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(WindowTreeHost);
};

}  // namespace aura

#endif  // UI_AURA_WINDOW_TREE_HOST_H_
