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

Side by Side 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: Review fix Created 8 years, 6 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 unified diff | Download patch
OLDNEW
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/shell.h" 7 #include "ash/shell.h"
8 #include "ui/aura/event.h"
8 #include "ui/aura/root_window.h" 9 #include "ui/aura/root_window.h"
10 #include "ui/aura/shared/root_window_event_filter.h"
9 #include "ui/aura/window.h" 11 #include "ui/aura/window.h"
10 #include "ui/aura/window_property.h" 12 #include "ui/aura/window_property.h"
13 #include "ui/gfx/point3.h"
14 #include "ui/compositor/dip_util.h"
11 #include "ui/compositor/layer.h" 15 #include "ui/compositor/layer.h"
16 #include "ui/compositor/layer_animation_observer.h"
12 #include "ui/compositor/scoped_layer_animation_settings.h" 17 #include "ui/compositor/scoped_layer_animation_settings.h"
13 18
14 namespace { 19 namespace {
15 20
16 const float kMaximumMagnifiScale = 4.0f; 21 const float kMaximumMagnifiScale = 4.0f;
17 const float kMaximumMagnifiScaleThreshold = 4.0f; 22 const float kMaximumMagnifiScaleThreshold = 4.0f;
18 const float kMinimumMagnifiScale = 1.0f; 23 const float kMinimumMagnifiScale = 1.0f;
19 const float kMinimumMagnifiScaleThreshold = 1.1f; 24 const float kMinimumMagnifiScaleThreshold = 1.1f;
20 25
21 } // namespace 26 } // namespace
22 27
23 namespace ash { 28 namespace ash {
24 namespace internal { 29 namespace internal {
25 30
26 MagnificationController::MagnificationController() 31 ////////////////////////////////////////////////////////////////////////////////
32 // MagnificationControllerImpl:
33
34 class MagnificationControllerImpl : virtual public MagnificationController,
35 public ui::ImplicitAnimationObserver {
36 public:
37 MagnificationControllerImpl();
38 virtual ~MagnificationControllerImpl() {}
39
40 // MagnificationController overrides:
41 virtual void SetScale(float scale, bool animation) OVERRIDE;
42 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.
43 void MoveWindow(int x, int y, bool animation);
44 void MoveWindow(const gfx::Point& point, bool animation);
45 gfx::Point GetWindowPosition() const { return gfx::Point(x_, y_); }
46 void EnsureShowRect(const gfx::Rect& rect, bool animation);
47 virtual void EnsureShowPoint(const gfx::Point& point,
48 bool animation) OVERRIDE;
49
50 private:
51 aura::RootWindow* root_window_;
52 bool is_on_zooming_;
sky 2012/06/11 16:19:14 Add description.
yoshiki 2012/06/19 17:56:16 Done.
53
54 // Current scale, position of the magnification window.
55 float scale_;
56 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.
57 int y_;
58
59 // ui::ImplicitAnimationObserver overrides:
sky 2012/06/11 16:19:14 methods before fields.
yoshiki 2012/06/19 17:56:16 Done.
60 virtual void OnImplicitAnimationsCompleted() OVERRIDE;
61
62 // should be called internally just after the scale and/or the position are
63 // changed.
64 bool Redraw(const gfx::Point& position, float scale, bool animation);
65 bool RedrawDIP(const gfx::Point& position, float scale, bool animation);
66
67 // Ensures that the given point, rect or last mouse location is inside
68 // magnification window. If not, the controller moves the window to contain
69 // the given point/rect.
70 void EnsureShowRectWithScale(
71 const gfx::Rect& target_rect, float scale, bool animation);
72 void EnsureShowRectDIP(
73 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.
74 void EnsureShowPointWithScale(
75 const gfx::Point& point, float scale, bool animation);
76 void OnMouseMove();
77
78 // Returns if the magnification scale is 1.0 or not (larger then 1.0).
79 bool IsMagnified() const;
80
81 // Returns the rect of the magnification window.
82 gfx::Rect GetWindowRectDIP(float scale) const;
83 // Returns the size of the root window.
84 gfx::Size GetHostSizeDIP() const;
85
86 // Correct the givin scale value if nessesary.
87 void ValidateScale(float* scale);
88
89 // aura::EventFilter overrides:
90 virtual bool PreHandleKeyEvent(aura::Window* target,
91 aura::KeyEvent* event) OVERRIDE;
92 virtual bool PreHandleMouseEvent(aura::Window* target,
93 aura::MouseEvent* event) OVERRIDE;
94 virtual ui::TouchStatus PreHandleTouchEvent(aura::Window* target,
95 aura::TouchEvent* event) OVERRIDE;
96 virtual ui::GestureStatus PreHandleGestureEvent(
97 aura::Window* target,
98 aura::GestureEvent* event) OVERRIDE;
99
100 DISALLOW_COPY_AND_ASSIGN(MagnificationControllerImpl);
101 };
102
103 ////////////////////////////////////////////////////////////////////////////////
104 // MagnificationControllerImpl:
105
106 MagnificationControllerImpl::MagnificationControllerImpl()
27 : scale_(1.0f), x_(0), y_(0) { 107 : 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.
28 root_window_ = ash::Shell::GetRootWindow(); 108 root_window_ = ash::Shell::GetRootWindow();
29 } 109 }
30 110
31 void MagnificationController::SetScale(float scale) { 111 bool MagnificationControllerImpl::Redraw(
112 const gfx::Point& position, float scale, bool animation) {
113 const gfx::Point position_in_dip =
114 ui::ConvertPointToDIP(root_window_->layer(), position);
115 return RedrawDIP(position_in_dip, scale, animation);
116 }
117
118 bool MagnificationControllerImpl::RedrawDIP(
119 const gfx::Point& position_in_dip, float scale, bool animation) {
120 int x = position_in_dip.x();
121 int y = position_in_dip.y();
122
123 ValidateScale(&scale);
124
125 if (x < 0)
126 x = 0;
127 if (y < 0)
128 y = 0;
129
130 const gfx::Size host_size_in_dip = GetHostSizeDIP();
131 const gfx::Size window_size_in_dip = GetWindowRectDIP(scale).size();
132 int max_x = host_size_in_dip.width() - window_size_in_dip.width();
133 int max_y = host_size_in_dip.height() - window_size_in_dip.height();
134 if (x > max_x)
135 x = max_x;
136 if (y > max_y)
137 y = max_y;
138
139 // Ignores 1 px diffirence because it may be error on calculation.
140 if (std::abs(x_ - x) <= 1 && std::abs(y_ - y) <= 1 && scale == scale_)
141 return false;
142
143 x_ = x;
144 y_ = y;
32 scale_ = scale; 145 scale_ = scale;
33 RedrawScreen(true);
34 }
35
36 void MagnificationController::MoveWindow(int x, int y) {
37 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 146
101 // Creates transform matrix. 147 // Creates transform matrix.
102 ui::Transform transform; 148 ui::Transform transform;
103 // Flips the signs intentionally to convert them from the position of the 149 // Flips the signs intentionally to convert them from the position of the
104 // magnification window. 150 // magnification window.
105 transform.ConcatTranslate(-x, -y); 151 transform.ConcatTranslate(-x_, -y_);
106 transform.ConcatScale(scale, scale); 152 transform.ConcatScale(scale_, scale_);
107 153
108 if (animation) { 154 ui::ScopedLayerAnimationSettings settings(
109 ui::ScopedLayerAnimationSettings settings( 155 root_window_->layer()->GetAnimator());
110 root_window_->layer()->GetAnimator()); 156 settings.AddObserver(this);
111 settings.SetPreemptionStrategy( 157 settings.SetPreemptionStrategy(
112 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); 158 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
113 settings.SetTweenType(ui::Tween::EASE_IN_OUT); 159 settings.SetTweenType(ui::Tween::EASE_OUT);
114 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100)); 160 settings.SetTransitionDuration(
161 base::TimeDelta::FromMilliseconds(animation ? 100 : 0));
162
163 root_window_->layer()->SetTransform(transform);
164
165 return true;
166 }
167
168 void MagnificationControllerImpl::EnsureShowRectWithScale(
169 const gfx::Rect& target_rect, float scale, bool animation) {
170 const gfx::Rect target_rect_in_dip =
171 ui::ConvertRectToDIP(root_window_->layer(), target_rect);
172 EnsureShowRectDIP(target_rect_in_dip, scale, animation);
173 }
174
175 void MagnificationControllerImpl::EnsureShowRectDIP(
176 const gfx::Rect& target_rect, float scale, bool animation) {
177 ValidateScale(&scale);
178
179 const gfx::Rect window_rect = GetWindowRectDIP(scale);
180 if (scale == scale_ && window_rect.Contains(target_rect))
181 return;
182
183 gfx::Rect rect = window_rect;
184 if (target_rect.width() > rect.width())
185 rect.set_x(target_rect.CenterPoint().x() - rect.x() / 2);
186 else if (target_rect.right() < rect.x())
187 rect.set_x(target_rect.right());
188 else if (rect.right() < target_rect.x())
189 rect.set_x(target_rect.x() - rect.width());
190
191 if (rect.height() > window_rect.height())
192 rect.set_y(target_rect.CenterPoint().y() - rect.y() / 2);
193 else if (target_rect.bottom() < rect.y())
194 rect.set_y(target_rect.bottom());
195 else if (rect.bottom() < target_rect.y())
196 rect.set_y(target_rect.y() - rect.height());
197
198 RedrawDIP(rect.origin(), scale, animation);
199 }
200
201 void MagnificationControllerImpl::EnsureShowPointWithScale(
202 const gfx::Point& point, float scale, bool animation) {
203 EnsureShowRectWithScale(gfx::Rect(point, gfx::Size(0, 0)), scale, animation);
204 }
205
206 void MagnificationControllerImpl::OnMouseMove() {
207 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.
208
209 int x = x_;
210 int y = y_;
211 bool start_zoom = false;
212
213 const gfx::Rect window_rect = GetWindowRectDIP(scale_);
214 const int left = window_rect.x();
215 const int right = window_rect.right();
216 const int width_margin = static_cast<int>(0.1f * window_rect.width());
217 const int width_offset = static_cast<int>(0.5f * window_rect.width());
218
219 if (mouse.x() < left + width_margin) {
220 x -= width_offset;
221 start_zoom = true;
222 } else if (right - width_margin < mouse.x()) {
223 x += width_offset;
224 start_zoom = true;
115 } 225 }
116 226
117 root_window_->layer()->SetTransform(transform); 227 const int top = window_rect.y();
118 } 228 const int bottom = window_rect.bottom();
119 229 // Uses same margin with x-axis's one.
120 gfx::Rect MagnificationController::GetWindowRect() { 230 const int height_margin = width_margin;
121 gfx::Size size = root_window_->GetHostSize(); 231 const int height_offset = static_cast<int>(0.5f * window_rect.height());
122 int width = size.width() / scale_; 232
123 int height = size.height() / scale_; 233 if (mouse.y() < top + height_margin) {
234 y -= height_offset;
235 start_zoom = true;
236 } else if (bottom - height_margin < mouse.y()) {
237 y += height_offset;
238 start_zoom = true;
239 }
240
241 if (start_zoom && !is_on_zooming_) {
242 bool ret = Redraw(gfx::Point(x, y), scale_, true);
243
244 if (ret) {
245 is_on_zooming_ = true;
246
247 int x_diff = x_ - window_rect.x();
248 int y_diff = y_ - window_rect.y();
249 // If the magnified region is moved, hides the mouse cursor and moves it.
250 if (x_diff != 0 || y_diff != 0) {
251 ash::Shell::GetInstance()->
252 root_filter()->set_update_cursor_visibility(false);
253 root_window_->ShowCursor(false);
254 mouse.set_x(mouse.x() - (x_ - window_rect.x()));
255 mouse.set_y(mouse.y() - (y_ - window_rect.y()));
256 root_window_->MoveCursorTo(mouse);
257 }
258 }
259 }
260 }
261
262 gfx::Size MagnificationControllerImpl::GetHostSizeDIP() const {
263 return ui::ConvertSizeToDIP(root_window_->layer(),
264 root_window_->GetHostSize());
265 }
266
267 gfx::Rect MagnificationControllerImpl::GetWindowRectDIP(float scale) const {
268 const gfx::Size size_in_dip =
269 ui::ConvertSizeToDIP(root_window_->layer(),
270 root_window_->GetHostSize());
271 const int width = size_in_dip.width() / scale;
272 const int height = size_in_dip.height() / scale;
124 273
125 return gfx::Rect(x_, y_, width, height); 274 return gfx::Rect(x_, y_, width, height);
126 } 275 }
127 276
277 bool MagnificationControllerImpl::IsMagnified() const {
278 return scale_ >= kMinimumMagnifiScaleThreshold;
279 }
280
281 void MagnificationControllerImpl::ValidateScale(float* scale) {
282 // Adjust the scale to just |kMinimumMagnifiScale| if scale is smaller than
283 // |kMinimumMagnifiScaleThreshold|;
284 if (*scale < kMinimumMagnifiScaleThreshold)
285 *scale = kMinimumMagnifiScale;
286
287 // Adjust the scale to just |kMinimumMagnifiScale| if scale is bigger than
288 // |kMinimumMagnifiScaleThreshold|;
289 if (*scale > kMaximumMagnifiScaleThreshold)
290 *scale = kMaximumMagnifiScale;
291 }
292
293 void MagnificationControllerImpl::OnImplicitAnimationsCompleted() {
294 root_window_->ShowCursor(true);
295 is_on_zooming_ = false;
296 }
297
298 ////////////////////////////////////////////////////////////////////////////////
299 // MagnificationControllerImpl: MagnificationController implementation
300
301 void MagnificationControllerImpl::SetScale(float scale, bool animation) {
302 ValidateScale(&scale);
303
304 // Try not to change the point which the mouse cursor indicates to.
305 const gfx::Rect window_rect = GetWindowRectDIP(scale);
306 const gfx::Point mouse = root_window_->last_mouse_location();
307 const gfx::Point origin = gfx::Point(mouse.x() * (1.0f - 1.0f / scale),
308 mouse.y() * (1.0f - 1.0f / scale));
309 Redraw(origin, scale, animation);
310 }
311
312 void MagnificationControllerImpl::MoveWindow(int x, int y, bool animation) {
313 Redraw(gfx::Point(x, y), scale_, animation);
314 }
315
316 void MagnificationControllerImpl::MoveWindow(
317 const gfx::Point& point, bool animation) {
318 Redraw(point, scale_, animation);
319 }
320
321 void MagnificationControllerImpl::EnsureShowRect(
322 const gfx::Rect& target_rect, bool animation) {
323 EnsureShowRectWithScale(target_rect, scale_, animation);
324 }
325
326 void MagnificationControllerImpl::EnsureShowPoint(
327 const gfx::Point& point, bool animation) {
328 EnsureShowPointWithScale(point, scale_, animation);
329 }
330
331 ////////////////////////////////////////////////////////////////////////////////
332 // MagnificationControllerImpl: aura::EventFilter implementation
333
334 bool MagnificationControllerImpl::PreHandleKeyEvent(
335 aura::Window* target, aura::KeyEvent* event) {
336 return false;
337 }
338
339 bool MagnificationControllerImpl::PreHandleMouseEvent(
340 aura::Window* target, aura::MouseEvent* event) {
341 if (IsMagnified())
342 OnMouseMove();
343 return false;
344 }
345
346 ui::TouchStatus MagnificationControllerImpl::PreHandleTouchEvent(
347 aura::Window* target, aura::TouchEvent* event) {
348 return ui::TOUCH_STATUS_UNKNOWN;
349 }
350
351 ui::GestureStatus MagnificationControllerImpl::PreHandleGestureEvent(
352 aura::Window* target,
353 aura::GestureEvent* event) {
354 return ui::GESTURE_STATUS_UNKNOWN;
355 }
356
357 ////////////////////////////////////////////////////////////////////////////////
358 // MagnificationController:
359
360 // static
361 MagnificationController* MagnificationController::CreateInstance() {
362 return new MagnificationControllerImpl();
363 }
364
128 } // namespace internal 365 } // namespace internal
129 } // namespace ash 366 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698