| Index: ash/magnifier/magnification_controller.cc
|
| diff --git a/ash/magnifier/magnification_controller.cc b/ash/magnifier/magnification_controller.cc
|
| index a6ad0a1a1ad601877d8aa578781503fb3acfbffa..f7a4e9a76b45874763b01e945d2535e6a5b1192e 100644
|
| --- a/ash/magnifier/magnification_controller.cc
|
| +++ b/ash/magnifier/magnification_controller.cc
|
| @@ -16,6 +16,7 @@
|
| #include "ash/system/tray/system_tray_delegate.h"
|
| #include "base/command_line.h"
|
| #include "base/synchronization/waitable_event.h"
|
| +#include "base/timer/timer.h"
|
| #include "ui/aura/client/aura_constants.h"
|
| #include "ui/aura/client/cursor_client.h"
|
| #include "ui/aura/window.h"
|
| @@ -47,13 +48,25 @@ const float kNonMagnifiedScale = 1.0f;
|
| const float kInitialMagnifiedScale = 2.0f;
|
| const float kScrollScaleChangeFactor = 0.05f;
|
|
|
| +// Default animation parameters for redrawing the magnification window.
|
| +const gfx::Tween::Type kDefaultAnimationTweenType = gfx::Tween::EASE_OUT;
|
| +const 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.
|
| +const gfx::Tween::Type kCenterCaretAnimationTweenType = gfx::Tween::LINEAR;
|
| +
|
| +// The delay of the timer for moving magnifier window for centering the text
|
| +// input focus.
|
| +const int kMoveMagnifierDelayInMs = 10;
|
| +
|
| // Threadshold of panning. If the cursor moves to within pixels (in DIP) of
|
| -// |kPanningMergin| from the edge, the view-port moves.
|
| -const int kPanningMergin = 100;
|
| +// |kCursorPanningMargin| from the edge, the view-port moves.
|
| +const int kCursorPanningMargin = 100;
|
|
|
| -// 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;
|
| +// Threadshold of panning. If the caret moves to within pixels (in DIP) of
|
| +// |kCaretPanningMargin| from the edge, the view-port moves.
|
| +const int kCaretPanningMargin = 50;
|
|
|
| void MoveCursorTo(aura::WindowTreeHost* host, const gfx::Point& root_location) {
|
| gfx::Point3F host_location_3f(root_location);
|
| @@ -81,6 +94,8 @@ class MagnificationControllerImpl : virtual public MagnificationController,
|
| // MagnificationController overrides:
|
| void SetEnabled(bool enabled) override;
|
| bool IsEnabled() const override;
|
| + void SetKeepFocusCentered(bool keep_focus_centered) override;
|
| + bool KeepFocusCentered() const override;
|
| void SetScale(float scale, bool animate) override;
|
| float GetScale() const override { return scale_; }
|
| void MoveWindow(int x, int y, bool animate) override;
|
| @@ -103,6 +118,10 @@ class MagnificationControllerImpl : virtual public MagnificationController,
|
|
|
| bool IsOnAnimationForTesting() const override { return is_on_animation_; }
|
|
|
| + void DisableMoveMagnifierDelayForTesting() override {
|
| + disable_move_magnifier_delay_ = true;
|
| + }
|
| +
|
| private:
|
| // ui::ImplicitAnimationObserver overrides:
|
| void OnImplicitAnimationsCompleted() override;
|
| @@ -118,7 +137,16 @@ class MagnificationControllerImpl : virtual public MagnificationController,
|
| // These methods should be called internally just after the scale and/or
|
| // the position are changed to redraw the window.
|
| bool Redraw(const gfx::PointF& position, float scale, bool animate);
|
| - bool RedrawDIP(const gfx::PointF& position, float scale, bool animate);
|
| +
|
| + // Redraws the magnification window with the given origin position in dip and
|
| + // the given scale. Returns true if the window is changed; otherwise, false.
|
| + // The last two parameters specify the animation duration and tween type.
|
| + // If |animation_in_ms| is zero, there will be no animation, and |tween_type|
|
| + // will be ignored.
|
| + bool RedrawDIP(const gfx::PointF& position_in_dip,
|
| + float scale,
|
| + int animation_in_ms,
|
| + gfx::Tween::Type tween_type);
|
|
|
| // 1) If the screen is scrolling (i.e. animating) and should scroll further,
|
| // it does nothing.
|
| @@ -166,11 +194,18 @@ class MagnificationControllerImpl : virtual public MagnificationController,
|
| int x_target_margin,
|
| int y_target_margin);
|
|
|
| + // Moves the view port to center |point| in magnifier screen.
|
| + void MoveMagnifierWindowCenterPoint(const gfx::Point& point);
|
| +
|
| // Moves the viewport so that |rect| is fully visible. If |rect| is larger
|
| // than the viewport horizontally or vertically, the viewport will be moved
|
| // to center the |rect| in that dimension.
|
| void MoveMagnifierWindowFollowRect(const gfx::Rect& rect);
|
|
|
| + // Invoked when |move_magnifier_timer_| fires to move the magnifier window to
|
| + // follow the caret.
|
| + void OnMoveMagnifierTimer();
|
| +
|
| // ui::InputMethodObserver:
|
| void OnTextInputTypeChanged(const ui::TextInputClient* client) override {}
|
| void OnFocus() override {}
|
| @@ -189,6 +224,8 @@ class MagnificationControllerImpl : virtual public MagnificationController,
|
|
|
| bool is_enabled_;
|
|
|
| + bool keep_focus_centered_;
|
| +
|
| // True if the cursor needs to move the given position after the animation
|
| // will be finished. When using this, set |position_after_animation_| as well.
|
| bool move_cursor_after_animation_;
|
| @@ -207,6 +244,16 @@ class MagnificationControllerImpl : virtual public MagnificationController,
|
|
|
| ui::InputMethod* input_method_; // Not owned.
|
|
|
| + // Timer for moving magnifier window when it fires.
|
| + base::OneShotTimer<MagnificationControllerImpl> move_magnifier_timer_;
|
| +
|
| + // Most recent caret position in |root_window_| coordinates.
|
| + gfx::Point caret_point_;
|
| +
|
| + // Flag for disabling moving magnifier delay. It can only be true in testing
|
| + // mode.
|
| + bool disable_move_magnifier_delay_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(MagnificationControllerImpl);
|
| };
|
|
|
| @@ -217,10 +264,12 @@ MagnificationControllerImpl::MagnificationControllerImpl()
|
| : root_window_(Shell::GetPrimaryRootWindow()),
|
| is_on_animation_(false),
|
| is_enabled_(false),
|
| + keep_focus_centered_(false),
|
| move_cursor_after_animation_(false),
|
| scale_(kNonMagnifiedScale),
|
| scroll_direction_(SCROLL_NONE),
|
| - input_method_(NULL) {
|
| + input_method_(NULL),
|
| + disable_move_magnifier_delay_(false) {
|
| Shell::GetInstance()->AddPreTargetHandler(this);
|
| root_window_->AddObserver(this);
|
| point_of_interest_ = root_window_->bounds().CenterPoint();
|
| @@ -248,7 +297,9 @@ void MagnificationControllerImpl::RedrawKeepingMousePosition(
|
| (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);
|
| + bool changed = RedrawDIP(origin, scale,
|
| + animate ? kDefaultAnimationDurationInMs : 0,
|
| + kDefaultAnimationTweenType);
|
| if (changed)
|
| AfterAnimationMoveCursorTo(mouse_in_root);
|
| }
|
| @@ -258,12 +309,15 @@ bool MagnificationControllerImpl::Redraw(const gfx::PointF& position,
|
| bool animate) {
|
| const gfx::PointF position_in_dip =
|
| ui::ConvertPointToDIP(root_window_->layer(), position);
|
| - return RedrawDIP(position_in_dip, scale, animate);
|
| + return RedrawDIP(position_in_dip, scale,
|
| + animate ? kDefaultAnimationDurationInMs : 0,
|
| + kDefaultAnimationTweenType);
|
| }
|
|
|
| bool MagnificationControllerImpl::RedrawDIP(const gfx::PointF& position_in_dip,
|
| float scale,
|
| - bool animate) {
|
| + int duration_in_ms,
|
| + gfx::Tween::Type tween_type) {
|
| DCHECK(root_window_);
|
|
|
| float x = position_in_dip.x();
|
| @@ -308,9 +362,9 @@ bool MagnificationControllerImpl::RedrawDIP(const gfx::PointF& position_in_dip,
|
| settings.AddObserver(this);
|
| settings.SetPreemptionStrategy(
|
| ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
|
| - settings.SetTweenType(gfx::Tween::EASE_OUT);
|
| + settings.SetTweenType(tween_type);
|
| settings.SetTransitionDuration(
|
| - base::TimeDelta::FromMilliseconds(animate ? 100 : 0));
|
| + base::TimeDelta::FromMilliseconds(duration_in_ms));
|
|
|
| gfx::Display display =
|
| Shell::GetScreen()->GetDisplayNearestWindow(root_window_);
|
| @@ -319,7 +373,7 @@ bool MagnificationControllerImpl::RedrawDIP(const gfx::PointF& position_in_dip,
|
| GetRootWindowController(root_window_)->ash_host()->SetRootWindowTransformer(
|
| transformer.Pass());
|
|
|
| - if (animate)
|
| + if (duration_in_ms > 0)
|
| is_on_animation_ = true;
|
|
|
| return true;
|
| @@ -352,14 +406,15 @@ void MagnificationControllerImpl::StartOrStopScrollIfNecessary() {
|
| new_origin.Offset(0, kMoveOffset);
|
| break;
|
| }
|
| - RedrawDIP(new_origin, scale_, true);
|
| + RedrawDIP(new_origin, scale_, kDefaultAnimationDurationInMs,
|
| + kDefaultAnimationTweenType);
|
| }
|
|
|
| void MagnificationControllerImpl::OnMouseMove(const gfx::Point& location) {
|
| DCHECK(root_window_);
|
|
|
| gfx::Point mouse(location);
|
| - int margin = kPanningMergin / scale_; // No need to consider DPI.
|
| + int margin = kCursorPanningMargin / scale_; // No need to consider DPI.
|
| MoveMagnifierWindowFollowPoint(mouse, margin, margin, margin, margin);
|
| }
|
|
|
| @@ -570,6 +625,15 @@ bool MagnificationControllerImpl::IsEnabled() const {
|
| return is_enabled_;
|
| }
|
|
|
| +void MagnificationControllerImpl::SetKeepFocusCentered(
|
| + bool keep_focus_centered) {
|
| + keep_focus_centered_ = keep_focus_centered;
|
| +}
|
| +
|
| +bool MagnificationControllerImpl::KeepFocusCentered() const {
|
| + return keep_focus_centered_;
|
| +}
|
| +
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // MagnificationControllerImpl: aura::EventFilter implementation
|
|
|
| @@ -662,9 +726,9 @@ void MagnificationControllerImpl::MoveMagnifierWindowFollowPoint(
|
| }
|
| int 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);
|
| + bool ret = RedrawDIP(gfx::Point(x, y), scale_,
|
| + 0, // No animation on panning.
|
| + kDefaultAnimationTweenType);
|
|
|
| if (ret) {
|
| // If the magnified region is moved, hides the mouse cursor and moves it.
|
| @@ -674,6 +738,22 @@ void MagnificationControllerImpl::MoveMagnifierWindowFollowPoint(
|
| }
|
| }
|
|
|
| +void MagnificationControllerImpl::MoveMagnifierWindowCenterPoint(
|
| + const gfx::Point& point) {
|
| + DCHECK(root_window_);
|
| +
|
| + const gfx::Rect window_rect = GetViewportRect();
|
| + if (point == window_rect.CenterPoint())
|
| + return;
|
| +
|
| + if (!is_on_animation_) {
|
| + // With animation on panning.
|
| + RedrawDIP(window_rect.origin() + (point - window_rect.CenterPoint()),
|
| + scale_, kDefaultAnimationDurationInMs,
|
| + kCenterCaretAnimationTweenType);
|
| + }
|
| +}
|
| +
|
| void MagnificationControllerImpl::MoveMagnifierWindowFollowRect(
|
| const gfx::Rect& rect) {
|
| DCHECK(root_window_);
|
| @@ -707,10 +787,16 @@ void MagnificationControllerImpl::MoveMagnifierWindowFollowRect(
|
| root_window_->layer()->GetAnimator()->StopAnimating();
|
| is_on_animation_ = false;
|
| }
|
| - RedrawDIP(gfx::Point(x, y), scale_, false); // No animation on panning.
|
| + RedrawDIP(gfx::Point(x, y), scale_,
|
| + 0, // No animation on panning.
|
| + kDefaultAnimationTweenType);
|
| }
|
| }
|
|
|
| +void MagnificationControllerImpl::OnMoveMagnifierTimer() {
|
| + MoveMagnifierWindowCenterPoint(caret_point_);
|
| +}
|
| +
|
| void MagnificationControllerImpl::OnCaretBoundsChanged(
|
| const ui::TextInputClient* client) {
|
| // caret bounds in screen coordinates.
|
| @@ -723,17 +809,41 @@ void MagnificationControllerImpl::OnCaretBoundsChanged(
|
| 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 = GetViewportRect();
|
| + caret_point_ = caret_bounds.CenterPoint();
|
| + // |caret_point_| in |root_window_| coordinates.
|
| + wm::ConvertPointFromScreen(root_window_, &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);
|
| + return;
|
| + }
|
|
|
| - const int panning_margin = kCaretPanningMargin / scale_;
|
| - MoveMagnifierWindowFollowPoint(caret_origin, panning_margin, panning_margin,
|
| - visible_window_rect.width() / 2,
|
| - visible_window_rect.height() / 2);
|
| + // 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, &MagnificationControllerImpl::OnMoveMagnifierTimer);
|
| }
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
|
|