// Copyright 2018 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 "services/ws/proxy_window.h"

#include <utility>

#include "base/containers/flat_map.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "services/ws/client_root.h"
#include "services/ws/drag_drop_delegate.h"
#include "services/ws/embedding.h"
#include "services/ws/top_level_proxy_window_impl.h"
#include "services/ws/window_tree.h"
#include "services/ws/window_utils.h"
#include "ui/aura/client/capture_client_observer.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/aura/window_targeter.h"
#include "ui/compositor/compositor.h"
#include "ui/events/event_handler.h"
#include "ui/wm/core/capture_controller.h"
#include "ui/wm/core/window_modality_controller.h"

DEFINE_UI_CLASS_PROPERTY_TYPE(ws::ProxyWindow*)

namespace ws {
namespace {
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(ProxyWindow, kProxyWindowKey, nullptr)

bool IsPointerPressedEvent(const ui::Event& event) {
  return event.type() == ui::ET_MOUSE_PRESSED ||
         event.type() == ui::ET_TOUCH_PRESSED;
}

bool IsPointerEvent(const ui::Event& event) {
  return event.IsMouseEvent() || event.IsTouchEvent();
}

bool IsLastMouseButtonRelease(const ui::Event& event) {
  return event.type() == ui::ET_MOUSE_RELEASED &&
         event.AsMouseEvent()->button_flags() ==
             event.AsMouseEvent()->changed_button_flags();
}

bool IsPointerReleased(const ui::Event& event) {
  return IsLastMouseButtonRelease(event) ||
         event.type() == ui::ET_TOUCH_RELEASED;
}

ui::PointerId GetPointerId(const ui::Event& event) {
  if (event.IsMouseEvent())
    return ui::MouseEvent::kMousePointerId;
  DCHECK(event.IsTouchEvent());
  return event.AsTouchEvent()->pointer_details().id;
}

// WindowTargeter used for ProxyWindows. This is used for two purposes:
// . If the location is in the non-client area, then child Windows are not
//   considered. This is done to ensure the delegate of the window (which is
//   local) sees the event.
// . To ensure |WindowTree::intercepts_events_| is honored.
class ProxyWindowTargeter : public aura::WindowTargeter {
 public:
  explicit ProxyWindowTargeter(ProxyWindow* proxy_window)
      : proxy_window_(proxy_window) {}
  ~ProxyWindowTargeter() override = default;

  // aura::WindowTargeter:
  bool SubtreeShouldBeExploredForEvent(aura::Window* window,
                                       const ui::LocatedEvent& event) override {
    // If the top-level does not have insets, then forward the call to the
    // parent's WindowTargeter. This is necessary for targeters such as
    // EasyResizeWindowTargeter to work correctly.
    if (mouse_extend().IsEmpty() && touch_extend().IsEmpty() &&
        proxy_window_->IsTopLevel() && window->parent()) {
      aura::WindowTargeter* parent_targeter =
          static_cast<WindowTargeter*>(window->parent()->targeter());
      if (parent_targeter)
        return parent_targeter->SubtreeShouldBeExploredForEvent(window, event);
    }
    return aura::WindowTargeter::SubtreeShouldBeExploredForEvent(window, event);
  }

  ui::EventTarget* FindTargetForEvent(ui::EventTarget* event_target,
                                      ui::Event* event) override {
    aura::Window* window = static_cast<aura::Window*>(event_target);
    DCHECK_EQ(window, proxy_window_->window());
    if (proxy_window_->DoesOwnerInterceptEvents()) {
      // If the owner intercepts events, then don't recurse (otherwise events
      // would go to a descendant).
      return event_target->CanAcceptEvent(*event) ? window : nullptr;
    }

    // Ensure events in the non-client area target the top-level window.
    // TopLevelEventHandler will ensure these are routed correctly.
    if (event->IsLocatedEvent() &&
        IsLocationInNonClientArea(window,
                                  event->AsLocatedEvent()->location())) {
      return window;
    }
    return aura::WindowTargeter::FindTargetForEvent(event_target, event);
  }

 private:
  ProxyWindow* const proxy_window_;

