Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3226)

Unified Diff: ash/magnifier/magnification_controller.cc

Issue 10388141: Full-screen Magnifier: Support warping the cursor on the edge (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ash/magnifier/magnification_controller.cc
diff --git a/ash/magnifier/magnification_controller.cc b/ash/magnifier/magnification_controller.cc
index af07eae43223b0e29e182851d2d3a4f532ae7a31..c201b000c1656ce938955c44b31e21205d034146 100644
--- a/ash/magnifier/magnification_controller.cc
+++ b/ash/magnifier/magnification_controller.cc
@@ -4,10 +4,14 @@
#include "ash/magnifier/magnification_controller.h"
+#include "ash/magnifier/magnified_cursor.h"
#include "ash/shell.h"
+#include "ui/aura/event.h"
+#include "ui/aura/event_filter.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/aura/window_property.h"
+#include "ui/compositor/dip_util.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
@@ -23,106 +27,295 @@ const float kMinimumMagnifiScaleThreshold = 1.1f;
namespace ash {
namespace internal {
-MagnificationController::MagnificationController()
+////////////////////////////////////////////////////////////////////////////////
+// MagnificationControllerImpl:
+
+class MagnificationControllerImpl : public aura::EventFilter {
+ public:
+ MagnificationControllerImpl();
+ virtual ~MagnificationControllerImpl() {}
+
+ // Returns the current magnification ratio.
+ float GetScale() const { return scale_; }
+
+ // Returns the current top-left point of the magnification window.
+ gfx::Point GetWindowPosition() const { return gfx::Point(x_, y_); }
+
+ // should be called internally just after the scale and/or the position are
+ // changed.
+ void Redraw(const gfx::Point& position, float scale, bool animation);
+
+ // Returns the rect of the magnification window.
+ gfx::Rect GetWindowRect(float scale) const;
+
+ // 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 EnsureShowRect(
+ const gfx::Rect& target_rect, float scale, bool animation);
+ void EnsureShowPoint(const gfx::Point& point, float scale, bool animation);
+ void EnsureShowLastMouseLocation(float scale, bool animation);
+
+ // Returns if the magnification scale is 1.0 or not (larger then 1.0).
+ bool IsMagnified() const;
+
+ private:
+ aura::RootWindow* root_window_;
+
+ // Current scale, position of the magnification window.
+ float scale_;
+ int x_;
+ int y_;
+
+ scoped_ptr<MagnifiedCursor> cursor_;
+
+ void EnsureShowRectDPI(
+ const gfx::Rect& target_rect_in_dpi, float scale, bool animation);
+ void RedrawDPI(const gfx::Point& position, float scale, bool animation);
+
+ void OnStartMagnification();
+ void OnStopMagnification();
+
+ // Correct the givin scale value if nessesary.
+ void CorrectScale(float* scale);
+
+ // Moves the magnification window to new scale and position. This method
+ // 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()
: scale_(1.0f), x_(0), y_(0) {
root_window_ = ash::Shell::GetRootWindow();
+ cursor_.reset(new MagnifiedCursor(root_window_));
+
+ root_window_->magnification_layer()->Add(cursor_->layer());
+ root_window_->magnification_layer()->StackAtTop(cursor_->layer());
}
-void MagnificationController::SetScale(float scale) {
- scale_ = scale;
- RedrawScreen(true);
+void MagnificationControllerImpl::EnsureShowRect(
+ const gfx::Rect& target_rect, float scale, bool animation) {
+ const gfx::Rect target_rect_in_dip =
+ ui::ConvertRectToDIP(root_window_->magnification_layer(), target_rect);
+ EnsureShowRectDPI(target_rect_in_dip, scale, animation);
}
-void MagnificationController::MoveWindow(int x, int y) {
- y_ = y;
- x_ = x;
- RedrawScreen(true);
+void MagnificationControllerImpl::EnsureShowRectDPI(
+ const gfx::Rect& target_rect, float scale, bool animation) {
+ CorrectScale(&scale);
+
+ const gfx::Rect window_rect = GetWindowRect(scale);
+ if (scale == scale_ && window_rect.Contains(target_rect))
+ return;
+
+ 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());
+
+ RedrawDPI(rect.origin(), scale, animation);
}
-void MagnificationController::MoveWindow(const gfx::Point& point) {
- MoveWindow(point.x(), point.y());
+void MagnificationControllerImpl::EnsureShowPoint(
+ const gfx::Point& point, float scale, bool animation) {
+ EnsureShowRect(gfx::Rect(point, gfx::Size(0, 0)), scale, animation);
}
-void MagnificationController::EnsureShowRect(const gfx::Rect& target_rect) {
- gfx::Rect rect = GetWindowRect().AdjustToFit(target_rect);
- MoveWindow(rect.x(), rect.y());
+void MagnificationControllerImpl::EnsureShowLastMouseLocation(
+ float scale, bool animation) {
+ EnsureShowRectDPI(
+ gfx::Rect(root_window_->last_mouse_location(), gfx::Size(0, 0)),
+ scale, animation);
}
-void MagnificationController::EnsureShowPoint(const gfx::Point& point,
- bool animation) {
- gfx::Rect rect = GetWindowRect();
+void MagnificationControllerImpl::Redraw(
+ const gfx::Point& position, float scale, bool animation) {
+ const gfx::Point position_in_dpi =
+ ui::ConvertPointToDIP(root_window_->magnification_layer(), position);
+ RedrawDPI(position_in_dpi, scale, animation);
+}
- if (rect.Contains(point))
- return;
+void MagnificationControllerImpl::RedrawDPI(
+ const gfx::Point& position_in_dpi, float scale, bool animation) {
+ int x = position_in_dpi.x();
+ int y = position_in_dpi.y();
+
+ CorrectScale(&scale);
+
+ if (scale_ == kMinimumMagnifiScale && scale != kMinimumMagnifiScale)
+ OnStartMagnification();
+ else if (scale_ != kMinimumMagnifiScale && scale == kMinimumMagnifiScale)
+ OnStopMagnification();
+
+ scale_ = scale;
+
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+
+ const gfx::Size host_size_in_dip =
+ ui::ConvertSizeToDIP(root_window_->magnification_layer(),
+ root_window_->GetHostSize());
+ const gfx::Size window_size_in_dip = GetWindowRect(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;
+
+ x_ = x;
+ y_ = y;
+
+ // 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 (point.x() < rect.x())
- x_ = point.x();
- else if(rect.right() < point.x())
- x_ = point.x() - rect.width();
+ ui::ScopedLayerAnimationSettings settings(
+ root_window_->magnification_layer()->GetAnimator());
+ settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ settings.SetTweenType(ui::Tween::EASE_IN_OUT);
+ settings.SetTransitionDuration(
+ base::TimeDelta::FromMilliseconds(animation ? 100 : 0));
+
+ root_window_->magnification_layer()->SetTransform(transform);
+}
- if (point.y() < rect.y())
- y_ = point.y();
- else if(rect.bottom() < point.y())
- y_ = point.y() - rect.height();
+gfx::Rect MagnificationControllerImpl::GetWindowRect(float scale) const {
+ const gfx::Size size_in_dip =
+ ui::ConvertSizeToDIP(root_window_->magnification_layer(),
+ root_window_->GetHostSize());
+ const int width = size_in_dip.width() / scale;
+ const int height = size_in_dip.height() / scale;
- RedrawScreen(animation);
+ return gfx::Rect(x_, y_, width, height);
}
-void MagnificationController::RedrawScreen(bool animation) {
+bool MagnificationControllerImpl::IsMagnified() const {
+ return scale_ >= kMinimumMagnifiScaleThreshold;
+}
+void MagnificationControllerImpl::CorrectScale(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::OnStartMagnification() {
+ cursor_->SetVisible(true);
+ root_window_->SetForceHideCursor(true);
+ root_window_->ShowCursor(false);
+ cursor_->MovePointer(root_window_->last_mouse_location());
+}
- 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;
+void MagnificationControllerImpl::OnStopMagnification() {
+ cursor_->SetVisible(false);
+ root_window_->SetForceHideCursor(false);
+ root_window_->ShowCursor(true);
+}
+////////////////////////////////////////////////////////////////////////////////
+// MagnificationControllerImpl, aura::EventFilter implementation:
- float scale = scale_;
- int x = x_;
- int y = y_;
+bool MagnificationControllerImpl::PreHandleKeyEvent(
+ aura::Window* target, aura::KeyEvent* event) {
+ return false;
+}
- // 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));
+bool MagnificationControllerImpl::PreHandleMouseEvent(
+ aura::Window* target, aura::MouseEvent* event) {
+ if (IsMagnified()) {
+ EnsureShowLastMouseLocation(scale_, false);
+ cursor_->MovePointer(root_window_->last_mouse_location());
}
+ return false;
+}
- root_window_->layer()->SetTransform(transform);
+ui::TouchStatus MagnificationControllerImpl::PreHandleTouchEvent(
+ aura::Window* target, aura::TouchEvent* event) {
+ return ui::TOUCH_STATUS_UNKNOWN;
}
-gfx::Rect MagnificationController::GetWindowRect() {
- gfx::Size size = root_window_->GetHostSize();
- int width = size.width() / scale_;
- int height = size.height() / scale_;
+ui::GestureStatus MagnificationControllerImpl::PreHandleGestureEvent(
+ aura::Window* target,
+ aura::GestureEvent* event) {
+ return ui::GESTURE_STATUS_UNKNOWN;
+}
- return gfx::Rect(x_, y_, width, height);
+////////////////////////////////////////////////////////////////////////////////
+// MagnificationController:
+
+MagnificationController::MagnificationController() {
+ impl_.reset(new MagnificationControllerImpl());
+}
+
+MagnificationController::~MagnificationController() {
+}
+
+void MagnificationController::SetScale(float scale, bool animation) {
+ impl_->EnsureShowLastMouseLocation(scale, animation);
+}
+
+void MagnificationController::MoveWindow(int x, int y, bool animation) {
+ impl_->Redraw(gfx::Point(x, y), GetScale(), animation);
+}
+
+void MagnificationController::MoveWindow(
+ const gfx::Point& point, bool animation) {
+ impl_->Redraw(point, GetScale(), animation);
+}
+
+void MagnificationController::EnsureShowRect(
+ const gfx::Rect& target_rect, bool animation) {
+ impl_->EnsureShowRect(target_rect, GetScale(), animation);
+}
+
+void MagnificationController::EnsureShowPoint(
+ const gfx::Point& point, bool animation) {
+ impl_->EnsureShowPoint(point, GetScale(), animation);
+}
+
+float MagnificationController::GetScale() const {
+ return impl_->GetScale();
+}
+
+gfx::Point MagnificationController::GetWindowPosition() const {
+ return impl_->GetWindowPosition();
+}
+
+aura::EventFilter* MagnificationController::GetEventFilter() const {
+ return impl_.get();
}
} // namespace internal

Powered by Google App Engine
This is Rietveld 408576698