// 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.

#include "ash/magnifier/magnification_controller.h"

#include <algorithm>
#include <memory>
#include <utility>
#include <vector>

#include "ash/accelerators/accelerator_controller.h"
#include "ash/accessibility/accessibility_delegate.h"
#include "ash/display/root_window_transformers.h"
#include "ash/host/ash_window_tree_host.h"
#include "ash/host/root_window_transformer.h"
#include "ash/magnifier/magnifier_utils.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/root_window_controller.h"
#include "ash/shell.h"
#include "base/numerics/ranges.h"
#include "base/synchronization/waitable_event.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ime/ime_bridge.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/compositor/dip_util.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
#include "ui/events/gestures/gesture_provider_aura.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/keyboard/keyboard_controller.h"
#include "ui/wm/core/compound_event_filter.h"
#include "ui/wm/core/coordinate_conversion.h"

namespace ash {

namespace {

constexpr float kMaxMagnifiedScale = 20.0f;
constexpr float kMinMagnifiedScaleThreshold = 1.1f;
constexpr float kNonMagnifiedScale = 1.0f;

constexpr float kInitialMagnifiedScale = 2.0f;
constexpr float kScrollScaleChangeFactor = 0.00125f;

// Default animation parameters for redrawing the magnification window.
constexpr gfx::Tween::Type kDefaultAnimationTweenType = gfx::Tween::EASE_OUT;
constexpr int kDefaultAnimationDurationInMs = 100;

// Use linear transformation to make the magnifier window move smoothly
// to center the focus when user types in a text input field.
constexpr gfx::Tween::Type kCenterCaretAnimationTweenType = gfx::Tween::LINEAR;

// The delay of the timer for moving magnifier window for centering the text
// input focus.
constexpr int kMoveMagnifierDelayInMs = 10;

// Threshold of panning. If the cursor moves to within pixels (in DIP) of
// |kCursorPanningMargin| from the edge, the view-port moves.
constexpr int kCursorPanningMargin = 100;

// Threshold of panning at the bottom when the virtual keyboard is up. If the
// cursor moves to within pixels (in DIP) of |kKeyboardBottomPanningMargin| from
// the bottom edge, the view-port moves. This is only used by
// MoveMagnifierWindowFollowPoint() when |reduce_bottom_margin| is true.
constexpr int kKeyboardBottomPanningMargin = 10;

// Threadshold of panning. If the caret moves to within pixels (in DIP) of
// |kCaretPanningMargin| from the edge, the view-port moves.
constexpr int kCaretPanningMargin = 50;

void MoveCursorTo(aura::WindowTreeHost* host, const gfx::Point& root_location) {
  auto host_location_3f = gfx::Point3F(gfx::PointF(root_location));
  host->GetRootTransform().TransformPoint(&host_location_3f);
  host->MoveCursorToLocationInPixels(
      gfx::ToCeiledPoint(host_location_3f.AsPointF()));
}

}  // namespace

class MagnificationController::GestureProviderClient
    : public ui::GestureProviderAuraClient {
 public:
  GestureProviderClient() = default;
  ~GestureProviderClient() override = default;

  // ui::GestureProviderAuraClient overrides:
  void OnGestureEvent(GestureConsumer* consumer,
                      ui::GestureEvent* event) override {
    // Do nothing. OnGestureEvent is for timer based gesture events, e.g. tap.
    // MagnificationController is interested only in pinch and scroll
    // gestures.
    DCHECK_NE(ui::ET_GESTURE_SCROLL_BEGIN, event->type());
    DCHECK_NE(ui::ET_GESTURE_SCROLL_END, event->type());
    DCHECK_NE(ui::ET_GESTURE_SCROLL_UPDATE, event->type());
    DCHECK_NE(ui::ET_GESTURE_PINCH_BEGIN, event->type());
    DCHECK_NE(ui::ET_GESTURE_PINCH_END, event->type());
    DCHECK_NE(ui::ET_GESTURE_PINCH_UPDATE, event->type());
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(GestureProviderClient);
};

MagnificationController::MagnificationController()
    : root_window_(Shell::GetPrimaryRootWindow()),
      scale_(kNonMagnifiedScale),
      original_scale_(kNonMagnifiedScale) {
  Shell::Get()->AddPreTargetHandler(this);
  root_window_->AddObserver(this);
  root_window_->GetHost()->GetEventSource()->AddEventRewriter(this);
  if (ui::IMEBridge::Get())
    ui::IMEBridge::Get()->AddObserver(this);

  point_of_interest_in_root_ = root_window_->bounds().CenterPoint();

  gesture_provider_client_ = std::make_unique<GestureProviderClient>();
  gesture_provider_ = std::make_unique<ui::GestureProviderAura>(
      this, gesture_provider_client_.get());
}

MagnificationController::~MagnificationController() {
  if (input_method_)
    input_method_->RemoveObserver(this);
  input_method_ = nullptr;
  if (ui::IMEBridge::Get())
    ui::IMEBridge::Get()->RemoveObserver(this);

  root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this);
  root_window_->RemoveObserver(this);

  Shell::Get()->RemovePreTargetHandler(this);
}

void MagnificationController::SetEnabled(bool enabled) {
  if (enabled) {
    if (!is_enabled_) {
      input_method_ = magnifier_utils::GetInputMethod(root_window_);
      if (input_method_)
        input_method_->AddObserver(this);
    }
    Shell* shell = Shell::Get();
    float scale =
        shell->accessibility_delegate()->GetSavedScreenMagnifierScale();
    if (scale <= 0.0f)
      scale = kInitialMagnifiedScale;
    ValidateScale(&scale);

    // Do nothing, if already enabled with same scale.
    if (is_enabled_ && scale == scale_)
      return;

    is_enabled_ = enabled;
    RedrawKeepingMousePosition(scale, true, false);
    shell->accessibility_delegate()->SaveScreenMagnifierScale(scale);
  } else {
    // Do nothing, if already disabled.
    if (!is_enabled_)
      return;

    if (input_method_)
      input_method_->RemoveObserver(this);
    input_method_ = nullptr;

    RedrawKeepingMousePosition(kNonMagnifiedScale, true, false);
    is_enabled_ = enabled;
  }

  // Keyboard overscroll creates layout issues with fullscreen magnification
  // so it needs to be disabled when magnification is enabled.
  // TODO(spqchan): Fix the keyboard overscroll issues.
  auto config = keyboard::KeyboardController::Get()->keyboard_config();
  config.overscroll_behavior =
      is_enabled_ ? keyboard::mojom::KeyboardOverscrollBehavior::kDisabled
                  : keyboard::mojom::KeyboardOverscrollBehavior::kDefault;
  keyboard::KeyboardController::Get()->UpdateKeyboardConfig(config);
}

bool MagnificationController::IsEnabled() const {
  return is_enabled_;
}

void MagnificationController::SetKeepFocusCentered(bool keep_focus_centered) {
  keep_focus_centered_ = keep_focus_centered;
}

bool MagnificationController::KeepFocusCentered() const {
  return keep_focus_centered_;
}

void MagnificationController::SetScale(float scale, bool animate) {
  if (!is_enabled_)
    return;

  ValidateScale(&scale);
  Shell::Get()->accessibility_delegate()->SaveScreenMagnifierScale(scale);
  RedrawKeepingMousePosition(scale, animate, false);
}

void MagnificationController::StepToNextScaleValue(int delta_index) {
  SetScale(magnifier_utils::GetNextMagnifierScaleValue(
               delta_index, GetScale(), kNonMagnifiedScale, kMaxMagnifiedScale),
           true /* animate */);
}

void MagnificationController::MoveWindow(int x, int y, bool animate) {
  if (!is_enabled_)
    return;

  Redraw(gfx::PointF(x, y), scale_, animate);
}

void MagnificationController::MoveWindow(const gfx::Point& point,
                                         bool animate) {
  if (!is_enabled_)
    return;

  Redraw(gfx::PointF(point), scale_, animate);
}

gfx::Point MagnificationController::GetWindowPosition() const {
  return gfx::ToFlooredPoint(origin_);
}

void MagnificationController::SetScrollDirection(ScrollDirection direction) {
  scroll_direction_ = direction;
  StartOrStopScrollIfNecessary();
}

gfx::Rect MagnificationController::GetViewportRect() const {
  return gfx::ToEnclosingRect(GetWindowRectDIP(scale_));
}

void MagnificationController::CenterOnPoint(const gfx::Point& point_in_screen) {
  gfx::Point point_in_root = point_in_screen;
  ::wm::ConvertPointFromScreen(root_window_, &point_in_root);

  MoveMagnifierWindowCenterPoint(point_in_root);
}

void MagnificationController::HandleFocusedNodeChanged(
    bool is_editable_node,
    const gfx::Rect& node_bounds_in_screen) {
  // The editable node is handled by OnCaretBoundsChanged.
  if (is_editable_node)
    return;

  // Nothing to recenter on.
  if (node_bounds_in_screen.IsEmpty())
    return;

  gfx::Rect node_bounds_in_root = node_bounds_in_screen;
  ::wm::ConvertRectFromScreen(root_window_, &node_bounds_in_root);
  if (GetViewportRect().Contains(node_bounds_in_root))
    return;

  MoveMagnifierWindowFollowRect(node_bounds_in_root);
}

void MagnificationController::SwitchTargetRootWindow(
    aura::Window* new_root_window,
    bool redraw_original_root_window) {
  DCHECK(new_root_window);

  if (new_root_window == root_window_)
    return;

  // Stores the previous scale.
  float scale = GetScale();

  // Unmagnify the previous root window.
  root_window_->RemoveObserver(this);
  // TODO: This may need to remove the IME observer from the old root window
  // and add it to the new root window. https://crbug.com/820464

  // Do not move mouse back to its original position (point at border of the
  // root window) after redrawing as doing so will trigger root window switch
  // again.
  if (redraw_original_root_window)
    RedrawKeepingMousePosition(1.0f, true, true);
  root_window_ = new_root_window;
  RedrawKeepingMousePosition(scale, true, true);

  root_window_->AddObserver(this);
}

gfx::Transform MagnificationController::GetMagnifierTransform() const {
  gfx::Transform transform;
  if (IsEnabled()) {
    transform.Scale(scale_, scale_);
    gfx::Point offset = GetWindowPosition();
    transform.Translate(-offset.x(), -offset.y());
  }

  return transform;
}

void MagnificationController::OnInputContextHandlerChanged() {
  if (!is_enabled_)
    return;

  auto* new_input_method = magnifier_utils::GetInputMethod(root_window_);
  if (new_input_method == input_method_)
    return;

  if (input_method_)
    input_method_->RemoveObserver(this);
  input_method_ = new_input_method;
  if (input_method_)
    input_method_->AddObserver(this);
}

void MagnificationController::OnCaretBoundsChanged(
    const ui::TextInputClient* client) {
  // caret bounds in screen coordinates.
  const gfx::Rect caret_bounds = client->GetCaretBounds();
  // Note: OnCaretBoundsChanged could be fired OnTextInputTypeChanged during
  // which the caret position is not set a meaning position, and we do not
  // need to adjust the view port position based on the bogus caret position.
  // This is only a transition period, the caret position will be fixed upon
  // focusing right after.
  if (caret_bounds.width() == 0 && caret_bounds.height() == 0)
    return;

  gfx::Point new_caret_point = caret_bounds.CenterPoint();
  // |caret_point_| in |root_window_| coordinates.
  ::wm::ConvertPointFromScreen(root_window_, &new_caret_point);

  // When the caret point was not actually changed, nothing should happen.
  // OnCaretBoundsChanged could be fired on every event that may change the
  // caret bounds, in particular a window creation/movement, that may not result
  // in an actual movement.
  if (new_caret_point == caret_point_)
    return;
  caret_point_ = new_caret_point;

  // If the feature for centering the text input focus is disabled, the
  // magnifier window will be moved to follow the focus with a panning margin.
  if (!KeepFocusCentered()) {
    // Visible window_rect in |root_window_| coordinates.
    const gfx::Rect visible_window_rect = GetViewportRect();
    const int panning_margin = kCaretPanningMargin / scale_;
    MoveMagnifierWindowFollowPoint(caret_point_, panning_margin, panning_margin,
                                   visible_window_rect.width() / 2,
                                   visible_window_rect.height() / 2,
                                   false /* reduce_bottom_margin */);
    return;
  }

  // Move the magnifier window to center the focus with a little delay.
  // In Gmail compose window, when user types a blank space, it will insert
  // a non-breaking space(NBSP). NBSP will be replaced with a blank space
  // character when user types a non-blank space character later, which causes
  // OnCaretBoundsChanged be called twice. The first call moves the caret back
  // to the character position just before NBSP, replaces the NBSP with blank
  // space plus the new character, then the second call will move caret to the
  // position after the new character. In order to avoid the magnifier window
  // being moved back and forth with these two OnCaretBoundsChanged events, we
  // defer moving magnifier window until the |move_magnifier_timer_| fires,
  // when the caret settles eventually.
  move_magnifier_timer_.Stop();
  move_magnifier_timer_.Start(
      FROM_HERE,
      base::TimeDelta::FromMilliseconds(
          disable_move_magnifier_delay_ ? 0 : kMoveMagnifierDelayInMs),
      this, &MagnificationController::OnMoveMagnifierTimer);
}

void MagnificationController::OnInputMethodDestroyed(
    const ui::InputMethod* input_method) {
  DCHECK_EQ(input_method, input_method_);
  input_method_->RemoveObserver(this);
  input_method_ = nullptr;
}

void MagnificationController::OnImplicitAnimationsCompleted() {
  if (!is_on_animation_)
    return;

  if (move_cursor_after_animation_) {
    MoveCursorTo(root_window_->GetHost(), position_after_animation_);
    move_cursor_after_animation_ = false;

    aura::client::CursorClient* cursor_client =
        aura::client::GetCursorClient(root_window_);
    if (cursor_client)
      cursor_client->EnableMouseEvents();
  }

  is_on_animation_ = false;

  StartOrStopScrollIfNecessary();
}

void MagnificationController::OnWindowDestroying(aura::Window* root_window) {
  if (root_window == root_window_) {
    // There must be at least one root window because this controller is
    // destroyed before the root windows get destroyed.
    DCHECK(root_window);

    aura::Window* target_root_window = Shell::GetRootWindowForNewWindows();
    CHECK(target_root_window);

    // The destroyed root window must not be target.
    CHECK_NE(target_root_window, root_window);
    // Don't redraw the old root window as it's being destroyed.
    SwitchTargetRootWindow(target_root_window, false);
    point_of_interest_in_root_ = target_root_window->bounds().CenterPoint();
  }
}

void MagnificationController::OnWindowBoundsChanged(
    aura::Window* window,
    const gfx::Rect& old_bounds,
    const gfx::Rect& new_bounds,
    ui::PropertyChangeReason reason) {
  // TODO(yoshiki): implement here. crbug.com/230979
}

void MagnificationController::OnMouseEvent(ui::MouseEvent* event) {
  aura::Window* target = static_cast<aura::Window*>(event->target());
  aura::Window* current_root = target->GetRootWindow();
  gfx::Rect root_bounds = current_root->bounds();

  if (root_bounds.Contains(event->root_location())) {
    // This must be before |SwitchTargetRootWindow()|.
    if (event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)
      point_of_interest_in_root_ = event->root_location();

    if (current_root != root_window_) {
      DCHECK(current_root);
      SwitchTargetRootWindow(current_root, true);
    }

    if (IsMagnified() && event->type() == ui::ET_MOUSE_MOVED &&
        event->pointer_details().pointer_type !=
            ui::EventPointerType::POINTER_TYPE_PEN) {
      OnMouseMove(event->root_location());
    }
  }
}

void MagnificationController::OnScrollEvent(ui::ScrollEvent* event) {
  if (event->IsAltDown() && event->IsControlDown()) {
    if (event->type() == ui::ET_SCROLL_FLING_START) {
      event->StopPropagation();
      return;
    } else if (event->type() == ui::ET_SCROLL_FLING_CANCEL) {
      float scale = GetScale();
      // Jump back to exactly 1.0 if we are just a tiny bit zoomed in.
      // TODO(katie): These events are not fired after every scroll, which means
      // we don't always jump back to 1.0. Look into why they are missing.
      if (scale < kMinMagnifiedScaleThreshold) {
        scale = kNonMagnifiedScale;
        SetScale(scale, true);
      }
      event->StopPropagation();
      return;
    }

    if (event->type() == ui::ET_SCROLL) {
      SetScale(magnifier_utils::GetScaleFromScroll(
                   event->y_offset() * kScrollScaleChangeFactor, GetScale(),
                   kMaxMagnifiedScale, kNonMagnifiedScale),
               false /* animate */);
      event->StopPropagation();
      return;
    }
  }
}

void MagnificationController::OnTouchEvent(ui::TouchEvent* event) {
  aura::Window* target = static_cast<aura::Window*>(event->target());
  aura::Window* current_root = target->GetRootWindow();

  gfx::Rect root_bounds = current_root->bounds();
  if (!root_bounds.Contains(event->root_location()))
    return;

  point_of_interest_in_root_ = event->root_location();

  if (current_root != root_window_)
    SwitchTargetRootWindow(current_root, true);
}

ui::EventDispatchDetails MagnificationController::RewriteEvent(
    const ui::Event& event,
    const Continuation continuation) {
  if (!IsEnabled())
    return SendEvent(continuation, &event);

  if (!event.IsTouchEvent())
    return SendEvent(continuation, &event);

  const ui::TouchEvent* touch_event = event.AsTouchEvent();

  if (touch_event->type() == ui::ET_TOUCH_PRESSED) {
    touch_points_++;
    press_event_map_[touch_event->pointer_details().id] =
        std::make_unique<ui::TouchEvent>(*touch_event);
  } else if (touch_event->type() == ui::ET_TOUCH_RELEASED) {
    touch_points_--;
    press_event_map_.erase(touch_event->pointer_details().id);
  }

  ui::TouchEvent touch_event_copy = *touch_event;
  if (gesture_provider_->OnTouchEvent(&touch_event_copy)) {
    gesture_provider_->OnTouchEventAck(
        touch_event_copy.unique_event_id(), false /* event_consumed */,
        false /* is_source_touch_event_set_non_blocking */);
  } else {
    return DiscardEvent(continuation);
  }

  // User can change zoom level with two fingers pinch and pan around with two
  // fingers scroll. Once MagnificationController detects one of those two
  // gestures, it starts consuming all touch events with cancelling existing
  // touches. If cancel_pressed_touches is set to true, ET_TOUCH_CANCELLED
  // events are dispatched for existing touches after the next for-loop.
  bool cancel_pressed_touches = ProcessGestures();

  if (cancel_pressed_touches) {
    DCHECK_EQ(2u, press_event_map_.size());

    // MagnificationController starts consuming all touch events after it
    // cancells existing touches.
    consume_touch_event_ = true;

    for (const auto& it : press_event_map_) {
      ui::TouchEvent touch_cancel_event(ui::ET_TOUCH_CANCELLED, gfx::Point(),
                                        touch_event->time_stamp(),
                                        it.second->pointer_details());
      touch_cancel_event.set_location_f(it.second->location_f());
      touch_cancel_event.set_root_location_f(it.second->root_location_f());
      touch_cancel_event.set_flags(it.second->flags());

      // TouchExplorationController is watching event stream and managing its
      // internal state. If an event rewriter (MagnificationController) rewrites
      // event stream, the next event rewriter won't get the event, which makes
      // TouchExplorationController confused. Send cancelled event for recorded
      // touch events to the next event rewriter here instead of rewriting an
      // event in the stream.
      ui::EventDispatchDetails details =
          SendEvent(continuation, &touch_cancel_event);
      if (details.dispatcher_destroyed || details.target_destroyed)
        return details;
    }
    press_event_map_.clear();
  }
  bool discard = consume_touch_event_;

  // Reset state once no point is touched on the screen.
  if (touch_points_ == 0) {
    consume_touch_event_ = false;

    // Jump back to exactly 1.0 if we are just a tiny bit zoomed in.
    if (scale_ < kMinMagnifiedScaleThreshold) {
      SetScale(kNonMagnifiedScale, true /* animate */);
    } else {
      // Store current magnifier scale in pref. We don't need to call this if we
      // call SetScale (the above case) as SetScale does this.
      Shell::Get()->accessibility_delegate()->SaveScreenMagnifierScale(scale_);
    }
  }

  if (discard)
    return DiscardEvent(continuation);

  return SendEvent(continuation, &event);
}

bool MagnificationController::Redraw(const gfx::PointF& position,
                                     float scale,
                                     bool animate) {
  const gfx::PointF position_in_dip =
      ui::ConvertPointToDIP(root_window_->layer(), position);
  return RedrawDIP(position_in_dip, scale,
                   animate ? kDefaultAnimationDurationInMs : 0,
                   kDefaultAnimationTweenType);
}

bool MagnificationController::RedrawDIP(const gfx::PointF& position_in_dip,
                                        float scale,
                                        int duration_in_ms,
                                        gfx::Tween::Type tween_type) {
  DCHECK(root_window_);

  float x = position_in_dip.x();
  float y = position_in_dip.y();

  ValidateScale(&scale);

  if (x < 0)
    x = 0;
  if (y < 0)
    y = 0;

  const gfx::Size host_size_in_dip = GetHostSizeDIP();
  const gfx::SizeF window_size_in_dip = GetWindowRectDIP(scale).size();
  float max_x = host_size_in_dip.width() - window_size_in_dip.width();
  float max_y = host_size_in_dip.height() - window_size_in_dip.height();
  if (x > max_x)
    x = max_x;
  if (y > max_y)
    y = max_y;

  // Does nothing if both the origin and the scale are not changed.
  if (origin_.x() == x && origin_.y() == y && scale == scale_) {
    return false;
  }

  origin_.set_x(x);
  origin_.set_y(y);
  scale_ = scale;

  const ui::LayerAnimator::PreemptionStrategy strategy =
      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET;
  const base::TimeDelta duration =
      base::TimeDelta::FromMilliseconds(duration_in_ms);

  ui::ScopedLayerAnimationSettings root_layer_settings(
      root_window_->layer()->GetAnimator());
  root_layer_settings.AddObserver(this);
  root_layer_settings.SetPreemptionStrategy(strategy);
  root_layer_settings.SetTweenType(tween_type);
  root_layer_settings.SetTransitionDuration(duration);

  display::Display display =
      display::Screen::GetScreen()->GetDisplayNearestWindow(root_window_);
  std::unique_ptr<RootWindowTransformer> transformer(
      CreateRootWindowTransformerForDisplay(root_window_, display));

  // Inverse the transformation on the keyboard container so the keyboard will
  // remain zoomed out. Apply the same animation settings to it.
  // Note: if |scale_| is 1.0f, the transform matrix will be an identity matrix.
  // Applying the inverse of an identity matrix will not change the
  // transformation.
  // TODO(spqchan): Find a way to sync the layer animations together.
  aura::Window* virtual_keyboard_container =
      root_window_->GetChildById(kShellWindowId_ImeWindowParentContainer);

  gfx::Transform vk_transform;
  if (GetMagnifierTransform().GetInverse(&vk_transform)) {
    ui::ScopedLayerAnimationSettings vk_layer_settings(
        virtual_keyboard_container->layer()->GetAnimator());
    vk_layer_settings.SetPreemptionStrategy(strategy);
    vk_layer_settings.SetTweenType(tween_type);
    vk_layer_settings.SetTransitionDuration(duration);
    virtual_keyboard_container->SetTransform(vk_transform);
  }

  RootWindowController::ForWindow(root_window_)
      ->ash_host()
      ->SetRootWindowTransformer(std::move(transformer));

  if (duration_in_ms > 0)
    is_on_animation_ = true;

  return true;
}

void MagnificationController::StartOrStopScrollIfNecessary() {
  // This value controls the scrolling speed.
  const int kMoveOffset = 40;
  if (is_on_animation_) {
    if (scroll_direction_ == SCROLL_NONE)
      root_window_->layer()->GetAnimator()->StopAnimating();
    return;
  }

  gfx::PointF new_origin = origin_;
  switch (scroll_direction_) {
    case SCROLL_NONE:
      // No need to take action.
      return;
    case SCROLL_LEFT:
      new_origin.Offset(-kMoveOffset, 0);
      break;
    case SCROLL_RIGHT:
      new_origin.Offset(kMoveOffset, 0);
      break;
    case SCROLL_UP:
      new_origin.Offset(0, -kMoveOffset);
      break;
    case SCROLL_DOWN:
      new_origin.Offset(0, kMoveOffset);
      break;
  }
  RedrawDIP(new_origin, scale_, kDefaultAnimationDurationInMs,
            kDefaultAnimationTweenType);
}

void MagnificationController::RedrawKeepingMousePosition(
    float scale,
    bool animate,
    bool ignore_mouse_change) {
  gfx::Point mouse_in_root = point_of_interest_in_root_;
  // mouse_in_root is invalid value when the cursor is hidden.
  if (!root_window_->bounds().Contains(mouse_in_root))
    mouse_in_root = root_window_->bounds().CenterPoint();

  const gfx::PointF origin = gfx::PointF(
      mouse_in_root.x() - (scale_ / scale) * (mouse_in_root.x() - origin_.x()),
      mouse_in_root.y() - (scale_ / scale) * (mouse_in_root.y() - origin_.y()));
  bool changed =
      RedrawDIP(origin, scale, animate ? kDefaultAnimationDurationInMs : 0,
                kDefaultAnimationTweenType);
  if (!ignore_mouse_change && changed)
    AfterAnimationMoveCursorTo(mouse_in_root);
}

void MagnificationController::OnMouseMove(const gfx::Point& location) {
  DCHECK(root_window_);

  gfx::Point mouse(location);
  int margin = kCursorPanningMargin / scale_;  // No need to consider DPI.

  // Reduce the bottom margin if the keyboard is visible.
  bool reduce_bottom_margin =
      keyboard::KeyboardController::Get()->IsKeyboardVisible();

  MoveMagnifierWindowFollowPoint(mouse, margin, margin, margin, margin,
                                 reduce_bottom_margin);
}

void MagnificationController::AfterAnimationMoveCursorTo(
    const gfx::Point& location) {
  DCHECK(root_window_);

  aura::client::CursorClient* cursor_client =
      aura::client::GetCursorClient(root_window_);
  if (cursor_client) {
    // When cursor is invisible, do not move or show the cursor after the
    // animation.
    if (!cursor_client->IsCursorVisible())
      return;
    cursor_client->DisableMouseEvents();
  }
  move_cursor_after_animation_ = true;
  position_after_animation_ = location;
}

bool MagnificationController::IsMagnified() const {
  return scale_ >= kMinMagnifiedScaleThreshold;
}

gfx::RectF MagnificationController::GetWindowRectDIP(float scale) const {
  const gfx::Size size_in_dip = root_window_->bounds().size();
  const float width = size_in_dip.width() / scale;
  const float height = size_in_dip.height() / scale;

  return gfx::RectF(origin_.x(), origin_.y(), width, height);
}

gfx::Size MagnificationController::GetHostSizeDIP() const {
  return root_window_->bounds().size();
}

void MagnificationController::ValidateScale(float* scale) {
  *scale = base::ClampToRange(*scale, kNonMagnifiedScale, kMaxMagnifiedScale);
  DCHECK(kNonMagnifiedScale <= *scale && *scale <= kMaxMagnifiedScale);
}

bool MagnificationController::ProcessGestures() {
  bool cancel_pressed_touches = false;

  std::vector<std::unique_ptr<ui::GestureEvent>> gestures =
      gesture_provider_->GetAndResetPendingGestures();
  for (const auto& gesture : gestures) {
    const ui::GestureEventDetails& details = gesture->details();

    if (details.touch_points() != 2)
      continue;

    if (gesture->type() == ui::ET_GESTURE_PINCH_BEGIN) {
      original_scale_ = scale_;

      // Start consuming touch events with cancelling existing touches.
      if (!consume_touch_event_)
        cancel_pressed_touches = true;
    } else if (gesture->type() == ui::ET_GESTURE_PINCH_UPDATE) {
      float scale = GetScale() * details.scale();
      ValidateScale(&scale);

      // |details.bounding_box().CenterPoint()| return center of touch points
      // of gesture in non-dip screen coordinate.
      gfx::PointF gesture_center =
          gfx::PointF(details.bounding_box().CenterPoint());

      // Root transform does dip scaling, screen magnification scaling and
      // translation. Apply inverse transform to convert non-dip screen
      // coordinate to dip logical coordinate.
      root_window_->GetHost()->GetInverseRootTransform().TransformPoint(
          &gesture_center);

      // Calcualte new origin to keep the distance between |gesture_center|
      // and |origin| same in screen coordinate. This means the following
      // equation.
      // (gesture_center.x - origin_.x) * scale_ =
      //   (gesture_center.x - new_origin.x) * scale
      // If you solve it for |new_origin|, you will get the following formula.
      const gfx::PointF origin = gfx::PointF(
          gesture_center.x() -
              (scale_ / scale) * (gesture_center.x() - origin_.x()),
          gesture_center.y() -
              (scale_ / scale) * (gesture_center.y() - origin_.y()));

      RedrawDIP(origin, scale, 0, kDefaultAnimationTweenType);
    } else if (gesture->type() == ui::ET_GESTURE_SCROLL_BEGIN) {
      original_origin_ = origin_;

      // Start consuming all touch events with cancelling existing touches.
      if (!consume_touch_event_)
        cancel_pressed_touches = true;
    } else if (gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
      // Divide by scale to keep scroll speed same at any scale.
      float new_x = origin_.x() + (-1.0f * details.scroll_x() / scale_);
      float new_y = origin_.y() + (-1.0f * details.scroll_y() / scale_);

      RedrawDIP(gfx::PointF(new_x, new_y), scale_, 0,
                kDefaultAnimationTweenType);
    }
  }

  return cancel_pressed_touches;
}

void MagnificationController::MoveMagnifierWindowFollowPoint(
    const gfx::Point& point,
    int x_panning_margin,
    int y_panning_margin,
    int x_target_margin,
    int y_target_margin,
    bool reduce_bottom_margin) {
  DCHECK(root_window_);
  bool start_zoom = false;

  const gfx::Rect window_rect = GetViewportRect();
  const int left = window_rect.x();
  const int right = window_rect.right();

  int x_diff = 0;
  if (point.x() < left + x_panning_margin) {
    // Panning left.
    x_diff = point.x() - (left + x_target_margin);
    start_zoom = true;
  } else if (right - x_panning_margin < point.x()) {
    // Panning right.
    x_diff = point.x() - (right - x_target_margin);
    start_zoom = true;
  }
  int x = left + x_diff;

  const int top = window_rect.y();
  const int bottom = window_rect.bottom();

  // If |reduce_bottom_margin| is true, use kKeyboardBottomPanningMargin instead
  // of |y_panning_margin|. This is to prevent the magnifier from panning when
  // the user is trying to interact with the bottom of the keyboard.
  const int bottom_panning_margin = reduce_bottom_margin
                                        ? kKeyboardBottomPanningMargin / scale_
                                        : y_panning_margin;

  int y_diff = 0;
  if (point.y() < top + y_panning_margin) {
    // Panning up.
    y_diff = point.y() - (top + y_target_margin);
    start_zoom = true;
  } else if (bottom - bottom_panning_margin < point.y()) {
    // Panning down.
    const int bottom_target_margin =
        reduce_bottom_margin ? std::min(bottom_panning_margin, y_target_margin)
                             : y_target_margin;
    y_diff = point.y() - (bottom - bottom_target_margin);
    start_zoom = true;
  }
  int y = top + y_diff;
  if (start_zoom && !is_on_animation_) {
    bool ret = RedrawDIP(gfx::PointF(x, y), scale_,
                         0,  // No animation on panning.
                         kDefaultAnimationTweenType);

    if (ret) {
      // If the magnified region is moved, hides the mouse cursor and moves it.
      if (x_diff != 0 || y_diff != 0)
        MoveCursorTo(root_window_->GetHost(), point);
    }
  }
}

void MagnificationController::MoveMagnifierWindowCenterPoint(
    const gfx::Point& point) {
  DCHECK(root_window_);

  gfx::Rect window_rect = GetViewportRect();

  // Reduce the viewport bounds if the keyboard is up.
  if (keyboard::KeyboardController::Get()->IsEnabled()) {
    gfx::Rect keyboard_rect = keyboard::KeyboardController::Get()
                                  ->GetKeyboardWindow()
                                  ->GetBoundsInScreen();
    window_rect.set_height(window_rect.height() -
                           keyboard_rect.height() / scale_);
  }

  if (point == window_rect.CenterPoint())
    return;

  if (!is_on_animation_) {
    // With animation on panning.
    RedrawDIP(
        gfx::PointF(window_rect.origin() + (point - window_rect.CenterPoint())),
        scale_, kDefaultAnimationDurationInMs, kCenterCaretAnimationTweenType);
  }
}

void MagnificationController::MoveMagnifierWindowFollowRect(
    const gfx::Rect& rect) {
  DCHECK(root_window_);
  bool should_pan = false;

  const gfx::Rect viewport_rect = GetViewportRect();
  const int left = viewport_rect.x();
  const int right = viewport_rect.right();
  const gfx::Point rect_center = rect.CenterPoint();

  int x = left;
  if (rect.x() < left || right < rect.right()) {
    // Panning horizontally.
    x = rect_center.x() - viewport_rect.width() / 2;
    should_pan = true;
  }

  const int top = viewport_rect.y();
  const int bottom = viewport_rect.bottom();

  int y = top;
  if (rect.y() < top || bottom < rect.bottom()) {
    // Panning vertically.
    y = rect_center.y() - viewport_rect.height() / 2;
    should_pan = true;
  }

  if (should_pan) {
    if (is_on_animation_) {
      root_window_->layer()->GetAnimator()->StopAnimating();
      is_on_animation_ = false;
    }
    RedrawDIP(gfx::PointF(x, y), scale_,
              0,  // No animation on panning.
              kDefaultAnimationTweenType);
  }
}

void MagnificationController::OnMoveMagnifierTimer() {
  MoveMagnifierWindowCenterPoint(caret_point_);
}

}  // namespace ash