  DISALLOW_COPY_AND_ASSIGN(ProxyWindowTargeter);
};

// ProxyWindowEventHandler is used to forward events to the client.
// ProxyWindowEventHandler adds itself to the pre-phase to ensure it's
// considered before the Window's delegate (or other EventHandlers).
class ProxyWindowEventHandler : public ui::EventHandler {
 public:
  explicit ProxyWindowEventHandler(ProxyWindow* proxy_window)
      : proxy_window_(proxy_window) {
    // Use |kDefault| so as not to conflict with other important pre-target
    // handlers (such as laser pointer).
    window()->AddPreTargetHandler(this, ui::EventTarget::Priority::kDefault);
  }
  ~ProxyWindowEventHandler() override {
    window()->RemovePreTargetHandler(this);
  }

  ProxyWindow* proxy_window() { return proxy_window_; }
  aura::Window* window() { return proxy_window_->window(); }

  // ui::EventHandler:
  void OnEvent(ui::Event* event) override {
    if (event->phase() != ui::EP_PRETARGET) {
      // All work is done in the pre-phase. If this branch is hit, it means
      // event propagation was not stopped, and normal processing should
      // continue. Early out to avoid sending the event to the client again.
      return;
    }

    if (HandleInterceptedEvent(event) || ShouldIgnoreEvent(*event))
      return;

    auto* owning = proxy_window_->owning_window_tree();
    auto* embedded = proxy_window_->embedded_window_tree();
    WindowTree* target_client = nullptr;
    if (proxy_window_->DoesOwnerInterceptEvents()) {
      // A client that intercepts events, always gets the event regardless of
      // focus/capture.
      target_client = owning;
    } else if (event->IsKeyEvent()) {
      if (!proxy_window_->focus_owner())
        return;  // The local environment is going to process the event.
      target_client = proxy_window_->focus_owner();
    } else if (proxy_window()->capture_owner()) {
      target_client = proxy_window()->capture_owner();
    } else {
      // Prefer embedded over owner.
      target_client = !embedded ? owning : embedded;
    }
    DCHECK(target_client);

    // Don't send located events to the client during a move loop. Normally
    // the client shouldn't be the target at this point, but it's entirely
    // possible for held events to be released, triggering a spurious call.
    if (event->IsLocatedEvent() && target_client->IsMovingWindow())
      return;

    target_client->SendEventToClient(window(), *event);

    // The event was forwarded to the remote client. We don't want it handled
    // locally too.
    if (event->cancelable())
      event->StopPropagation();
  }

 protected:
  // Returns true if the event is a pinch event generated from the touchpad.
  bool IsPinchEventOnTouchpad(const ui::Event& event) {
    return event.IsPinchEvent() &&
           event.AsGestureEvent()->details().device_type() ==
               ui::GestureDeviceType::DEVICE_TOUCHPAD;
  }

  // Returns true if the event should be ignored (not forwarded to the client).
  bool ShouldIgnoreEvent(const ui::Event& event) {
    // It's assumed clients do their own gesture recognizition, which means
    // GestureEvents should not be forwarded to clients. Pinch events are
    // exceptional since they aren't created through gesture recognition but
    // from the touchpad directly. See https://crbug.com/933985.
    if (event.IsGestureEvent() && !IsPinchEventOnTouchpad(event))
      return true;

    if (static_cast<aura::Window*>(event.target()) != window()) {
      // As ProxyWindow is a EP_PRETARGET EventHandler it gets events *before*
      // descendants. Ignore all such events, and only process when
      // window() is the the target.
      return true;
    }
    if (wm::GetModalTransient(window()))
      return true;  // Do not send events to clients blocked by a modal window.
    return ShouldIgnoreEventType(event.type());
  }

  bool ShouldIgnoreEventType(ui::EventType type) const {
    // WindowTreeClient takes care of sending ET_MOUSE_CAPTURE_CHANGED at the
    // right point. The enter events are effectively synthetic, and indirectly
    // generated in the client as the result of a move event.
    switch (type) {
      case ui::ET_MOUSE_CAPTURE_CHANGED:
      case ui::ET_MOUSE_ENTERED:
        return true;
      default:
        break;
    }
    return false;
  }

  // If |window| identifies an embedding and the owning client intercepts
  // events, this forwards to the owner and returns true. Otherwise returns
  // false.
  bool HandleInterceptedEvent(ui::Event* event) {
    if (ShouldIgnoreEventType(event->type()))
      return false;

    // KeyEvents, and events when there is capture, do not go through through
    // ProxyWindowTargeter. As a result ProxyWindowEventHandler has to check
    // for a client intercepting events.
    if (proxy_window_->DoesOwnerInterceptEvents()) {
      proxy_window_->owning_window_tree()->SendEventToClient(window(), *event);
      if (event->cancelable())
        event->StopPropagation();
      return true;
    }
    return false;
  }

