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

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

Powered by Google App Engine
This is Rietveld 408576698