OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/magnifier/magnification_controller.h" | 5 #include "ash/magnifier/magnification_controller.h" |
6 | 6 |
| 7 #include "ash/magnifier/magnified_cursor.h" |
7 #include "ash/shell.h" | 8 #include "ash/shell.h" |
| 9 #include "ui/aura/event.h" |
| 10 #include "ui/aura/event_filter.h" |
8 #include "ui/aura/root_window.h" | 11 #include "ui/aura/root_window.h" |
9 #include "ui/aura/window.h" | 12 #include "ui/aura/window.h" |
10 #include "ui/aura/window_property.h" | 13 #include "ui/aura/window_property.h" |
| 14 #include "ui/compositor/dip_util.h" |
11 #include "ui/compositor/layer.h" | 15 #include "ui/compositor/layer.h" |
12 #include "ui/compositor/scoped_layer_animation_settings.h" | 16 #include "ui/compositor/scoped_layer_animation_settings.h" |
13 | 17 |
14 namespace { | 18 namespace { |
15 | 19 |
16 const float kMaximumMagnifiScale = 4.0f; | 20 const float kMaximumMagnifiScale = 4.0f; |
17 const float kMaximumMagnifiScaleThreshold = 4.0f; | 21 const float kMaximumMagnifiScaleThreshold = 4.0f; |
18 const float kMinimumMagnifiScale = 1.0f; | 22 const float kMinimumMagnifiScale = 1.0f; |
19 const float kMinimumMagnifiScaleThreshold = 1.1f; | 23 const float kMinimumMagnifiScaleThreshold = 1.1f; |
20 | 24 |
21 } // namespace | 25 } // namespace |
22 | 26 |
23 namespace ash { | 27 namespace ash { |
24 namespace internal { | 28 namespace internal { |
25 | 29 |
26 MagnificationController::MagnificationController() | 30 //////////////////////////////////////////////////////////////////////////////// |
| 31 // MagnificationControllerImpl: |
| 32 |
| 33 class MagnificationControllerImpl : public aura::EventFilter { |
| 34 public: |
| 35 MagnificationControllerImpl(); |
| 36 virtual ~MagnificationControllerImpl() {} |
| 37 |
| 38 // Returns the current magnification ratio. |
| 39 float GetScale() const { return scale_; } |
| 40 |
| 41 // Returns the current top-left point of the magnification window. |
| 42 gfx::Point GetWindowPosition() const { return gfx::Point(x_, y_); } |
| 43 |
| 44 // should be called internally just after the scale and/or the position are |
| 45 // changed. |
| 46 void Redraw(const gfx::Point& position, float scale, bool animation); |
| 47 |
| 48 // Returns the rect of the magnification window. |
| 49 gfx::Rect GetWindowRect(float scale) const; |
| 50 |
| 51 // Ensures that the given point, rect or last mouse location is inside |
| 52 // magnification window. If not, the controller moves the window to contain |
| 53 // the given point/rect. |
| 54 void EnsureShowRect( |
| 55 const gfx::Rect& target_rect, float scale, bool animation); |
| 56 void EnsureShowPoint(const gfx::Point& point, float scale, bool animation); |
| 57 void EnsureShowLastMouseLocation(float scale, bool animation); |
| 58 |
| 59 // Returns if the magnification scale is 1.0 or not (larger then 1.0). |
| 60 bool IsMagnified() const; |
| 61 |
| 62 private: |
| 63 aura::RootWindow* root_window_; |
| 64 |
| 65 // Current scale, position of the magnification window. |
| 66 float scale_; |
| 67 int x_; |
| 68 int y_; |
| 69 |
| 70 scoped_ptr<MagnifiedCursor> cursor_; |
| 71 |
| 72 void EnsureShowRectDPI( |
| 73 const gfx::Rect& target_rect_in_dpi, float scale, bool animation); |
| 74 void RedrawDPI(const gfx::Point& position, float scale, bool animation); |
| 75 |
| 76 void OnStartMagnification(); |
| 77 void OnStopMagnification(); |
| 78 |
| 79 // Correct the givin scale value if nessesary. |
| 80 void CorrectScale(float* scale); |
| 81 |
| 82 // Moves the magnification window to new scale and position. This method |
| 83 // aura::EventFilter overrides: |
| 84 virtual bool PreHandleKeyEvent(aura::Window* target, |
| 85 aura::KeyEvent* event) OVERRIDE; |
| 86 virtual bool PreHandleMouseEvent(aura::Window* target, |
| 87 aura::MouseEvent* event) OVERRIDE; |
| 88 virtual ui::TouchStatus PreHandleTouchEvent(aura::Window* target, |
| 89 aura::TouchEvent* event) OVERRIDE; |
| 90 virtual ui::GestureStatus PreHandleGestureEvent( |
| 91 aura::Window* target, |
| 92 aura::GestureEvent* event) OVERRIDE; |
| 93 |
| 94 DISALLOW_COPY_AND_ASSIGN(MagnificationControllerImpl); |
| 95 }; |
| 96 |
| 97 MagnificationControllerImpl::MagnificationControllerImpl() |
27 : scale_(1.0f), x_(0), y_(0) { | 98 : scale_(1.0f), x_(0), y_(0) { |
28 root_window_ = ash::Shell::GetRootWindow(); | 99 root_window_ = ash::Shell::GetRootWindow(); |
29 } | 100 cursor_.reset(new MagnifiedCursor(root_window_)); |
30 | 101 |
31 void MagnificationController::SetScale(float scale) { | 102 root_window_->magnification_layer()->Add(cursor_->layer()); |
| 103 root_window_->magnification_layer()->StackAtTop(cursor_->layer()); |
| 104 } |
| 105 |
| 106 void MagnificationControllerImpl::EnsureShowRect( |
| 107 const gfx::Rect& target_rect, float scale, bool animation) { |
| 108 const gfx::Rect target_rect_in_dip = |
| 109 ui::ConvertRectToDIP(root_window_->magnification_layer(), target_rect); |
| 110 EnsureShowRectDPI(target_rect_in_dip, scale, animation); |
| 111 } |
| 112 |
| 113 void MagnificationControllerImpl::EnsureShowRectDPI( |
| 114 const gfx::Rect& target_rect, float scale, bool animation) { |
| 115 CorrectScale(&scale); |
| 116 |
| 117 const gfx::Rect window_rect = GetWindowRect(scale); |
| 118 if (scale == scale_ && window_rect.Contains(target_rect)) |
| 119 return; |
| 120 |
| 121 gfx::Rect rect = window_rect; |
| 122 if (target_rect.width() > rect.width()) |
| 123 rect.set_x(target_rect.CenterPoint().x() - rect.x() / 2); |
| 124 else if (target_rect.right() < rect.x()) |
| 125 rect.set_x(target_rect.right()); |
| 126 else if (rect.right() < target_rect.x()) |
| 127 rect.set_x(target_rect.x() - rect.width()); |
| 128 |
| 129 if (rect.height() > window_rect.height()) |
| 130 rect.set_y(target_rect.CenterPoint().y() - rect.y() / 2); |
| 131 else if (target_rect.bottom() < rect.y()) |
| 132 rect.set_y(target_rect.bottom()); |
| 133 else if (rect.bottom() < target_rect.y()) |
| 134 rect.set_y(target_rect.y() - rect.height()); |
| 135 |
| 136 RedrawDPI(rect.origin(), scale, animation); |
| 137 } |
| 138 |
| 139 void MagnificationControllerImpl::EnsureShowPoint( |
| 140 const gfx::Point& point, float scale, bool animation) { |
| 141 EnsureShowRect(gfx::Rect(point, gfx::Size(0, 0)), scale, animation); |
| 142 } |
| 143 |
| 144 void MagnificationControllerImpl::EnsureShowLastMouseLocation( |
| 145 float scale, bool animation) { |
| 146 EnsureShowRectDPI( |
| 147 gfx::Rect(root_window_->last_mouse_location(), gfx::Size(0, 0)), |
| 148 scale, animation); |
| 149 } |
| 150 |
| 151 void MagnificationControllerImpl::Redraw( |
| 152 const gfx::Point& position, float scale, bool animation) { |
| 153 const gfx::Point position_in_dpi = |
| 154 ui::ConvertPointToDIP(root_window_->magnification_layer(), position); |
| 155 RedrawDPI(position_in_dpi, scale, animation); |
| 156 } |
| 157 |
| 158 void MagnificationControllerImpl::RedrawDPI( |
| 159 const gfx::Point& position_in_dpi, float scale, bool animation) { |
| 160 int x = position_in_dpi.x(); |
| 161 int y = position_in_dpi.y(); |
| 162 |
| 163 CorrectScale(&scale); |
| 164 |
| 165 if (scale_ == kMinimumMagnifiScale && scale != kMinimumMagnifiScale) |
| 166 OnStartMagnification(); |
| 167 else if (scale_ != kMinimumMagnifiScale && scale == kMinimumMagnifiScale) |
| 168 OnStopMagnification(); |
| 169 |
32 scale_ = scale; | 170 scale_ = scale; |
33 RedrawScreen(true); | 171 |
34 } | 172 if (x < 0) |
35 | 173 x = 0; |
36 void MagnificationController::MoveWindow(int x, int y) { | 174 if (y < 0) |
| 175 y = 0; |
| 176 |
| 177 const gfx::Size host_size_in_dip = |
| 178 ui::ConvertSizeToDIP(root_window_->magnification_layer(), |
| 179 root_window_->GetHostSize()); |
| 180 const gfx::Size window_size_in_dip = GetWindowRect(scale).size(); |
| 181 int max_x = host_size_in_dip.width() - window_size_in_dip.width(); |
| 182 int max_y = host_size_in_dip.height() - window_size_in_dip.height(); |
| 183 if (x > max_x) |
| 184 x = max_x; |
| 185 if (y > max_y) |
| 186 y = max_y; |
| 187 |
| 188 x_ = x; |
37 y_ = y; | 189 y_ = y; |
38 x_ = x; | |
39 RedrawScreen(true); | |
40 } | |
41 | |
42 void MagnificationController::MoveWindow(const gfx::Point& point) { | |
43 MoveWindow(point.x(), point.y()); | |
44 } | |
45 | |
46 void MagnificationController::EnsureShowRect(const gfx::Rect& target_rect) { | |
47 gfx::Rect rect = GetWindowRect().AdjustToFit(target_rect); | |
48 MoveWindow(rect.x(), rect.y()); | |
49 } | |
50 | |
51 void MagnificationController::EnsureShowPoint(const gfx::Point& point, | |
52 bool animation) { | |
53 gfx::Rect rect = GetWindowRect(); | |
54 | |
55 if (rect.Contains(point)) | |
56 return; | |
57 | |
58 if (point.x() < rect.x()) | |
59 x_ = point.x(); | |
60 else if(rect.right() < point.x()) | |
61 x_ = point.x() - rect.width(); | |
62 | |
63 if (point.y() < rect.y()) | |
64 y_ = point.y(); | |
65 else if(rect.bottom() < point.y()) | |
66 y_ = point.y() - rect.height(); | |
67 | |
68 RedrawScreen(animation); | |
69 } | |
70 | |
71 void MagnificationController::RedrawScreen(bool animation) { | |
72 | |
73 // Adjust the scale to just |kMinimumMagnifiScale| if scale is smaller than | |
74 // |kMinimumMagnifiScaleThreshold|; | |
75 if (scale_ < kMinimumMagnifiScaleThreshold) | |
76 scale_ = kMinimumMagnifiScale; | |
77 // Adjust the scale to just |kMinimumMagnifiScale| if scale is bigger than | |
78 // |kMinimumMagnifiScaleThreshold|; | |
79 if (scale_ > kMaximumMagnifiScaleThreshold) | |
80 scale_ = kMaximumMagnifiScale; | |
81 | |
82 if (x_ < 0) | |
83 x_ = 0; | |
84 if (y_ < 0) | |
85 y_ = 0; | |
86 | |
87 gfx::Size host_size = root_window_->GetHostSize(); | |
88 gfx::Size window_size = GetWindowRect().size(); | |
89 int max_x = host_size.width() - window_size.width(); | |
90 int max_y = host_size.height() - window_size.height(); | |
91 if (x_ > max_x) | |
92 x_ = max_x; | |
93 if (y_ > max_y) | |
94 y_ = max_y; | |
95 | |
96 | |
97 float scale = scale_; | |
98 int x = x_; | |
99 int y = y_; | |
100 | 190 |
101 // Creates transform matrix. | 191 // Creates transform matrix. |
102 ui::Transform transform; | 192 ui::Transform transform; |
103 // Flips the signs intentionally to convert them from the position of the | 193 // Flips the signs intentionally to convert them from the position of the |
104 // magnification window. | 194 // magnification window. |
105 transform.ConcatTranslate(-x, -y); | 195 transform.ConcatTranslate(-x_, -y_); |
106 transform.ConcatScale(scale, scale); | 196 transform.ConcatScale(scale_, scale_); |
107 | 197 |
108 if (animation) { | 198 ui::ScopedLayerAnimationSettings settings( |
109 ui::ScopedLayerAnimationSettings settings( | 199 root_window_->magnification_layer()->GetAnimator()); |
110 root_window_->layer()->GetAnimator()); | 200 settings.SetPreemptionStrategy( |
111 settings.SetPreemptionStrategy( | 201 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
112 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); | 202 settings.SetTweenType(ui::Tween::EASE_IN_OUT); |
113 settings.SetTweenType(ui::Tween::EASE_IN_OUT); | 203 settings.SetTransitionDuration( |
114 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100)); | 204 base::TimeDelta::FromMilliseconds(animation ? 100 : 0)); |
| 205 |
| 206 root_window_->magnification_layer()->SetTransform(transform); |
| 207 } |
| 208 |
| 209 gfx::Rect MagnificationControllerImpl::GetWindowRect(float scale) const { |
| 210 const gfx::Size size_in_dip = |
| 211 ui::ConvertSizeToDIP(root_window_->magnification_layer(), |
| 212 root_window_->GetHostSize()); |
| 213 const int width = size_in_dip.width() / scale; |
| 214 const int height = size_in_dip.height() / scale; |
| 215 |
| 216 return gfx::Rect(x_, y_, width, height); |
| 217 } |
| 218 |
| 219 bool MagnificationControllerImpl::IsMagnified() const { |
| 220 return scale_ >= kMinimumMagnifiScaleThreshold; |
| 221 } |
| 222 |
| 223 void MagnificationControllerImpl::CorrectScale(float* scale) { |
| 224 // Adjust the scale to just |kMinimumMagnifiScale| if scale is smaller than |
| 225 // |kMinimumMagnifiScaleThreshold|; |
| 226 if (*scale < kMinimumMagnifiScaleThreshold) |
| 227 *scale = kMinimumMagnifiScale; |
| 228 |
| 229 // Adjust the scale to just |kMinimumMagnifiScale| if scale is bigger than |
| 230 // |kMinimumMagnifiScaleThreshold|; |
| 231 if (*scale > kMaximumMagnifiScaleThreshold) |
| 232 *scale = kMaximumMagnifiScale; |
| 233 } |
| 234 |
| 235 void MagnificationControllerImpl::OnStartMagnification() { |
| 236 cursor_->SetVisible(true); |
| 237 root_window_->SetForceHideCursor(true); |
| 238 root_window_->ShowCursor(false); |
| 239 cursor_->MovePointer(root_window_->last_mouse_location()); |
| 240 } |
| 241 |
| 242 void MagnificationControllerImpl::OnStopMagnification() { |
| 243 cursor_->SetVisible(false); |
| 244 root_window_->SetForceHideCursor(false); |
| 245 root_window_->ShowCursor(true); |
| 246 } |
| 247 |
| 248 //////////////////////////////////////////////////////////////////////////////// |
| 249 // MagnificationControllerImpl, aura::EventFilter implementation: |
| 250 |
| 251 bool MagnificationControllerImpl::PreHandleKeyEvent( |
| 252 aura::Window* target, aura::KeyEvent* event) { |
| 253 return false; |
| 254 } |
| 255 |
| 256 bool MagnificationControllerImpl::PreHandleMouseEvent( |
| 257 aura::Window* target, aura::MouseEvent* event) { |
| 258 if (IsMagnified()) { |
| 259 EnsureShowLastMouseLocation(scale_, false); |
| 260 cursor_->MovePointer(root_window_->last_mouse_location()); |
115 } | 261 } |
116 | 262 return false; |
117 root_window_->layer()->SetTransform(transform); | 263 } |
118 } | 264 |
119 | 265 ui::TouchStatus MagnificationControllerImpl::PreHandleTouchEvent( |
120 gfx::Rect MagnificationController::GetWindowRect() { | 266 aura::Window* target, aura::TouchEvent* event) { |
121 gfx::Size size = root_window_->GetHostSize(); | 267 return ui::TOUCH_STATUS_UNKNOWN; |
122 int width = size.width() / scale_; | 268 } |
123 int height = size.height() / scale_; | 269 |
124 | 270 ui::GestureStatus MagnificationControllerImpl::PreHandleGestureEvent( |
125 return gfx::Rect(x_, y_, width, height); | 271 aura::Window* target, |
| 272 aura::GestureEvent* event) { |
| 273 return ui::GESTURE_STATUS_UNKNOWN; |
| 274 } |
| 275 |
| 276 //////////////////////////////////////////////////////////////////////////////// |
| 277 // MagnificationController: |
| 278 |
| 279 MagnificationController::MagnificationController() { |
| 280 impl_.reset(new MagnificationControllerImpl()); |
| 281 } |
| 282 |
| 283 MagnificationController::~MagnificationController() { |
| 284 } |
| 285 |
| 286 void MagnificationController::SetScale(float scale, bool animation) { |
| 287 impl_->EnsureShowLastMouseLocation(scale, animation); |
| 288 } |
| 289 |
| 290 void MagnificationController::MoveWindow(int x, int y, bool animation) { |
| 291 impl_->Redraw(gfx::Point(x, y), GetScale(), animation); |
| 292 } |
| 293 |
| 294 void MagnificationController::MoveWindow( |
| 295 const gfx::Point& point, bool animation) { |
| 296 impl_->Redraw(point, GetScale(), animation); |
| 297 } |
| 298 |
| 299 void MagnificationController::EnsureShowRect( |
| 300 const gfx::Rect& target_rect, bool animation) { |
| 301 impl_->EnsureShowRect(target_rect, GetScale(), animation); |
| 302 } |
| 303 |
| 304 void MagnificationController::EnsureShowPoint( |
| 305 const gfx::Point& point, bool animation) { |
| 306 impl_->EnsureShowPoint(point, GetScale(), animation); |
| 307 } |
| 308 |
| 309 float MagnificationController::GetScale() const { |
| 310 return impl_->GetScale(); |
| 311 } |
| 312 |
| 313 gfx::Point MagnificationController::GetWindowPosition() const { |
| 314 return impl_->GetWindowPosition(); |
| 315 } |
| 316 |
| 317 aura::EventFilter* MagnificationController::GetEventFilter() const { |
| 318 return impl_.get(); |
126 } | 319 } |
127 | 320 |
128 } // namespace internal | 321 } // namespace internal |
129 } // namespace ash | 322 } // namespace ash |
OLD | NEW |