 private:
  ProxyWindow* const proxy_window_;

  DISALLOW_COPY_AND_ASSIGN(ProxyWindowEventHandler);
};

class TopLevelEventHandler;

// PointerPressHandler is used to track state while a pointer is down.
// PointerPressHandler is typically destroyed when the pointer is released, but
// it may be destroyed at other times, such as when capture changes.
class PointerPressHandler : public aura::client::CaptureClientObserver,
                            public aura::WindowObserver {
 public:
  PointerPressHandler(TopLevelEventHandler* top_level_event_handler,
                      ui::PointerId pointer_id,
                      const gfx::Point& location);
  ~PointerPressHandler() override;

  bool in_non_client_area() const { return in_non_client_area_; }

 private:
  // aura::client::CaptureClientObserver:
  void OnCaptureChanged(aura::Window* lost_capture,
                        aura::Window* gained_capture) override;

  // aura::WindowObserver:
  void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;

  TopLevelEventHandler* top_level_event_handler_;

  // True if the pointer down occurred in the non-client area.
  const bool in_non_client_area_;

  // Id of the pointer the handler was created for.
  const ui::PointerId pointer_id_;

  DISALLOW_COPY_AND_ASSIGN(PointerPressHandler);
};

// ui::EventHandler used for top-levels. Some events that target the non-client
// area are not sent to the client, instead are handled locally. For example,
// if a press occurs in the non-client area, then the event is not sent to
// the client, it's handled locally.
class TopLevelEventHandler : public ProxyWindowEventHandler {
 public:
  explicit TopLevelEventHandler(ProxyWindow* proxy_window)
      : ProxyWindowEventHandler(proxy_window) {
    // Top-levels should always have an owning_window_tree().
    // OnEvent() assumes this.
    DCHECK(proxy_window->owning_window_tree());
  }

  ~TopLevelEventHandler() override = default;

  void DestroyPointerPressHandler(ui::PointerId id) {
    pointer_press_handlers_.erase(id);
  }

  // Returns true if the pointer with |pointer_id| was pressed over the
  // top-level. If this returns true, TopLevelEventHandler is waiting on a
  // release to reset state.
  bool IsHandlingPointerPress(ui::PointerId pointer_id) const {
    return pointer_press_handlers_.count(pointer_id) > 0;
  }

  // Called when the capture owner changes.
  void OnCaptureOwnerChanged() {
    // Changing the capture owner toggles between local and the client getting
    // the event. The |pointer_press_handlers_| are no longer applicable
    // (because the target is purely dicatated by capture owner).
    pointer_press_handlers_.clear();
  }

