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

Side by Side Diff: ash/magnifier/magnification_controller.cc

Issue 665903003: Magnifier needs to follow the focus of the textfield. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address code review comments. Created 6 years, 1 month 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
« no previous file with comments | « no previous file | ash/magnifier/magnification_controller_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/accelerators/accelerator_controller.h" 7 #include "ash/accelerators/accelerator_controller.h"
8 #include "ash/accessibility_delegate.h" 8 #include "ash/accessibility_delegate.h"
9 #include "ash/ash_switches.h" 9 #include "ash/ash_switches.h"
10 #include "ash/display/root_window_transformers.h" 10 #include "ash/display/root_window_transformers.h"
11 #include "ash/host/ash_window_tree_host.h" 11 #include "ash/host/ash_window_tree_host.h"
12 #include "ash/host/root_window_transformer.h" 12 #include "ash/host/root_window_transformer.h"
13 #include "ash/root_window_controller.h" 13 #include "ash/root_window_controller.h"
14 #include "ash/shell.h" 14 #include "ash/shell.h"
15 #include "ash/system/tray/system_tray_delegate.h" 15 #include "ash/system/tray/system_tray_delegate.h"
16 #include "base/command_line.h" 16 #include "base/command_line.h"
17 #include "base/synchronization/waitable_event.h" 17 #include "base/synchronization/waitable_event.h"
18 #include "ui/aura/client/aura_constants.h"
18 #include "ui/aura/client/cursor_client.h" 19 #include "ui/aura/client/cursor_client.h"
19 #include "ui/aura/window.h" 20 #include "ui/aura/window.h"
20 #include "ui/aura/window_property.h"
21 #include "ui/aura/window_tree_host.h" 21 #include "ui/aura/window_tree_host.h"
22 #include "ui/base/ime/input_method.h"
23 #include "ui/base/ime/input_method_observer.h"
24 #include "ui/base/ime/text_input_client.h"
22 #include "ui/compositor/dip_util.h" 25 #include "ui/compositor/dip_util.h"
23 #include "ui/compositor/layer.h" 26 #include "ui/compositor/layer.h"
24 #include "ui/compositor/layer_animation_observer.h" 27 #include "ui/compositor/layer_animation_observer.h"
25 #include "ui/compositor/scoped_layer_animation_settings.h" 28 #include "ui/compositor/scoped_layer_animation_settings.h"
26 #include "ui/events/event.h" 29 #include "ui/events/event.h"
27 #include "ui/events/event_handler.h" 30 #include "ui/events/event_handler.h"
28 #include "ui/gfx/point3_f.h" 31 #include "ui/gfx/point3_f.h"
29 #include "ui/gfx/point_conversions.h" 32 #include "ui/gfx/point_conversions.h"
30 #include "ui/gfx/point_f.h" 33 #include "ui/gfx/point_f.h"
31 #include "ui/gfx/rect_conversions.h" 34 #include "ui/gfx/rect_conversions.h"
32 #include "ui/gfx/screen.h" 35 #include "ui/gfx/screen.h"
33 #include "ui/wm/core/compound_event_filter.h" 36 #include "ui/wm/core/compound_event_filter.h"
37 #include "ui/wm/core/coordinate_conversion.h"
34 38
35 namespace { 39 namespace {
36 40
37 const float kMaxMagnifiedScale = 4.0f; 41 const float kMaxMagnifiedScale = 4.0f;
38 const float kMaxMagnifiedScaleThreshold = 4.0f; 42 const float kMaxMagnifiedScaleThreshold = 4.0f;
39 const float kMinMagnifiedScaleThreshold = 1.1f; 43 const float kMinMagnifiedScaleThreshold = 1.1f;
40 const float kNonMagnifiedScale = 1.0f; 44 const float kNonMagnifiedScale = 1.0f;
41 45
42 const float kInitialMagnifiedScale = 2.0f; 46 const float kInitialMagnifiedScale = 2.0f;
43 const float kScrollScaleChangeFactor = 0.05f; 47 const float kScrollScaleChangeFactor = 0.05f;
44 48
45 // Threadshold of panning. If the cursor moves to within pixels (in DIP) of 49 // Threadshold of panning. If the cursor moves to within pixels (in DIP) of
46 // |kPanningMergin| from the edge, the view-port moves. 50 // |kPanningMergin| from the edge, the view-port moves.
47 const int kPanningMergin = 100; 51 const int kPanningMergin = 100;
48 52
53 // Gives a little panning margin for following caret, so that we will move the
54 // view-port before the caret is completely out of sight.
55 const int kCaretPanningMargin = 10;
56
49 void MoveCursorTo(aura::WindowTreeHost* host, const gfx::Point& root_location) { 57 void MoveCursorTo(aura::WindowTreeHost* host, const gfx::Point& root_location) {
50 gfx::Point3F host_location_3f(root_location); 58 gfx::Point3F host_location_3f(root_location);
51 host->GetRootTransform().TransformPoint(&host_location_3f); 59 host->GetRootTransform().TransformPoint(&host_location_3f);
52 host->MoveCursorToHostLocation( 60 host->MoveCursorToHostLocation(
53 gfx::ToCeiledPoint(host_location_3f.AsPointF())); 61 gfx::ToCeiledPoint(host_location_3f.AsPointF()));
54 } 62 }
55 63
56 } // namespace 64 } // namespace
57 65
58 namespace ash { 66 namespace ash {
59 67
60 //////////////////////////////////////////////////////////////////////////////// 68 ////////////////////////////////////////////////////////////////////////////////
61 // MagnificationControllerImpl: 69 // MagnificationControllerImpl:
62 70
63 class MagnificationControllerImpl : virtual public MagnificationController, 71 class MagnificationControllerImpl : virtual public MagnificationController,
64 public ui::EventHandler, 72 public ui::EventHandler,
65 public ui::ImplicitAnimationObserver, 73 public ui::ImplicitAnimationObserver,
66 public aura::WindowObserver { 74 public aura::WindowObserver,
75 public ui::InputMethodObserver {
67 public: 76 public:
68 MagnificationControllerImpl(); 77 MagnificationControllerImpl();
69 virtual ~MagnificationControllerImpl(); 78 virtual ~MagnificationControllerImpl();
70 79
71 // MagnificationController overrides: 80 // MagnificationController overrides:
72 virtual void SetEnabled(bool enabled) override; 81 virtual void SetEnabled(bool enabled) override;
73 virtual bool IsEnabled() const override; 82 virtual bool IsEnabled() const override;
74 virtual void SetScale(float scale, bool animate) override; 83 virtual void SetScale(float scale, bool animate) override;
75 virtual float GetScale() const override { return scale_; } 84 virtual float GetScale() const override { return scale_; }
76 virtual void MoveWindow(int x, int y, bool animate) override; 85 virtual void MoveWindow(int x, int y, bool animate) override;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 gfx::Size GetHostSizeDIP() const; 146 gfx::Size GetHostSizeDIP() const;
138 147
139 // Correct the givin scale value if nessesary. 148 // Correct the givin scale value if nessesary.
140 void ValidateScale(float* scale); 149 void ValidateScale(float* scale);
141 150
142 // ui::EventHandler overrides: 151 // ui::EventHandler overrides:
143 virtual void OnMouseEvent(ui::MouseEvent* event) override; 152 virtual void OnMouseEvent(ui::MouseEvent* event) override;
144 virtual void OnScrollEvent(ui::ScrollEvent* event) override; 153 virtual void OnScrollEvent(ui::ScrollEvent* event) override;
145 virtual void OnTouchEvent(ui::TouchEvent* event) override; 154 virtual void OnTouchEvent(ui::TouchEvent* event) override;
146 155
156 // Moves the view port when |point| is located within
157 // |x_panning_margin| and |y_pannin_margin| to the edge of the visible
158 // window region. The view port will be moved so that the |point| will be
159 // moved to the point where it has |x_target_margin| and |y_target_margin|
160 // to the edge of the visible region.
161 void MoveMagnifierWindow(const gfx::Point& point,
162 int x_panning_margin,
163 int y_panning_margin,
164 int x_target_margin,
165 int y_target_margin);
166
167 // ui::InputMethodObserver:
168 virtual void OnTextInputTypeChanged(
169 const ui::TextInputClient* client) override {}
170 virtual void OnFocus() override {}
171 virtual void OnBlur() override {}
172 virtual void OnTextInputStateChanged(
173 const ui::TextInputClient* client) override {}
174 virtual void OnInputMethodDestroyed(
175 const ui::InputMethod* input_method) override {}
176 virtual void OnShowImeIfNeeded() override {}
177 virtual void OnCaretBoundsChanged(const ui::TextInputClient* client) override;
178
147 // Target root window. This must not be NULL. 179 // Target root window. This must not be NULL.
148 aura::Window* root_window_; 180 aura::Window* root_window_;
149 181
150 // True if the magnified window is currently animating a change. Otherwise, 182 // True if the magnified window is currently animating a change. Otherwise,
151 // false. 183 // false.
152 bool is_on_animation_; 184 bool is_on_animation_;
153 185
154 bool is_enabled_; 186 bool is_enabled_;
155 187
156 // True if the cursor needs to move the given position after the animation 188 // True if the cursor needs to move the given position after the animation
157 // will be finished. When using this, set |position_after_animation_| as well. 189 // will be finished. When using this, set |position_after_animation_| as well.
158 bool move_cursor_after_animation_; 190 bool move_cursor_after_animation_;
159 // Stores the position of cursor to be moved after animation. 191 // Stores the position of cursor to be moved after animation.
160 gfx::Point position_after_animation_; 192 gfx::Point position_after_animation_;
161 193
162 // Stores the last mouse cursor (or last touched) location. This value is 194 // Stores the last mouse cursor (or last touched) location. This value is
163 // used on zooming to keep this location visible. 195 // used on zooming to keep this location visible.
164 gfx::Point point_of_interest_; 196 gfx::Point point_of_interest_;
165 197
166 // Current scale, origin (left-top) position of the magnification window. 198 // Current scale, origin (left-top) position of the magnification window.
167 float scale_; 199 float scale_;
168 gfx::PointF origin_; 200 gfx::PointF origin_;
169 201
170 ScrollDirection scroll_direction_; 202 ScrollDirection scroll_direction_;
171 203
204 ui::InputMethod* input_method_; // Not owned.
205
172 DISALLOW_COPY_AND_ASSIGN(MagnificationControllerImpl); 206 DISALLOW_COPY_AND_ASSIGN(MagnificationControllerImpl);
173 }; 207 };
174 208
175 //////////////////////////////////////////////////////////////////////////////// 209 ////////////////////////////////////////////////////////////////////////////////
176 // MagnificationControllerImpl: 210 // MagnificationControllerImpl:
177 211
178 MagnificationControllerImpl::MagnificationControllerImpl() 212 MagnificationControllerImpl::MagnificationControllerImpl()
179 : root_window_(Shell::GetPrimaryRootWindow()), 213 : root_window_(Shell::GetPrimaryRootWindow()),
180 is_on_animation_(false), 214 is_on_animation_(false),
181 is_enabled_(false), 215 is_enabled_(false),
182 move_cursor_after_animation_(false), 216 move_cursor_after_animation_(false),
183 scale_(kNonMagnifiedScale), 217 scale_(kNonMagnifiedScale),
184 scroll_direction_(SCROLL_NONE) { 218 scroll_direction_(SCROLL_NONE),
219 input_method_(NULL) {
185 Shell::GetInstance()->AddPreTargetHandler(this); 220 Shell::GetInstance()->AddPreTargetHandler(this);
186 root_window_->AddObserver(this); 221 root_window_->AddObserver(this);
187 point_of_interest_ = root_window_->bounds().CenterPoint(); 222 point_of_interest_ = root_window_->bounds().CenterPoint();
188 } 223 }
189 224
190 MagnificationControllerImpl::~MagnificationControllerImpl() { 225 MagnificationControllerImpl::~MagnificationControllerImpl() {
226 if (input_method_)
227 input_method_->RemoveObserver(this);
228
191 root_window_->RemoveObserver(this); 229 root_window_->RemoveObserver(this);
192 230
193 Shell::GetInstance()->RemovePreTargetHandler(this); 231 Shell::GetInstance()->RemovePreTargetHandler(this);
194 } 232 }
195 233
196 void MagnificationControllerImpl::RedrawKeepingMousePosition( 234 void MagnificationControllerImpl::RedrawKeepingMousePosition(
197 float scale, bool animate) { 235 float scale, bool animate) {
198 gfx::Point mouse_in_root = point_of_interest_; 236 gfx::Point mouse_in_root = point_of_interest_;
199 237
200 // mouse_in_root is invalid value when the cursor is hidden. 238 // mouse_in_root is invalid value when the cursor is hidden.
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 new_origin.Offset(0, kMoveOffset); 348 new_origin.Offset(0, kMoveOffset);
311 break; 349 break;
312 } 350 }
313 RedrawDIP(new_origin, scale_, true); 351 RedrawDIP(new_origin, scale_, true);
314 } 352 }
315 353
316 void MagnificationControllerImpl::OnMouseMove(const gfx::Point& location) { 354 void MagnificationControllerImpl::OnMouseMove(const gfx::Point& location) {
317 DCHECK(root_window_); 355 DCHECK(root_window_);
318 356
319 gfx::Point mouse(location); 357 gfx::Point mouse(location);
320
321 int x = origin_.x();
322 int y = origin_.y();
323 bool start_zoom = false;
324
325 const gfx::Rect window_rect = gfx::ToEnclosingRect(GetWindowRectDIP(scale_));
326 const int left = window_rect.x();
327 const int right = window_rect.right();
328 int margin = kPanningMergin / scale_; // No need to consider DPI. 358 int margin = kPanningMergin / scale_; // No need to consider DPI.
329 359 MoveMagnifierWindow(mouse, margin, margin, margin, margin);
330 int x_diff = 0;
331
332 if (mouse.x() < left + margin) {
333 // Panning left.
334 x_diff = mouse.x() - (left + margin);
335 start_zoom = true;
336 } else if (right - margin < mouse.x()) {
337 // Panning right.
338 x_diff = mouse.x() - (right - margin);
339 start_zoom = true;
340 }
341 x = left + x_diff;
342
343 const int top = window_rect.y();
344 const int bottom = window_rect.bottom();
345
346 int y_diff = 0;
347 if (mouse.y() < top + margin) {
348 // Panning up.
349 y_diff = mouse.y() - (top + margin);
350 start_zoom = true;
351 } else if (bottom - margin < mouse.y()) {
352 // Panning down.
353 y_diff = mouse.y() - (bottom - margin);
354 start_zoom = true;
355 }
356 y = top + y_diff;
357
358 if (start_zoom && !is_on_animation_) {
359 // No animation on panning.
360 bool animate = false;
361 bool ret = RedrawDIP(gfx::Point(x, y), scale_, animate);
362
363 if (ret) {
364 // If the magnified region is moved, hides the mouse cursor and moves it.
365 if (x_diff != 0 || y_diff != 0)
366 MoveCursorTo(root_window_->GetHost(), mouse);
367 }
368 }
369 } 360 }
370 361
371 void MagnificationControllerImpl::AfterAnimationMoveCursorTo( 362 void MagnificationControllerImpl::AfterAnimationMoveCursorTo(
372 const gfx::Point& location) { 363 const gfx::Point& location) {
373 DCHECK(root_window_); 364 DCHECK(root_window_);
374 365
375 aura::client::CursorClient* cursor_client = 366 aura::client::CursorClient* cursor_client =
376 aura::client::GetCursorClient(root_window_); 367 aura::client::GetCursorClient(root_window_);
377 if (cursor_client) { 368 if (cursor_client) {
378 // When cursor is invisible, do not move or show the cursor after the 369 // When cursor is invisible, do not move or show the cursor after the
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 501
511 void MagnificationControllerImpl::SetScrollDirection( 502 void MagnificationControllerImpl::SetScrollDirection(
512 ScrollDirection direction) { 503 ScrollDirection direction) {
513 scroll_direction_ = direction; 504 scroll_direction_ = direction;
514 StartOrStopScrollIfNecessary(); 505 StartOrStopScrollIfNecessary();
515 } 506 }
516 507
517 void MagnificationControllerImpl::SetEnabled(bool enabled) { 508 void MagnificationControllerImpl::SetEnabled(bool enabled) {
518 Shell* shell = Shell::GetInstance(); 509 Shell* shell = Shell::GetInstance();
519 if (enabled) { 510 if (enabled) {
511 if (!input_method_) {
512 input_method_ =
513 root_window_->GetProperty(aura::client::kRootWindowInputMethodKey);
514 if (input_method_)
515 input_method_->AddObserver(this);
516 }
517
520 float scale = 518 float scale =
521 Shell::GetInstance()->accessibility_delegate()-> 519 Shell::GetInstance()->accessibility_delegate()->
522 GetSavedScreenMagnifierScale(); 520 GetSavedScreenMagnifierScale();
523 if (scale <= 0.0f) 521 if (scale <= 0.0f)
524 scale = kInitialMagnifiedScale; 522 scale = kInitialMagnifiedScale;
525 ValidateScale(&scale); 523 ValidateScale(&scale);
526 524
527 // Do nothing, if already enabled with same scale. 525 // Do nothing, if already enabled with same scale.
528 if (is_enabled_ && scale == scale_) 526 if (is_enabled_ && scale == scale_)
529 return; 527 return;
530 528
531 is_enabled_ = enabled; 529 is_enabled_ = enabled;
532 RedrawKeepingMousePosition(scale, true); 530 RedrawKeepingMousePosition(scale, true);
533 shell->accessibility_delegate()->SaveScreenMagnifierScale(scale); 531 shell->accessibility_delegate()->SaveScreenMagnifierScale(scale);
534 } else { 532 } else {
535 // Do nothing, if already disabled. 533 // Do nothing, if already disabled.
536 if (!is_enabled_) 534 if (!is_enabled_)
537 return; 535 return;
538 536
537 if (input_method_) {
538 input_method_->RemoveObserver(this);
539 input_method_ = NULL;
540 }
541
539 RedrawKeepingMousePosition(kNonMagnifiedScale, true); 542 RedrawKeepingMousePosition(kNonMagnifiedScale, true);
540 is_enabled_ = enabled; 543 is_enabled_ = enabled;
541 } 544 }
542 } 545 }
543 546
544 bool MagnificationControllerImpl::IsEnabled() const { 547 bool MagnificationControllerImpl::IsEnabled() const {
545 return is_enabled_; 548 return is_enabled_;
546 } 549 }
547 550
548 //////////////////////////////////////////////////////////////////////////////// 551 ////////////////////////////////////////////////////////////////////////////////
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 void MagnificationControllerImpl::OnTouchEvent(ui::TouchEvent* event) { 593 void MagnificationControllerImpl::OnTouchEvent(ui::TouchEvent* event) {
591 aura::Window* target = static_cast<aura::Window*>(event->target()); 594 aura::Window* target = static_cast<aura::Window*>(event->target());
592 aura::Window* current_root = target->GetRootWindow(); 595 aura::Window* current_root = target->GetRootWindow();
593 if (current_root == root_window_) { 596 if (current_root == root_window_) {
594 gfx::Rect root_bounds = current_root->bounds(); 597 gfx::Rect root_bounds = current_root->bounds();
595 if (root_bounds.Contains(event->root_location())) 598 if (root_bounds.Contains(event->root_location()))
596 point_of_interest_ = event->root_location(); 599 point_of_interest_ = event->root_location();
597 } 600 }
598 } 601 }
599 602
603 void MagnificationControllerImpl::MoveMagnifierWindow(const gfx::Point& point,
604 int x_panning_margin,
605 int y_panning_margin,
606 int x_target_margin,
607 int y_target_margin) {
608 DCHECK(root_window_);
609 int x = origin_.x();
610 int y = origin_.y();
611 bool start_zoom = false;
612
613 const gfx::Rect window_rect = gfx::ToEnclosingRect(GetWindowRectDIP(scale_));
614 const int left = window_rect.x();
615 const int right = window_rect.right();
616
617 int x_diff = 0;
618 if (point.x() < left + x_panning_margin) {
619 // Panning left.
620 x_diff = point.x() - (left + x_target_margin);
621 start_zoom = true;
622 } else if (right - x_panning_margin < point.x()) {
623 // Panning right.
624 x_diff = point.x() - (right - x_target_margin);
625 start_zoom = true;
626 }
627 x = left + x_diff;
628
629 const int top = window_rect.y();
630 const int bottom = window_rect.bottom();
631
632 int y_diff = 0;
633 if (point.y() < top + y_panning_margin) {
634 // Panning up.
635 y_diff = point.y() - (top + y_target_margin);
636 start_zoom = true;
637 } else if (bottom - y_panning_margin < point.y()) {
638 // Panning down.
639 y_diff = point.y() - (bottom - y_target_margin);
640 start_zoom = true;
641 }
642 y = top + y_diff;
643 if (start_zoom && !is_on_animation_) {
644 // No animation on panning.
645 bool animate = false;
646 bool ret = RedrawDIP(gfx::Point(x, y), scale_, animate);
647
648 if (ret) {
649 // If the magnified region is moved, hides the mouse cursor and moves it.
650 if (x_diff != 0 || y_diff != 0)
651 MoveCursorTo(root_window_->GetHost(), point);
652 }
653 }
654 }
655
656 void MagnificationControllerImpl::OnCaretBoundsChanged(
657 const ui::TextInputClient* client) {
658 // caret bounds in screen coordinates.
659 const gfx::Rect caret_bounds = client->GetCaretBounds();
660 // Note: OnCaretBoundsChanged could be fired OnTextInputTypeChanged during
661 // which the caret position is not set a meaning position, and we do not
662 // need to adjust the view port position based on the bogus caret position.
663 // This is only a transition period, the caret position will be fixed upon
664 // focusing right after.
665 if (caret_bounds.width() == 0 && caret_bounds.height() == 0)
666 return;
667
668 gfx::Point caret_origin = caret_bounds.origin();
669 // caret_origin in |root_window_| coordinates.
670 wm::ConvertPointFromScreen(root_window_, &caret_origin);
671
672 // Visible window_rect in |root_window_| coordinates.
673 const gfx::Rect visible_window_rect =
674 gfx::ToEnclosingRect(GetWindowRectDIP(scale_));
675
676 const int panning_margin = kCaretPanningMargin / scale_;
677 MoveMagnifierWindow(caret_origin,
678 panning_margin,
679 panning_margin,
680 visible_window_rect.width() / 2,
681 visible_window_rect.height() / 2);
682 }
683
600 //////////////////////////////////////////////////////////////////////////////// 684 ////////////////////////////////////////////////////////////////////////////////
601 // MagnificationController: 685 // MagnificationController:
602 686
603 // static 687 // static
604 MagnificationController* MagnificationController::CreateInstance() { 688 MagnificationController* MagnificationController::CreateInstance() {
605 return new MagnificationControllerImpl(); 689 return new MagnificationControllerImpl();
606 } 690 }
607 691
608 } // namespace ash 692 } // namespace ash
OLDNEW
« no previous file with comments | « no previous file | ash/magnifier/magnification_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698