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

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

Issue 10915140: Add the partial screen magnifier to Chrome OS. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Code review fixes Created 8 years, 3 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "ash/magnifier/partial_magnification_controller.h"
6
7 #include "ash/shell.h"
8 #include "ui/aura/event_filter.h"
9 #include "ui/aura/root_window.h"
10 #include "ui/aura/shared/compound_event_filter.h"
11 #include "ui/aura/window.h"
12 #include "ui/aura/window_observer.h"
13 #include "ui/aura/window_property.h"
14 #include "ui/gfx/point3.h"
15 #include "ui/gfx/screen.h"
16 #include "ui/compositor/layer.h"
17 #include "ui/views/widget/widget.h"
18 #include "ui/views/widget/widget_delegate.h"
19
20 namespace {
21
22 const float kMinPartialMagnifiedScaleThreshold = 1.1f;
23 const int kZoomInset = 16;
24 const int kMagnifierWidth = 200;
25 const int kMagnifierHeight = 200;
oshima 2012/09/13 16:35:31 doument
Zachary Kuznia 2012/10/09 09:02:36 Done.
26
27 } // namespace
28
29 namespace ash {
30 namespace internal {
31
32 class ZoomDelegateView : public views::WidgetDelegateView {
33 public:
34 explicit ZoomDelegateView();
oshima 2012/09/13 16:35:31 remove explicit
Zachary Kuznia 2012/10/09 09:02:36 Done.
35 virtual ~ZoomDelegateView();
36
37 // views::View overrides
38 virtual gfx::Size GetPreferredSize() OVERRIDE;
39 virtual void Layout() OVERRIDE;
40
41 // views::WidgetZoomDelegateView overrides:
42 virtual bool CanActivate() const OVERRIDE {
43 return false;
44 }
45
46 private:
47
48 DISALLOW_COPY_AND_ASSIGN(ZoomDelegateView);
49 };
50
51 ZoomDelegateView::ZoomDelegateView() {
52 }
53
54 ZoomDelegateView::~ZoomDelegateView() {
55 }
56
57 gfx::Size ZoomDelegateView::GetPreferredSize() {
58 return child_count() > 0 ? child_at(0)->GetPreferredSize() : gfx::Size();
59 }
60
61 void ZoomDelegateView::Layout() {
62 if (child_count() == 0)
63 return;
64 child_at(0)->SetBounds(0, 0, width(), height());
65 }
66
67
68 ////////////////////////////////////////////////////////////////////////////////
69 // PartialMagnificationControllerImpl:
70
71 class PartialMagnificationControllerImpl
72 : public PartialMagnificationController,
73 public aura::EventFilter,
74 public aura::WindowObserver {
75 public:
76 PartialMagnificationControllerImpl();
77 virtual ~PartialMagnificationControllerImpl();
78
79 // PartialMagnificationController overrides:
80 virtual void SetEnabled(bool enabled) OVERRIDE;
81 virtual bool IsEnabled() OVERRIDE;
82 virtual void SetScale(float scale) OVERRIDE;
83 virtual float GetScale() const OVERRIDE { return scale_; }
84
85 private:
86 void OnMouseMove(const gfx::Point& location);
87
88 // Switch PartialMagnified RootWindow to |new_root_window|. This does
89 // following:
90 // - Remove the magnifier from the current root window.
91 // - Create a magnifier in the new root_window |new_root_window|.
92 // - Switch the target window from current window to |new_root_window|.
93 void SwitchTargetRootWindow(aura::RootWindow* new_root_window);
94
95 // Removes self as observer of old root window, sets the root window, and adds
96 // self as observer of the new window.
97 void SetRootWindow(aura::RootWindow* root_window);
98
99 // Return true if the magnification scale > kMinPartialMagnifiedScaleThreshold
100 bool IsPartialMagnified() const;
101
102 // Cleans up the window if needed.
103 void CloseMagnifierWindow();
104
105 // aura::EventFilter overrides:
106 virtual bool PreHandleKeyEvent(aura::Window* target,
107 ui::KeyEvent* event) OVERRIDE;
108 virtual bool PreHandleMouseEvent(aura::Window* target,
109 ui::MouseEvent* event) OVERRIDE;
110 virtual ui::TouchStatus PreHandleTouchEvent(
111 aura::Window* target,
112 ui::TouchEvent* event) OVERRIDE;
113 virtual ui::EventResult PreHandleGestureEvent(
114 aura::Window* target,
115 ui::GestureEvent* event) OVERRIDE;
116
117 // Overridden from WindowObserver:
118 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
119
120 aura::RootWindow* root_window_;
121
122 // True if the magnified window is in motion of zooming or un-zooming effect.
123 // Otherwise, false.
124 bool is_on_zooming_;
125
126 bool is_enabled_;
127
128 // Current scale, origin (left-top) position of the magnification window.
129 float scale_;
130 gfx::Point origin_;
131
132 aura::Window* zoom_window_;
133 views::Widget* zoom_widget_;
134
135 DISALLOW_COPY_AND_ASSIGN(PartialMagnificationControllerImpl);
136 };
137
138 ////////////////////////////////////////////////////////////////////////////////
139 // PartialMagnificationControllerImpl:
140
141 PartialMagnificationControllerImpl::PartialMagnificationControllerImpl()
142 : root_window_(NULL),
143 is_on_zooming_(false),
144 is_enabled_(false),
145 scale_(kNonPartialMagnifiedScale),
146 zoom_window_(NULL),
147 zoom_widget_(NULL) {
148 Shell::GetInstance()->AddEnvEventFilter(this);
149 }
150
151 PartialMagnificationControllerImpl::~PartialMagnificationControllerImpl() {
152 CloseMagnifierWindow();
153
154 Shell::GetInstance()->RemoveEnvEventFilter(this);
155 }
156
157 void PartialMagnificationControllerImpl::OnMouseMove(
158 const gfx::Point& location) {
159 int x = location.x();
160 int y = location.y();
oshima 2012/09/13 16:35:31 or you can use gfx::Point::Offset. up to you.
Zachary Kuznia 2012/10/09 09:02:36 Done.
161
162 if (zoom_window_)
163 zoom_widget_->SetBounds(gfx::Rect(x - kMagnifierWidth / 2,
164 y - kMagnifierHeight / 2,
165 kMagnifierWidth, kMagnifierHeight));
166 }
167
168 bool PartialMagnificationControllerImpl::IsPartialMagnified() const {
169 return scale_ >= kMinPartialMagnifiedScaleThreshold;
170 }
171
172 void PartialMagnificationControllerImpl::CloseMagnifierWindow() {
173 if (zoom_window_) {
174 zoom_widget_->Close();
175 delete zoom_window_;
176 zoom_window_ = NULL;
177 zoom_widget_ = NULL;
178 }
179 }
180
181 void PartialMagnificationControllerImpl::SwitchTargetRootWindow(
182 aura::RootWindow* new_root_window) {
183 if (new_root_window == root_window_)
184 return;
185
186 float scale = GetScale();
187
188 SetScale(1.0f);
189 SetRootWindow(new_root_window);
190 SetScale(scale);
191 }
192
193 void PartialMagnificationControllerImpl::SetRootWindow(
194 aura::RootWindow* root_window) {
195 if (root_window_)
196 root_window_->RemoveObserver(this);
197
198 root_window_ = root_window;
199 if (root_window_)
200 root_window_->AddObserver(this);
201 }
202
203
204 ////////////////////////////////////////////////////////////////////////////////
205 // PartialMagnificationControllerImpl:
206 // PartialMagnificationController implementation
207
208 void PartialMagnificationControllerImpl::SetScale(float scale) {
209 if (!is_enabled_)
210 return;
211
212 scale_ = scale;
213
214 if (IsPartialMagnified()) {
215 if (!zoom_window_) {
216 if (!root_window_)
217 SetRootWindow(ash::Shell::GetActiveRootWindow());
oshima 2012/09/13 16:35:31 Don't you want to use root window where the mouse
Zachary Kuznia 2012/10/09 09:02:36 What is the proper way to get that window? Check
218
219 gfx::Point mouse(root_window_->GetLastMouseLocationInRoot());
220
221 zoom_window_ = new aura::Window(NULL);
222 zoom_window_->Init(ui::LAYER_NOT_DRAWN);
223 root_window_->AddChild(zoom_window_);
oshima 2012/09/13 16:35:31 to which container this will be added? Will this s
Zachary Kuznia 2012/10/09 09:02:36 It's added after the containers, so that it should
224
225 zoom_widget_ = new views::Widget;
226 views::Widget::InitParams params(
227 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
228 params.transparent = true;
229 params.parent = zoom_window_;
230 ZoomDelegateView* delegate_view = new ZoomDelegateView;
231 params.delegate = delegate_view;
232 zoom_widget_->Init(params);
233 zoom_widget_->SetBounds(gfx::Rect(mouse.x() - kMagnifierWidth / 2,
234 mouse.y() - kMagnifierHeight / 2,
235 kMagnifierWidth, kMagnifierHeight));
236 zoom_widget_->set_focus_on_creation(false);
237 zoom_widget_->SetContentsView(delegate_view);
238 zoom_widget_->Show();
239 zoom_window_->layer()->SetBounds(gfx::Rect(0, 0,
240 kMagnifierWidth,
241 kMagnifierHeight));
242 zoom_window_->Show();
243
244 zoom_widget_->GetNativeView()->layer()->SetBackgroundZoom(
245 (kMagnifierWidth - (kMagnifierWidth / scale_)) / 2,
246 (kMagnifierHeight - (kMagnifierHeight / scale_)) / 2,
247 scale_,
248 kZoomInset);
249 }
250 } else {
251 CloseMagnifierWindow();
252 }
253 }
254
255 void PartialMagnificationControllerImpl::SetEnabled(bool enabled) {
256 if (enabled) {
257 is_enabled_ = enabled;
258 SetScale(kDefaultPartialMagnifiedScale);
259 } else {
260 SetScale(kNonPartialMagnifiedScale);
261 is_enabled_ = enabled;
262 }
263 }
264
265 bool PartialMagnificationControllerImpl::IsEnabled() {
266 return is_enabled_;
267 }
268
269
270 ////////////////////////////////////////////////////////////////////////////////
271 // PartialMagnificationControllerImpl: aura::EventFilter implementation
272
273 bool PartialMagnificationControllerImpl::PreHandleKeyEvent(
274 aura::Window* target,
275 ui::KeyEvent* event) {
276 return false;
277 }
278
279 bool PartialMagnificationControllerImpl::PreHandleMouseEvent(
280 aura::Window* target,
281 ui::MouseEvent* event) {
282 if (event->type() == ui::ET_SCROLL && event->IsAltDown()) {
283 ui::ScrollEvent* scroll_event = static_cast<ui::ScrollEvent*>(event);
284 if (scroll_event->y_offset() > 0)
285 SetScale(kDefaultPartialMagnifiedScale);
286 else
287 SetScale(1);
288
289 return true;
290 }
291
292 if (IsPartialMagnified() && event->type() == ui::ET_MOUSE_MOVED) {
293 aura::RootWindow* current_root = target->GetRootWindow();
oshima 2012/09/13 16:35:31 IIRC, target can be on different root when input i
Zachary Kuznia 2012/10/09 09:02:36 It seems to work properly with menus.
294 gfx::Rect root_bounds = current_root->bounds();
295
296 if (root_bounds.Contains(event->root_location())) {
297 if (current_root != root_window_)
298 SwitchTargetRootWindow(current_root);
299
300 OnMouseMove(event->root_location());
301 }
302 }
303
304 return false;
305 }
306
307 ui::TouchStatus PartialMagnificationControllerImpl::PreHandleTouchEvent(
308 aura::Window* target,
309 ui::TouchEvent* event) {
310 return ui::TOUCH_STATUS_UNKNOWN;
311 }
312
313 ui::EventResult PartialMagnificationControllerImpl::PreHandleGestureEvent(
314 aura::Window* target,
315 ui::GestureEvent* event) {
316 return ui::ER_UNHANDLED;
317 }
318
319 ////////////////////////////////////////////////////////////////////////////////
320 // PartialMagnificationControllerImpl: aura::WindowObserver implementation
321
322 void PartialMagnificationControllerImpl::OnWindowDestroying(
323 aura::Window* window) {
324 aura::RootWindow* new_root_window = ash::Shell::GetActiveRootWindow();
325
326 if (new_root_window == root_window_)
327 new_root_window = ash::Shell::GetPrimaryRootWindow();
328
329 if (new_root_window == root_window_)
330 new_root_window = NULL;
331
332 SetRootWindow(new_root_window);
333 }
334
335 ////////////////////////////////////////////////////////////////////////////////
336 // PartialMagnificationController:
337
338 // static
339 PartialMagnificationController*
340 PartialMagnificationController::CreateInstance() {
341 return new PartialMagnificationControllerImpl();
342 }
343
344 } // namespace internal
345 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698