  // ProxyWindowEventHandler:
  void OnEvent(ui::Event* event) override {
    if (event->phase() != ui::EP_PRETARGET) {
      // All work is done in the pre-phase. If this branch is hit, it means
      // event propagation was not stopped, and normal processing should
      // continue. Early out to avoid sending the event to the client again.
      return;
    }

    if (HandleInterceptedEvent(event))
      return;

    if (!event->IsLocatedEvent()) {
      ProxyWindowEventHandler::OnEvent(event);
      return;
    }

    // When the gesture-end happens in the server side, the gesture state
    // is cleaned up there; this state should be synchronized with the client.
    if (event->type() == ui::ET_GESTURE_END &&
        event->AsGestureEvent()->details().touch_points() == 1) {
      proxy_window()->owning_window_tree()->CleanupGestureState(window());
      return;
    }

    if (ShouldIgnoreEvent(*event))
      return;

    // If there is capture, send the event to the client that owns it. A null
    // capture owner means the local environment should handle the event.
    if (wm::CaptureController::Get()->GetCaptureWindow()) {
      if (proxy_window()->capture_owner()) {
        proxy_window()->capture_owner()->SendEventToClient(window(), *event);
        if (event->cancelable())
          event->StopPropagation();
        return;
      }
      return;
    }

    // This code has two specific behaviors. It's used to ensure events go to
    // the right target (either local, or the remote client).
    // . a press-release sequence targets only one. If in non-client area then
    //   local, otherwise remote client.
    // . mouse-moves (not drags) go to both targets.
    bool stop_propagation = false;
    if (proxy_window()->HasNonClientArea() && IsPointerEvent(*event)) {
      const ui::PointerId pointer_id = GetPointerId(*event);
      if (!pointer_press_handlers_.count(pointer_id)) {
        if (IsPointerPressedEvent(*event)) {
          std::unique_ptr<PointerPressHandler> handler_ptr =
              std::make_unique<PointerPressHandler>(
                  this, pointer_id, event->AsLocatedEvent()->location());
          PointerPressHandler* handler = handler_ptr.get();
          pointer_press_handlers_[pointer_id] = std::move(handler_ptr);
          if (handler->in_non_client_area())
            return;  // Don't send presses in non-client area to client.
          stop_propagation = true;
        }
      } else {
        // Currently handling a pointer press and waiting on release.
        PointerPressHandler* handler =
            pointer_press_handlers_[pointer_id].get();
        const bool was_press_in_non_client_area = handler->in_non_client_area();
        if (IsPointerReleased(*event))
          pointer_press_handlers_.erase(pointer_id);
        if (was_press_in_non_client_area)
          return;  // Don't send release to client since press didn't go there.
        stop_propagation = true;
      }
    }
    proxy_window()->owning_window_tree()->SendEventToClient(window(), *event);
    if (stop_propagation && event->cancelable())
      event->StopPropagation();
  }

 private:
  // Non-null while in a pointer press press-drag-release cycle. Maps from
  // pointer-id of the pointer that is down to the handler.
  base::flat_map<ui::PointerId, std::unique_ptr<PointerPressHandler>>
      pointer_press_handlers_;

