Index: ash/magnifier/magnification_controller.cc |
diff --git a/ash/magnifier/magnification_controller.cc b/ash/magnifier/magnification_controller.cc |
index af07eae43223b0e29e182851d2d3a4f532ae7a31..8f46f9753c03db73ca2d20dd35539349ac18e77f 100644 |
--- a/ash/magnifier/magnification_controller.cc |
+++ b/ash/magnifier/magnification_controller.cc |
@@ -5,10 +5,15 @@ |
#include "ash/magnifier/magnification_controller.h" |
#include "ash/shell.h" |
+#include "ui/aura/event.h" |
#include "ui/aura/root_window.h" |
+#include "ui/aura/shared/root_window_event_filter.h" |
#include "ui/aura/window.h" |
#include "ui/aura/window_property.h" |
+#include "ui/gfx/point3.h" |
+#include "ui/compositor/dip_util.h" |
#include "ui/compositor/layer.h" |
+#include "ui/compositor/layer_animation_observer.h" |
#include "ui/compositor/scoped_layer_animation_settings.h" |
namespace { |
@@ -23,106 +28,338 @@ const float kMinimumMagnifiScaleThreshold = 1.1f; |
namespace ash { |
namespace internal { |
-MagnificationController::MagnificationController() |
+//////////////////////////////////////////////////////////////////////////////// |
+// MagnificationControllerImpl: |
+ |
+class MagnificationControllerImpl : virtual public MagnificationController, |
+ public ui::ImplicitAnimationObserver { |
+ public: |
+ MagnificationControllerImpl(); |
+ virtual ~MagnificationControllerImpl() {} |
+ |
+ // MagnificationController overrides: |
+ virtual void SetScale(float scale, bool animation) OVERRIDE; |
+ float GetScale() const { return scale_; } |
sky
2012/06/11 16:19:14
virtual OVERRIDE on all these.
yoshiki
2012/06/19 17:56:16
Done.
|
+ void MoveWindow(int x, int y, bool animation); |
+ void MoveWindow(const gfx::Point& point, bool animation); |
+ gfx::Point GetWindowPosition() const { return gfx::Point(x_, y_); } |
+ void EnsureShowRect(const gfx::Rect& rect, bool animation); |
+ virtual void EnsureShowPoint(const gfx::Point& point, |
+ bool animation) OVERRIDE; |
+ |
+ private: |
+ aura::RootWindow* root_window_; |
+ bool is_on_zooming_; |
sky
2012/06/11 16:19:14
Add description.
yoshiki
2012/06/19 17:56:16
Done.
|
+ |
+ // Current scale, position of the magnification window. |
+ float scale_; |
+ int x_; |
sky
2012/06/11 16:19:14
Any reason you're not using gfx::Point?
yoshiki
2012/06/19 17:56:16
Done.
|
+ int y_; |
+ |
+ // ui::ImplicitAnimationObserver overrides: |
sky
2012/06/11 16:19:14
methods before fields.
yoshiki
2012/06/19 17:56:16
Done.
|
+ virtual void OnImplicitAnimationsCompleted() OVERRIDE; |
+ |
+ // should be called internally just after the scale and/or the position are |
+ // changed. |
+ bool Redraw(const gfx::Point& position, float scale, bool animation); |
+ bool RedrawDIP(const gfx::Point& position, float scale, bool animation); |
+ |
+ // 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 EnsureShowRectWithScale( |
+ const gfx::Rect& target_rect, float scale, bool animation); |
+ void EnsureShowRectDIP( |
+ const gfx::Rect& target_rect_in_dip, float scale, bool animation); |
sky
2012/06/11 16:19:14
If you can't fill all arguments on the first line,
yoshiki
2012/06/19 17:56:16
Done.
|
+ void EnsureShowPointWithScale( |
+ const gfx::Point& point, float scale, bool animation); |
+ void OnMouseMove(); |
+ |
+ // Returns if the magnification scale is 1.0 or not (larger then 1.0). |
+ bool IsMagnified() const; |
+ |
+ // Returns the rect of the magnification window. |
+ gfx::Rect GetWindowRectDIP(float scale) const; |
+ // Returns the size of the root window. |
+ gfx::Size GetHostSizeDIP() const; |
+ |
+ // Correct the givin scale value if nessesary. |
+ void ValidateScale(float* scale); |
+ |
+ // aura::EventFilter overrides: |
+ virtual bool PreHandleKeyEvent(aura::Window* target, |
+ aura::KeyEvent* event) OVERRIDE; |
+ virtual bool PreHandleMouseEvent(aura::Window* target, |
+ aura::MouseEvent* event) OVERRIDE; |
+ virtual ui::TouchStatus PreHandleTouchEvent(aura::Window* target, |
+ aura::TouchEvent* event) OVERRIDE; |
+ virtual ui::GestureStatus PreHandleGestureEvent( |
+ aura::Window* target, |
+ aura::GestureEvent* event) OVERRIDE; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MagnificationControllerImpl); |
+}; |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// MagnificationControllerImpl: |
+ |
+MagnificationControllerImpl::MagnificationControllerImpl() |
: scale_(1.0f), x_(0), y_(0) { |
sky
2012/06/11 16:19:14
each arg on its own line.
sky
2012/06/11 16:19:14
Set root_window_ and is_on_zooming_ in the member
yoshiki
2012/06/19 17:56:16
Done.
yoshiki
2012/06/19 17:56:16
Done.
|
root_window_ = ash::Shell::GetRootWindow(); |
} |
-void MagnificationController::SetScale(float scale) { |
- scale_ = scale; |
- RedrawScreen(true); |
+bool MagnificationControllerImpl::Redraw( |
+ const gfx::Point& position, float scale, bool animation) { |
+ const gfx::Point position_in_dip = |
+ ui::ConvertPointToDIP(root_window_->layer(), position); |
+ return RedrawDIP(position_in_dip, scale, animation); |
} |
-void MagnificationController::MoveWindow(int x, int y) { |
- y_ = y; |
+bool MagnificationControllerImpl::RedrawDIP( |
+ const gfx::Point& position_in_dip, float scale, bool animation) { |
+ int x = position_in_dip.x(); |
+ int 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::Size window_size_in_dip = GetWindowRectDIP(scale).size(); |
+ int max_x = host_size_in_dip.width() - window_size_in_dip.width(); |
+ int 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; |
+ |
+ // Ignores 1 px diffirence because it may be error on calculation. |
+ if (std::abs(x_ - x) <= 1 && std::abs(y_ - y) <= 1 && scale == scale_) |
+ return false; |
+ |
x_ = x; |
- RedrawScreen(true); |
-} |
+ y_ = y; |
+ scale_ = scale; |
+ |
+ // Creates transform matrix. |
+ ui::Transform transform; |
+ // Flips the signs intentionally to convert them from the position of the |
+ // magnification window. |
+ transform.ConcatTranslate(-x_, -y_); |
+ transform.ConcatScale(scale_, scale_); |
+ |
+ ui::ScopedLayerAnimationSettings settings( |
+ root_window_->layer()->GetAnimator()); |
+ settings.AddObserver(this); |
+ settings.SetPreemptionStrategy( |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
+ settings.SetTweenType(ui::Tween::EASE_OUT); |
+ settings.SetTransitionDuration( |
+ base::TimeDelta::FromMilliseconds(animation ? 100 : 0)); |
+ |
+ root_window_->layer()->SetTransform(transform); |
-void MagnificationController::MoveWindow(const gfx::Point& point) { |
- MoveWindow(point.x(), point.y()); |
+ return true; |
} |
-void MagnificationController::EnsureShowRect(const gfx::Rect& target_rect) { |
- gfx::Rect rect = GetWindowRect().AdjustToFit(target_rect); |
- MoveWindow(rect.x(), rect.y()); |
+void MagnificationControllerImpl::EnsureShowRectWithScale( |
+ const gfx::Rect& target_rect, float scale, bool animation) { |
+ const gfx::Rect target_rect_in_dip = |
+ ui::ConvertRectToDIP(root_window_->layer(), target_rect); |
+ EnsureShowRectDIP(target_rect_in_dip, scale, animation); |
} |
-void MagnificationController::EnsureShowPoint(const gfx::Point& point, |
- bool animation) { |
- gfx::Rect rect = GetWindowRect(); |
+void MagnificationControllerImpl::EnsureShowRectDIP( |
+ const gfx::Rect& target_rect, float scale, bool animation) { |
+ ValidateScale(&scale); |
- if (rect.Contains(point)) |
+ const gfx::Rect window_rect = GetWindowRectDIP(scale); |
+ if (scale == scale_ && window_rect.Contains(target_rect)) |
return; |
- if (point.x() < rect.x()) |
- x_ = point.x(); |
- else if(rect.right() < point.x()) |
- x_ = point.x() - rect.width(); |
+ 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 (point.y() < rect.y()) |
- y_ = point.y(); |
- else if(rect.bottom() < point.y()) |
- y_ = point.y() - rect.height(); |
+ 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()); |
- RedrawScreen(animation); |
+ RedrawDIP(rect.origin(), scale, animation); |
} |
-void MagnificationController::RedrawScreen(bool animation) { |
+void MagnificationControllerImpl::EnsureShowPointWithScale( |
+ const gfx::Point& point, float scale, bool animation) { |
+ EnsureShowRectWithScale(gfx::Rect(point, gfx::Size(0, 0)), scale, animation); |
+} |
+ |
+void MagnificationControllerImpl::OnMouseMove() { |
+ gfx::Point mouse = root_window_->last_mouse_location(); |
oshima
2012/06/11 21:48:30
please use the mouse event instead of using last m
yoshiki
2012/06/19 17:56:16
Done.
|
+ |
+ int x = x_; |
+ int y = y_; |
+ bool start_zoom = false; |
+ const gfx::Rect window_rect = GetWindowRectDIP(scale_); |
+ const int left = window_rect.x(); |
+ const int right = window_rect.right(); |
+ const int width_margin = static_cast<int>(0.1f * window_rect.width()); |
+ const int width_offset = static_cast<int>(0.5f * window_rect.width()); |
+ |
+ if (mouse.x() < left + width_margin) { |
+ x -= width_offset; |
+ start_zoom = true; |
+ } else if (right - width_margin < mouse.x()) { |
+ x += width_offset; |
+ start_zoom = true; |
+ } |
+ |
+ const int top = window_rect.y(); |
+ const int bottom = window_rect.bottom(); |
+ // Uses same margin with x-axis's one. |
+ const int height_margin = width_margin; |
+ const int height_offset = static_cast<int>(0.5f * window_rect.height()); |
+ |
+ if (mouse.y() < top + height_margin) { |
+ y -= height_offset; |
+ start_zoom = true; |
+ } else if (bottom - height_margin < mouse.y()) { |
+ y += height_offset; |
+ start_zoom = true; |
+ } |
+ |
+ if (start_zoom && !is_on_zooming_) { |
+ bool ret = Redraw(gfx::Point(x, y), scale_, true); |
+ |
+ if (ret) { |
+ is_on_zooming_ = true; |
+ |
+ int x_diff = x_ - window_rect.x(); |
+ int y_diff = y_ - window_rect.y(); |
+ // If the magnified region is moved, hides the mouse cursor and moves it. |
+ if (x_diff != 0 || y_diff != 0) { |
+ ash::Shell::GetInstance()-> |
+ root_filter()->set_update_cursor_visibility(false); |
+ root_window_->ShowCursor(false); |
+ mouse.set_x(mouse.x() - (x_ - window_rect.x())); |
+ mouse.set_y(mouse.y() - (y_ - window_rect.y())); |
+ root_window_->MoveCursorTo(mouse); |
+ } |
+ } |
+ } |
+} |
+ |
+gfx::Size MagnificationControllerImpl::GetHostSizeDIP() const { |
+ return ui::ConvertSizeToDIP(root_window_->layer(), |
+ root_window_->GetHostSize()); |
+} |
+ |
+gfx::Rect MagnificationControllerImpl::GetWindowRectDIP(float scale) const { |
+ const gfx::Size size_in_dip = |
+ ui::ConvertSizeToDIP(root_window_->layer(), |
+ root_window_->GetHostSize()); |
+ const int width = size_in_dip.width() / scale; |
+ const int height = size_in_dip.height() / scale; |
+ |
+ return gfx::Rect(x_, y_, width, height); |
+} |
+ |
+bool MagnificationControllerImpl::IsMagnified() const { |
+ return scale_ >= kMinimumMagnifiScaleThreshold; |
+} |
+ |
+void MagnificationControllerImpl::ValidateScale(float* scale) { |
// Adjust the scale to just |kMinimumMagnifiScale| if scale is smaller than |
// |kMinimumMagnifiScaleThreshold|; |
- if (scale_ < kMinimumMagnifiScaleThreshold) |
- scale_ = kMinimumMagnifiScale; |
+ if (*scale < kMinimumMagnifiScaleThreshold) |
+ *scale = kMinimumMagnifiScale; |
+ |
// Adjust the scale to just |kMinimumMagnifiScale| if scale is bigger than |
// |kMinimumMagnifiScaleThreshold|; |
- if (scale_ > kMaximumMagnifiScaleThreshold) |
- scale_ = kMaximumMagnifiScale; |
+ if (*scale > kMaximumMagnifiScaleThreshold) |
+ *scale = kMaximumMagnifiScale; |
+} |
- if (x_ < 0) |
- x_ = 0; |
- if (y_ < 0) |
- y_ = 0; |
+void MagnificationControllerImpl::OnImplicitAnimationsCompleted() { |
+ root_window_->ShowCursor(true); |
+ is_on_zooming_ = false; |
+} |
- gfx::Size host_size = root_window_->GetHostSize(); |
- gfx::Size window_size = GetWindowRect().size(); |
- int max_x = host_size.width() - window_size.width(); |
- int max_y = host_size.height() - window_size.height(); |
- if (x_ > max_x) |
- x_ = max_x; |
- if (y_ > max_y) |
- y_ = max_y; |
+//////////////////////////////////////////////////////////////////////////////// |
+// MagnificationControllerImpl: MagnificationController implementation |
+void MagnificationControllerImpl::SetScale(float scale, bool animation) { |
+ ValidateScale(&scale); |
- float scale = scale_; |
- int x = x_; |
- int y = y_; |
+ // Try not to change the point which the mouse cursor indicates to. |
+ const gfx::Rect window_rect = GetWindowRectDIP(scale); |
+ const gfx::Point mouse = root_window_->last_mouse_location(); |
+ const gfx::Point origin = gfx::Point(mouse.x() * (1.0f - 1.0f / scale), |
+ mouse.y() * (1.0f - 1.0f / scale)); |
+ Redraw(origin, scale, animation); |
+} |
- // Creates transform matrix. |
- ui::Transform transform; |
- // Flips the signs intentionally to convert them from the position of the |
- // magnification window. |
- transform.ConcatTranslate(-x, -y); |
- transform.ConcatScale(scale, scale); |
- |
- if (animation) { |
- ui::ScopedLayerAnimationSettings settings( |
- root_window_->layer()->GetAnimator()); |
- settings.SetPreemptionStrategy( |
- ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
- settings.SetTweenType(ui::Tween::EASE_IN_OUT); |
- settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100)); |
- } |
+void MagnificationControllerImpl::MoveWindow(int x, int y, bool animation) { |
+ Redraw(gfx::Point(x, y), scale_, animation); |
+} |
- root_window_->layer()->SetTransform(transform); |
+void MagnificationControllerImpl::MoveWindow( |
+ const gfx::Point& point, bool animation) { |
+ Redraw(point, scale_, animation); |
} |
-gfx::Rect MagnificationController::GetWindowRect() { |
- gfx::Size size = root_window_->GetHostSize(); |
- int width = size.width() / scale_; |
- int height = size.height() / scale_; |
+void MagnificationControllerImpl::EnsureShowRect( |
+ const gfx::Rect& target_rect, bool animation) { |
+ EnsureShowRectWithScale(target_rect, scale_, animation); |
+} |
- return gfx::Rect(x_, y_, width, height); |
+void MagnificationControllerImpl::EnsureShowPoint( |
+ const gfx::Point& point, bool animation) { |
+ EnsureShowPointWithScale(point, scale_, animation); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// MagnificationControllerImpl: aura::EventFilter implementation |
+ |
+bool MagnificationControllerImpl::PreHandleKeyEvent( |
+ aura::Window* target, aura::KeyEvent* event) { |
+ return false; |
+} |
+ |
+bool MagnificationControllerImpl::PreHandleMouseEvent( |
+ aura::Window* target, aura::MouseEvent* event) { |
+ if (IsMagnified()) |
+ OnMouseMove(); |
+ return false; |
+} |
+ |
+ui::TouchStatus MagnificationControllerImpl::PreHandleTouchEvent( |
+ aura::Window* target, aura::TouchEvent* event) { |
+ return ui::TOUCH_STATUS_UNKNOWN; |
+} |
+ |
+ui::GestureStatus MagnificationControllerImpl::PreHandleGestureEvent( |
+ aura::Window* target, |
+ aura::GestureEvent* event) { |
+ return ui::GESTURE_STATUS_UNKNOWN; |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// MagnificationController: |
+ |
+// static |
+MagnificationController* MagnificationController::CreateInstance() { |
+ return new MagnificationControllerImpl(); |
} |
} // namespace internal |