Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ash / magnifier / magnification_controller.cc
index 0df6e12..f43154f 100644 (file)
@@ -4,16 +4,24 @@
 
 #include "ash/magnifier/magnification_controller.h"
 
+#include "ash/accelerators/accelerator_controller.h"
 #include "ash/accessibility_delegate.h"
+#include "ash/ash_switches.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/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/system/tray/system_tray_delegate.h"
+#include "base/command_line.h"
 #include "base/synchronization/waitable_event.h"
+#include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/cursor_client.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/root_window_transformer.h"
 #include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/ime/input_method.h"
+#include "ui/base/ime/input_method_observer.h"
+#include "ui/base/ime/text_input_client.h"
 #include "ui/compositor/dip_util.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animation_observer.h"
@@ -25,7 +33,8 @@
 #include "ui/gfx/point_f.h"
 #include "ui/gfx/rect_conversions.h"
 #include "ui/gfx/screen.h"
-#include "ui/views/corewm/compound_event_filter.h"
+#include "ui/wm/core/compound_event_filter.h"
+#include "ui/wm/core/coordinate_conversion.h"
 
 namespace {
 
@@ -41,11 +50,14 @@ const float kScrollScaleChangeFactor = 0.05f;
 // |kPanningMergin| from the edge, the view-port moves.
 const int kPanningMergin = 100;
 
-void MoveCursorTo(aura::RootWindow* root_window,
-                  const gfx::Point& root_location) {
+// Gives a little panning margin for following caret, so that we will move the
+// view-port before the caret is completely out of sight.
+const int kCaretPanningMargin = 10;
+
+void MoveCursorTo(aura::WindowTreeHost* host, const gfx::Point& root_location) {
   gfx::Point3F host_location_3f(root_location);
-  root_window->GetRootTransform().TransformPoint(&host_location_3f);
-  root_window->MoveCursorToHostLocation(
+  host->GetRootTransform().TransformPoint(&host_location_3f);
+  host->MoveCursorToHostLocation(
       gfx::ToCeiledPoint(host_location_3f.AsPointF()));
 }
 
@@ -59,39 +71,38 @@ namespace ash {
 class MagnificationControllerImpl : virtual public MagnificationController,
                                     public ui::EventHandler,
                                     public ui::ImplicitAnimationObserver,
-                                    public aura::WindowObserver {
+                                    public aura::WindowObserver,
+                                    public ui::InputMethodObserver {
  public:
   MagnificationControllerImpl();
-  virtual ~MagnificationControllerImpl();
+  ~MagnificationControllerImpl() override;
 
   // MagnificationController overrides:
-  virtual void SetEnabled(bool enabled) OVERRIDE;
-  virtual bool IsEnabled() const OVERRIDE;
-  virtual void SetScale(float scale, bool animate) OVERRIDE;
-  virtual float GetScale() const OVERRIDE { return scale_; }
-  virtual void MoveWindow(int x, int y, bool animate) OVERRIDE;
-  virtual void MoveWindow(const gfx::Point& point, bool animate) OVERRIDE;
-  virtual gfx::Point GetWindowPosition() const OVERRIDE {
+  void SetEnabled(bool enabled) override;
+  bool IsEnabled() const override;
+  void SetScale(float scale, bool animate) override;
+  float GetScale() const override { return scale_; }
+  void MoveWindow(int x, int y, bool animate) override;
+  void MoveWindow(const gfx::Point& point, bool animate) override;
+  gfx::Point GetWindowPosition() const override {
     return gfx::ToFlooredPoint(origin_);
   }
-  virtual void EnsureRectIsVisible(const gfx::Rect& rect,
-                                   bool animate) OVERRIDE;
-  virtual void EnsurePointIsVisible(const gfx::Point& point,
-                                    bool animate) OVERRIDE;
+  void SetScrollDirection(ScrollDirection direction) override;
+
   // For test
-  virtual gfx::Point GetPointOfInterestForTesting() OVERRIDE {
+  gfx::Point GetPointOfInterestForTesting() override {
     return point_of_interest_;
   }
 
  private:
   // ui::ImplicitAnimationObserver overrides:
-  virtual void OnImplicitAnimationsCompleted() OVERRIDE;
+  void OnImplicitAnimationsCompleted() override;
 
   // aura::WindowObserver overrides:
-  virtual void OnWindowDestroying(aura::Window* root_window) OVERRIDE;
-  virtual void OnWindowBoundsChanged(aura::Window* window,
-                                     const gfx::Rect& old_bounds,
-                                     const gfx::Rect& new_bounds) OVERRIDE;
+  void OnWindowDestroying(aura::Window* root_window) override;
+  void OnWindowBoundsChanged(aura::Window* window,
+                             const gfx::Rect& old_bounds,
+                             const gfx::Rect& new_bounds) override;
 
   // Redraws the magnification window with the given origin position and the
   // given scale. Returns true if the window is changed; otherwise, false.
@@ -100,22 +111,18 @@ class MagnificationControllerImpl : virtual public MagnificationController,
   bool Redraw(const gfx::PointF& position, float scale, bool animate);
   bool RedrawDIP(const gfx::PointF& position, float scale, bool animate);
 
+  // 1) If the screen is scrolling (i.e. animating) and should scroll further,
+  // it does nothing.
+  // 2) If the screen is scrolling (i.e. animating) and the direction is NONE,
+  // it stops the scrolling animation.
+  // 3) If the direction is set to value other than NONE, it starts the
+  // scrolling/ animation towards that direction.
+  void StartOrStopScrollIfNecessary();
+
   // Redraw with the given zoom scale keeping the mouse cursor location. In
   // other words, zoom (or unzoom) centering around the cursor.
   void RedrawKeepingMousePosition(float scale, bool animate);
 
-  // Ensures that the given point, rect or last mouse location is inside
-  // magnification window. If not, the controller moves the window to contain
-  // the given point/rect.
-  void EnsureRectIsVisibleWithScale(const gfx::Rect& target_rect,
-                                    float scale,
-                                    bool animate);
-  void EnsureRectIsVisibleDIP(const gfx::Rect& target_rect_in_dip,
-                              float scale,
-                              bool animate);
-  void EnsurePointIsVisibleWithScale(const gfx::Point& point,
-                                     float scale,
-                                     bool animate);
   void OnMouseMove(const gfx::Point& location);
 
   // Move the mouse cursot to the given point. Actual move will be done when
@@ -142,9 +149,29 @@ class MagnificationControllerImpl : virtual public MagnificationController,
   void ValidateScale(float* scale);
 
   // ui::EventHandler overrides:
-  virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
-  virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
-  virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
+  void OnMouseEvent(ui::MouseEvent* event) override;
+  void OnScrollEvent(ui::ScrollEvent* event) override;
+  void OnTouchEvent(ui::TouchEvent* event) override;
+
+  // Moves the view port when |point| is located within
+  // |x_panning_margin| and |y_pannin_margin| to the edge of the visible
+  // window region. The view port will be moved so that the |point| will be
+  // moved to the point where it has |x_target_margin| and |y_target_margin|
+  // to the edge of the visible region.
+  void MoveMagnifierWindow(const gfx::Point& point,
+                           int x_panning_margin,
+                           int y_panning_margin,
+                           int x_target_margin,
+                           int y_target_margin);
+
+  // ui::InputMethodObserver:
+  void OnTextInputTypeChanged(const ui::TextInputClient* client) override {}
+  void OnFocus() override {}
+  void OnBlur() override {}
+  void OnTextInputStateChanged(const ui::TextInputClient* client) override {}
+  void OnInputMethodDestroyed(const ui::InputMethod* input_method) override {}
+  void OnShowImeIfNeeded() override {}
+  void OnCaretBoundsChanged(const ui::TextInputClient* client) override;
 
   // Target root window. This must not be NULL.
   aura::Window* root_window_;
@@ -169,6 +196,10 @@ class MagnificationControllerImpl : virtual public MagnificationController,
   float scale_;
   gfx::PointF origin_;
 
+  ScrollDirection scroll_direction_;
+
+  ui::InputMethod* input_method_;  // Not owned.
+
   DISALLOW_COPY_AND_ASSIGN(MagnificationControllerImpl);
 };
 
@@ -176,17 +207,22 @@ class MagnificationControllerImpl : virtual public MagnificationController,
 // MagnificationControllerImpl:
 
 MagnificationControllerImpl::MagnificationControllerImpl()
-    : root_window_(ash::Shell::GetPrimaryRootWindow()),
+    : root_window_(Shell::GetPrimaryRootWindow()),
       is_on_animation_(false),
       is_enabled_(false),
       move_cursor_after_animation_(false),
-      scale_(kNonMagnifiedScale) {
+      scale_(kNonMagnifiedScale),
+      scroll_direction_(SCROLL_NONE),
+      input_method_(NULL) {
   Shell::GetInstance()->AddPreTargetHandler(this);
   root_window_->AddObserver(this);
   point_of_interest_ = root_window_->bounds().CenterPoint();
 }
 
 MagnificationControllerImpl::~MagnificationControllerImpl() {
+  if (input_method_)
+    input_method_->RemoveObserver(this);
+
   root_window_->RemoveObserver(this);
 
   Shell::GetInstance()->RemovePreTargetHandler(this);
@@ -271,9 +307,10 @@ bool MagnificationControllerImpl::RedrawDIP(const gfx::PointF& position_in_dip,
 
   gfx::Display display =
       Shell::GetScreen()->GetDisplayNearestWindow(root_window_);
-  scoped_ptr<aura::RootWindowTransformer> transformer(
-      internal::CreateRootWindowTransformerForDisplay(root_window_, display));
-  root_window_->GetDispatcher()->SetRootWindowTransformer(transformer.Pass());
+  scoped_ptr<RootWindowTransformer> transformer(
+      CreateRootWindowTransformerForDisplay(root_window_, display));
+  GetRootWindowController(root_window_)->ash_host()->SetRootWindowTransformer(
+      transformer.Pass());
 
   if (animate)
     is_on_animation_ = true;
@@ -281,108 +318,42 @@ bool MagnificationControllerImpl::RedrawDIP(const gfx::PointF& position_in_dip,
   return true;
 }
 
-void MagnificationControllerImpl::EnsureRectIsVisibleWithScale(
-    const gfx::Rect& target_rect,
-    float scale,
-    bool animate) {
-  const gfx::Rect target_rect_in_dip =
-      ui::ConvertRectToDIP(root_window_->layer(), target_rect);
-  EnsureRectIsVisibleDIP(target_rect_in_dip, scale, animate);
-}
-
-void MagnificationControllerImpl::EnsureRectIsVisibleDIP(
-    const gfx::Rect& target_rect,
-    float scale,
-    bool animate) {
-  ValidateScale(&scale);
-
-  const gfx::Rect window_rect = gfx::ToEnclosingRect(GetWindowRectDIP(scale));
-  if (scale == scale_ && window_rect.Contains(target_rect))
+void MagnificationControllerImpl::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;
+  }
 
-  // TODO(yoshiki): Un-zoom and change the scale if the magnification window
-  // can't contain the whole given rect.
-
-  gfx::Rect rect = window_rect;
-  if (target_rect.width() > rect.width())
-    rect.set_x(target_rect.CenterPoint().x() - rect.x() / 2);
-  else if (target_rect.right() < rect.x())
-    rect.set_x(target_rect.right());
-  else if (rect.right() < target_rect.x())
-    rect.set_x(target_rect.x() - rect.width());
-
-  if (rect.height() > window_rect.height())
-    rect.set_y(target_rect.CenterPoint().y() - rect.y() / 2);
-  else if (target_rect.bottom() < rect.y())
-    rect.set_y(target_rect.bottom());
-  else if (rect.bottom() < target_rect.y())
-    rect.set_y(target_rect.y() - rect.height());
-
-  RedrawDIP(rect.origin(), scale, animate);
-}
-
-void MagnificationControllerImpl::EnsurePointIsVisibleWithScale(
-    const gfx::Point& point,
-    float scale,
-    bool animate) {
-  EnsureRectIsVisibleWithScale(gfx::Rect(point, gfx::Size(0, 0)),
-                               scale,
-                               animate);
+  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_, true);
 }
 
 void MagnificationControllerImpl::OnMouseMove(const gfx::Point& location) {
   DCHECK(root_window_);
 
   gfx::Point mouse(location);
-
-  int x = origin_.x();
-  int y = origin_.y();
-  bool start_zoom = false;
-
-  const gfx::Rect window_rect = gfx::ToEnclosingRect(GetWindowRectDIP(scale_));
-  const int left = window_rect.x();
-  const int right = window_rect.right();
   int margin = kPanningMergin / scale_;  // No need to consider DPI.
-
-  int x_diff = 0;
-
-  if (mouse.x() < left + margin) {
-    // Panning left.
-    x_diff = mouse.x() - (left + margin);
-    start_zoom = true;
-  } else if (right - margin < mouse.x()) {
-    // Panning right.
-    x_diff = mouse.x() - (right - margin);
-    start_zoom = true;
-  }
-  x = left + x_diff;
-
-  const int top = window_rect.y();
-  const int bottom = window_rect.bottom();
-
-  int y_diff = 0;
-  if (mouse.y() < top + margin) {
-    // Panning up.
-    y_diff = mouse.y() - (top + margin);
-    start_zoom = true;
-  } else if (bottom - margin < mouse.y()) {
-    // Panning down.
-    y_diff = mouse.y() - (bottom - margin);
-    start_zoom = true;
-  }
-  y = top + y_diff;
-
-  if (start_zoom && !is_on_animation_) {
-    // No animation on panning.
-    bool animate = false;
-    bool ret = RedrawDIP(gfx::Point(x, y), scale_, animate);
-
-    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_->GetDispatcher(), mouse);
-    }
-  }
+  MoveMagnifierWindow(mouse, margin, margin, margin, margin);
 }
 
 void MagnificationControllerImpl::AfterAnimationMoveCursorTo(
@@ -437,7 +408,7 @@ void MagnificationControllerImpl::OnImplicitAnimationsCompleted() {
     return;
 
   if (move_cursor_after_animation_) {
-    MoveCursorTo(root_window_->GetDispatcher(), position_after_animation_);
+    MoveCursorTo(root_window_->GetHost(), position_after_animation_);
     move_cursor_after_animation_ = false;
 
     aura::client::CursorClient* cursor_client =
@@ -447,6 +418,8 @@ void MagnificationControllerImpl::OnImplicitAnimationsCompleted() {
   }
 
   is_on_animation_ = false;
+
+  StartOrStopScrollIfNecessary();
 }
 
 void MagnificationControllerImpl::OnWindowDestroying(
@@ -503,7 +476,7 @@ void MagnificationControllerImpl::SetScale(float scale, bool animate) {
     return;
 
   ValidateScale(&scale);
-  ash::Shell::GetInstance()->accessibility_delegate()->
+  Shell::GetInstance()->accessibility_delegate()->
       SaveScreenMagnifierScale(scale);
   RedrawKeepingMousePosition(scale, animate);
 }
@@ -523,28 +496,24 @@ void MagnificationControllerImpl::MoveWindow(const gfx::Point& point,
   Redraw(point, scale_, animate);
 }
 
-void MagnificationControllerImpl::EnsureRectIsVisible(
-    const gfx::Rect& target_rect,
-    bool animate) {
-  if (!is_enabled_)
-    return;
-
-  EnsureRectIsVisibleWithScale(target_rect, scale_, animate);
-}
-
-void MagnificationControllerImpl::EnsurePointIsVisible(
-    const gfx::Point& point,
-    bool animate) {
-  if (!is_enabled_)
-    return;
-
-  EnsurePointIsVisibleWithScale(point, scale_, animate);
+void MagnificationControllerImpl::SetScrollDirection(
+    ScrollDirection direction) {
+  scroll_direction_ = direction;
+  StartOrStopScrollIfNecessary();
 }
 
 void MagnificationControllerImpl::SetEnabled(bool enabled) {
+  Shell* shell = Shell::GetInstance();
   if (enabled) {
+    if (!input_method_) {
+      input_method_ =
+          root_window_->GetProperty(aura::client::kRootWindowInputMethodKey);
+      if (input_method_)
+        input_method_->AddObserver(this);
+    }
+
     float scale =
-        ash::Shell::GetInstance()->accessibility_delegate()->
+        Shell::GetInstance()->accessibility_delegate()->
         GetSavedScreenMagnifierScale();
     if (scale <= 0.0f)
       scale = kInitialMagnifiedScale;
@@ -556,13 +525,17 @@ void MagnificationControllerImpl::SetEnabled(bool enabled) {
 
     is_enabled_ = enabled;
     RedrawKeepingMousePosition(scale, true);
-    ash::Shell::GetInstance()->accessibility_delegate()->
-        SaveScreenMagnifierScale(scale);
+    shell->accessibility_delegate()->SaveScreenMagnifierScale(scale);
   } else {
     // Do nothing, if already disabled.
     if (!is_enabled_)
       return;
 
+    if (input_method_) {
+      input_method_->RemoveObserver(this);
+      input_method_ = NULL;
+    }
+
     RedrawKeepingMousePosition(kNonMagnifiedScale, true);
     is_enabled_ = enabled;
   }
@@ -582,7 +555,8 @@ void MagnificationControllerImpl::OnMouseEvent(ui::MouseEvent* event) {
 
   if (root_bounds.Contains(event->root_location())) {
     // This must be before |SwitchTargetRootWindow()|.
-    point_of_interest_ = event->root_location();
+    if (event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)
+      point_of_interest_ = event->root_location();
 
     if (current_root != root_window_) {
       DCHECK(current_root);
@@ -623,6 +597,87 @@ void MagnificationControllerImpl::OnTouchEvent(ui::TouchEvent* event) {
   }
 }
 
+void MagnificationControllerImpl::MoveMagnifierWindow(const gfx::Point& point,
+                                                      int x_panning_margin,
+                                                      int y_panning_margin,
+                                                      int x_target_margin,
+                                                      int y_target_margin) {
+  DCHECK(root_window_);
+  int x = origin_.x();
+  int y = origin_.y();
+  bool start_zoom = false;
+
+  const gfx::Rect window_rect = gfx::ToEnclosingRect(GetWindowRectDIP(scale_));
+  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;
+  }
+  x = left + x_diff;
+
+  const int top = window_rect.y();
+  const int bottom = window_rect.bottom();
+
+  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 - y_panning_margin < point.y()) {
+    // Panning down.
+    y_diff = point.y() - (bottom - y_target_margin);
+    start_zoom = true;
+  }
+  y = top + y_diff;
+  if (start_zoom && !is_on_animation_) {
+    // No animation on panning.
+    bool animate = false;
+    bool ret = RedrawDIP(gfx::Point(x, y), scale_, animate);
+
+    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 MagnificationControllerImpl::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 caret_origin = caret_bounds.origin();
+  // caret_origin in |root_window_| coordinates.
+  wm::ConvertPointFromScreen(root_window_, &caret_origin);
+
+  // Visible window_rect in |root_window_| coordinates.
+  const gfx::Rect visible_window_rect =
+      gfx::ToEnclosingRect(GetWindowRectDIP(scale_));
+
+  const int panning_margin = kCaretPanningMargin / scale_;
+  MoveMagnifierWindow(caret_origin,
+                      panning_margin,
+                      panning_margin,
+                      visible_window_rect.width() / 2,
+                      visible_window_rect.height() / 2);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // MagnificationController: