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

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

Powered by Google App Engine
This is Rietveld 408576698