  DISALLOW_COPY_AND_ASSIGN(TopLevelEventHandler);
};

PointerPressHandler::PointerPressHandler(
    TopLevelEventHandler* top_level_event_handler,
    ui::PointerId pointer_id,
    const gfx::Point& location)
    : top_level_event_handler_(top_level_event_handler),
      in_non_client_area_(
          IsLocationInNonClientArea(top_level_event_handler->window(),
                                    location)),
      pointer_id_(pointer_id) {
  wm::CaptureController::Get()->AddObserver(this);
  top_level_event_handler_->window()->AddObserver(this);
}

PointerPressHandler::~PointerPressHandler() {
  top_level_event_handler_->window()->RemoveObserver(this);
  wm::CaptureController::Get()->RemoveObserver(this);
}

void PointerPressHandler::OnCaptureChanged(aura::Window* lost_capture,
                                           aura::Window* gained_capture) {
  if (gained_capture != top_level_event_handler_->window())
    top_level_event_handler_->DestroyPointerPressHandler(pointer_id_);
}

void PointerPressHandler::OnWindowVisibilityChanged(aura::Window* window,
                                                    bool visible) {
  if (!top_level_event_handler_->window()->IsVisible())
    top_level_event_handler_->DestroyPointerPressHandler(pointer_id_);
}

}  // namespace

ProxyWindow::~ProxyWindow() {
  // WindowTree/ClientRoot should have reset |attached_frame_sink_id_| before
  // the Window is destroyed.
  DCHECK(!attached_frame_sink_id_.is_valid());
}

// static
ProxyWindow* ProxyWindow::Create(aura::Window* window,
                                 WindowTree* tree,
                                 const viz::FrameSinkId& frame_sink_id,
                                 bool is_top_level) {
  DCHECK(!GetMayBeNull(window));
  // Owned by |window|.
  ProxyWindow* proxy_window =
      new ProxyWindow(window, tree, frame_sink_id, is_top_level);
  return proxy_window;
}

// static
const ProxyWindow* ProxyWindow::GetMayBeNull(const aura::Window* window) {
  return window ? window->GetProperty(kProxyWindowKey) : nullptr;
}

void ProxyWindow::Destroy() {
  // This should only be called for windows created locally for an embedding
  // (not created by a remote client). Such windows do not have an owner.
  DCHECK(!owning_window_tree_);
  // static_cast is needed to determine which function SetProperty() applies
  // to.
  window_->SetProperty(kProxyWindowKey, static_cast<ProxyWindow*>(nullptr));
}

WindowTree* ProxyWindow::embedded_window_tree() {
  return embedding_ ? embedding_->embedded_tree() : nullptr;
}

const WindowTree* ProxyWindow::embedded_window_tree() const {
  return embedding_ ? embedding_->embedded_tree() : nullptr;
}

void ProxyWindow::SetClientArea(
    const gfx::Insets& insets,
    const std::vector<gfx::Rect>& additional_client_areas) {
  if (client_area_ == insets &&
      additional_client_areas == additional_client_areas_) {
    return;
  }

  additional_client_areas_ = additional_client_areas;
  client_area_ = insets;
}

void ProxyWindow::SetHitTestInsets(const gfx::Insets& mouse,
                                   const gfx::Insets& touch) {
  window_targeter_->SetInsets(mouse, touch);
}

void ProxyWindow::SetCaptureOwner(WindowTree* owner) {
  capture_owner_ = owner;
  if (!IsTopLevel())
    return;

  static_cast<TopLevelEventHandler*>(event_handler_.get())
      ->OnCaptureOwnerChanged();
}

void ProxyWindow::StoreCursor(const ui::Cursor& cursor) {
  cursor_ = cursor;
}

bool ProxyWindow::DoesOwnerInterceptEvents() const {
  return embedding_ && embedding_->embedding_tree_intercepts_events();
}

void ProxyWindow::SetEmbedding(std::unique_ptr<Embedding> embedding) {
  embedding_ = std::move(embedding);
}

bool ProxyWindow::HasNonClientArea() const {
  return owning_window_tree_ && owning_window_tree_->IsTopLevel(window_) &&
         (!client_area_.IsEmpty() || !additional_client_areas_.empty());
}

bool ProxyWindow::IsTopLevel() const {
  return owning_window_tree_ && owning_window_tree_->IsTopLevel(window_);
}

void ProxyWindow::AttachCompositorFrameSink(
    viz::mojom::CompositorFrameSinkRequest compositor_frame_sink,
    viz::mojom::CompositorFrameSinkClientPtr client) {
  attached_compositor_frame_sink_ = true;
  viz::HostFrameSinkManager* host_frame_sink_manager =
      window_->env()->context_factory_private()->GetHostFrameSinkManager();
  host_frame_sink_manager->CreateCompositorFrameSink(
      frame_sink_id_, std::move(compositor_frame_sink), std::move(client));
}

void ProxyWindow::SetDragDropDelegate(
    std::unique_ptr<DragDropDelegate> drag_drop_delegate) {
  drag_drop_delegate_ = std::move(drag_drop_delegate);
}

void ProxyWindow::SetTopLevelProxyWindow(
    std::unique_ptr<TopLevelProxyWindowImpl> window) {
  top_level_proxy_window_ = std::move(window);
}

std::string ProxyWindow::GetIdForDebugging() {
  return owning_window_tree_
             ? owning_window_tree_->ClientWindowIdForWindow(window_).ToString()
             : frame_sink_id_.ToString();
}

ProxyWindow::ProxyWindow(aura::Window* window,
                         WindowTree* tree,
                         const viz::FrameSinkId& frame_sink_id,
                         bool is_top_level)
    : window_(window),
      owning_window_tree_(tree),
      frame_sink_id_(frame_sink_id) {
  window_->SetProperty(kProxyWindowKey, this);
  if (is_top_level)
    event_handler_ = std::make_unique<TopLevelEventHandler>(this);
  else
    event_handler_ = std::make_unique<ProxyWindowEventHandler>(this);
  auto proxy_window_targeter = std::make_unique<ProxyWindowTargeter>(this);
  window_targeter_ = proxy_window_targeter.get();
  window_->SetEventTargeter(std::move(proxy_window_targeter));
  // In order for a window to receive events it must have a target_handler()
  // (see Window::CanAcceptEvent()). Normally the delegate is the TargetHandler,
  // but if the delegate is null, then so is the target_handler(). Set
  // |event_handler_| as the target_handler() to force the Window to accept
  // events.
  if (!window_->delegate())
    window_->SetTargetHandler(event_handler_.get());
}

bool ProxyWindow::IsHandlingPointerPressForTesting(ui::PointerId pointer_id) {
  DCHECK(IsTopLevel());
  return static_cast<TopLevelEventHandler*>(event_handler_.get())
      ->IsHandlingPointerPress(pointer_id);
}

}  // namespace ws
