OLD | NEW |
---|---|
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/partial_magnification_controller.h" | 5 #include "ash/magnifier/partial_magnification_controller.h" |
6 | 6 |
7 #include "ash/common/system/chromeos/palette/palette_utils.h" | 7 #include "ash/common/system/chromeos/palette/palette_utils.h" |
8 #include "ash/shell.h" | 8 #include "ash/shell.h" |
9 #include "third_party/skia/include/core/SkDrawLooper.h" | |
9 #include "ui/aura/window_event_dispatcher.h" | 10 #include "ui/aura/window_event_dispatcher.h" |
10 #include "ui/aura/window_tree_host.h" | 11 #include "ui/aura/window_tree_host.h" |
11 #include "ui/compositor/layer.h" | 12 #include "ui/compositor/layer.h" |
12 #include "ui/compositor/paint_recorder.h" | 13 #include "ui/compositor/paint_recorder.h" |
13 #include "ui/events/event.h" | 14 #include "ui/events/event.h" |
14 #include "ui/events/event_constants.h" | 15 #include "ui/events/event_constants.h" |
15 #include "ui/views/widget/widget.h" | 16 #include "ui/views/widget/widget.h" |
16 #include "ui/wm/core/coordinate_conversion.h" | 17 #include "ui/wm/core/coordinate_conversion.h" |
17 | 18 |
18 namespace ash { | 19 namespace ash { |
19 namespace { | 20 namespace { |
20 | 21 |
21 // Ratio of magnifier scale. | 22 // Ratio of magnifier scale. |
22 const float kMagnificationScale = 2.f; | 23 const float kMagnificationScale = 2.f; |
23 // Radius of the magnifying glass in DIP. | 24 // Radius of the magnifying glass in DIP. This does not include the thickness |
24 const int kMagnifierRadius = 200; | 25 // of the magnifying glass shadow and border. |
26 const int kMagnifierRadius = 188; | |
25 // Size of the border around the magnifying glass in DIP. | 27 // Size of the border around the magnifying glass in DIP. |
26 const int kBorderSize = 10; | 28 const int kBorderSize = 10; |
27 // Thickness of the outline around magnifying glass border in DIP. | 29 // Thickness of the outline around magnifying glass border in DIP. |
28 const int kBorderOutlineThickness = 2; | 30 const int kBorderOutlineThickness = 1; |
31 // Thickness of the shadow around the magnifying glass in DIP. | |
32 const int kShadowThickness = 24; | |
33 // Offset of the shadow around the magnifying glass in DIP. One of the shadows | |
34 // is lowered a bit, so we have to include |kShadowOffset| in our calculations | |
35 // to compensate. | |
36 const int kShadowOffset = 24; | |
29 // The color of the border and its outlines. The border has an outline on both | 37 // The color of the border and its outlines. The border has an outline on both |
30 // sides, producing a black/white/black ring. | 38 // sides, producing a black/white/black ring. |
31 const SkColor kBorderColor = SK_ColorWHITE; | 39 const SkColor kBorderColor = SkColorSetARGB(204, 255, 255, 255); |
32 const SkColor kBorderOutlineColor = SK_ColorBLACK; | 40 const SkColor kBorderOutlineColor = SkColorSetARGB(51, 0, 0, 0); |
41 // The colors of the two shadow around the magnifiying glass. | |
42 const SkColor kTopShadowColor = SkColorSetARGB(26, 0, 0, 0); | |
43 const SkColor kBottomShadowColor = SkColorSetARGB(61, 0, 0, 0); | |
33 // Inset on the zoom filter. | 44 // Inset on the zoom filter. |
34 const int kZoomInset = 0; | 45 const int kZoomInset = 0; |
35 // Vertical offset between the center of the magnifier and the tip of the | 46 // Vertical offset between the center of the magnifier and the tip of the |
36 // pointer. TODO(jdufault): The vertical offset should only apply to the window | 47 // pointer. TODO(jdufault): The vertical offset should only apply to the window |
37 // location, not the magnified contents. See crbug.com/637617. | 48 // location, not the magnified contents. See crbug.com/637617. |
38 const int kVerticalOffset = 0; | 49 const int kVerticalOffset = 0; |
39 | 50 |
40 // Name of the magnifier window. | 51 // Name of the magnifier window. |
41 const char kPartialMagniferWindowName[] = "PartialMagnifierWindow"; | 52 const char kPartialMagniferWindowName[] = "PartialMagnifierWindow"; |
42 | 53 |
43 gfx::Size GetWindowSize() { | 54 gfx::Size GetWindowSize() { |
44 return gfx::Size(kMagnifierRadius * 2, kMagnifierRadius * 2); | 55 // The diameter of the window is the diameter of the magnifier, border and |
56 // shadow combined. We apply |kShadowOffset| on all sides even though the | |
57 // shadow is only thicker on the bottom so as to keep the circle centered in | |
58 // the view and keep calculations (border rendering and content masking) | |
59 // simpler. | |
60 int window_diameter = | |
61 (kMagnifierRadius + kBorderSize + kShadowThickness + kShadowOffset) * 2; | |
62 return gfx::Size(window_diameter, window_diameter); | |
45 } | 63 } |
46 | 64 |
47 gfx::Rect GetBounds(gfx::Point mouse) { | 65 gfx::Rect GetBounds(gfx::Point mouse) { |
48 gfx::Size size = GetWindowSize(); | 66 gfx::Size size = GetWindowSize(); |
49 gfx::Point origin(mouse.x() - (size.width() / 2), | 67 gfx::Point origin(mouse.x() - (size.width() / 2), |
50 mouse.y() - (size.height() / 2) - kVerticalOffset); | 68 mouse.y() - (size.height() / 2) - kVerticalOffset); |
51 return gfx::Rect(origin, size); | 69 return gfx::Rect(origin, size); |
52 } | 70 } |
53 | 71 |
54 aura::Window* GetCurrentRootWindow() { | 72 aura::Window* GetCurrentRootWindow() { |
55 aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows(); | 73 aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows(); |
56 for (aura::Window* root_window : root_windows) { | 74 for (aura::Window* root_window : root_windows) { |
57 if (root_window->ContainsPointInRoot( | 75 if (root_window->ContainsPointInRoot( |
58 root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot())) | 76 root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot())) |
59 return root_window; | 77 return root_window; |
60 } | 78 } |
61 return nullptr; | 79 return nullptr; |
62 } | 80 } |
63 | 81 |
64 } // namespace | 82 } // namespace |
65 | 83 |
66 // The content mask provides a clipping layer for the magnification window so we | 84 // The content mask provides a clipping layer for the magnification window so we |
67 // can show a circular magnifier. | 85 // can show a circular magnifier. |
68 class PartialMagnificationController::ContentMask : public ui::LayerDelegate { | 86 class PartialMagnificationController::ContentMask : public ui::LayerDelegate { |
69 public: | 87 public: |
70 // If |stroke| is true, the circle will be a stroke. This is useful if we wish | 88 // If |is_border| is true, the circle will be a stroke. This is useful if we |
71 // to clip a border. | 89 // wish to clip a border. |
72 ContentMask(bool stroke, gfx::Size mask_bounds) | 90 ContentMask(bool is_border, gfx::Size mask_bounds) |
73 : layer_(ui::LAYER_TEXTURED), stroke_(stroke) { | 91 : layer_(ui::LAYER_TEXTURED), is_border_(is_border) { |
74 layer_.set_delegate(this); | 92 layer_.set_delegate(this); |
75 layer_.SetFillsBoundsOpaquely(false); | 93 layer_.SetFillsBoundsOpaquely(false); |
76 layer_.SetBounds(gfx::Rect(mask_bounds)); | 94 layer_.SetBounds(gfx::Rect(mask_bounds)); |
77 } | 95 } |
78 | 96 |
79 ~ContentMask() override { layer_.set_delegate(nullptr); } | 97 ~ContentMask() override { layer_.set_delegate(nullptr); } |
80 | 98 |
81 ui::Layer* layer() { return &layer_; } | 99 ui::Layer* layer() { return &layer_; } |
82 | 100 |
83 private: | 101 private: |
84 // ui::LayerDelegate: | 102 // ui::LayerDelegate: |
85 void OnPaintLayer(const ui::PaintContext& context) override { | 103 void OnPaintLayer(const ui::PaintContext& context) override { |
86 ui::PaintRecorder recorder(context, layer()->size()); | 104 ui::PaintRecorder recorder(context, layer()->size()); |
87 | 105 |
88 SkPaint paint; | 106 SkPaint paint; |
89 paint.setAlpha(255); | 107 paint.setAlpha(255); |
90 paint.setAntiAlias(true); | 108 paint.setAntiAlias(true); |
91 paint.setStrokeWidth(kBorderSize); | 109 // Stroke is used for clipping the border which consists of the rendered |
92 paint.setStyle(stroke_ ? SkPaint::kStroke_Style : SkPaint::kFill_Style); | 110 // border |kBorderSize| and the magnifier shadow |kShadowThickness| and |
111 // |kShadowOffset|. | |
112 paint.setStrokeWidth(kBorderSize + kShadowThickness + kShadowOffset); | |
113 paint.setStyle(is_border_ ? SkPaint::kStroke_Style : SkPaint::kFill_Style); | |
93 | 114 |
115 // If we want to clip the magnifier zone use the magnifiers radius. | |
116 // Otherwise we want to clip the border, shadow and shadow offset so we | |
117 // start | |
118 // at the halfway point of the stroke width. | |
94 gfx::Rect rect(layer()->bounds().size()); | 119 gfx::Rect rect(layer()->bounds().size()); |
95 recorder.canvas()->DrawCircle(rect.CenterPoint(), | 120 int clipping_radius = kMagnifierRadius; |
96 rect.width() / 2 - kBorderSize / 2, paint); | 121 if (is_border_) |
122 clipping_radius += (kShadowThickness + kShadowOffset + kBorderSize) / 2; | |
123 recorder.canvas()->DrawCircle(rect.CenterPoint(), clipping_radius, paint); | |
97 } | 124 } |
98 | 125 |
99 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} | 126 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} |
100 | 127 |
101 void OnDeviceScaleFactorChanged(float device_scale_factor) override { | 128 void OnDeviceScaleFactorChanged(float device_scale_factor) override { |
102 // Redrawing will take care of scale factor change. | 129 // Redrawing will take care of scale factor change. |
103 } | 130 } |
104 | 131 |
105 base::Closure PrepareForLayerBoundsChange() override { | 132 base::Closure PrepareForLayerBoundsChange() override { |
106 return base::Closure(); | 133 return base::Closure(); |
107 } | 134 } |
108 | 135 |
109 ui::Layer layer_; | 136 ui::Layer layer_; |
110 bool stroke_; | 137 bool is_border_; |
111 | |
112 DISALLOW_COPY_AND_ASSIGN(ContentMask); | 138 DISALLOW_COPY_AND_ASSIGN(ContentMask); |
113 }; | 139 }; |
114 | 140 |
115 // The border renderer draws the border as well as outline on both the outer and | 141 // The border renderer draws the border as well as outline on both the outer and |
116 // inner radius to increase visibility. | 142 // inner radius to increase visibility. The border renderer also handles drawing |
143 // the shadow. | |
117 class PartialMagnificationController::BorderRenderer | 144 class PartialMagnificationController::BorderRenderer |
118 : public ui::LayerDelegate { | 145 : public ui::LayerDelegate { |
119 public: | 146 public: |
120 explicit BorderRenderer(const gfx::Rect& magnifier_bounds) | 147 explicit BorderRenderer(const gfx::Rect& window_bounds) |
121 : magnifier_bounds_(magnifier_bounds) {} | 148 : magnifier_window_bounds_(window_bounds) { |
149 magnifier_shadows_.push_back(gfx::ShadowValue( | |
150 gfx::Vector2d(0, kShadowOffset), kShadowThickness, kBottomShadowColor)); | |
151 magnifier_shadows_.push_back(gfx::ShadowValue( | |
152 gfx::Vector2d(0, 0), kShadowThickness, kTopShadowColor)); | |
153 } | |
122 | 154 |
123 ~BorderRenderer() override {} | 155 ~BorderRenderer() override {} |
124 | 156 |
125 private: | 157 private: |
126 // ui::LayerDelegate: | 158 // ui::LayerDelegate: |
127 void OnPaintLayer(const ui::PaintContext& context) override { | 159 void OnPaintLayer(const ui::PaintContext& context) override { |
128 ui::PaintRecorder recorder(context, magnifier_bounds_.size()); | 160 ui::PaintRecorder recorder(context, magnifier_window_bounds_.size()); |
129 | 161 |
130 SkPaint paint; | 162 // Draw the shadow. |
131 paint.setAntiAlias(true); | 163 SkPaint shadow_paint; |
132 paint.setStyle(SkPaint::kStroke_Style); | 164 shadow_paint.setAntiAlias(true); |
165 shadow_paint.setColor(SK_ColorTRANSPARENT); | |
166 shadow_paint.setLooper(gfx::CreateShadowDrawLooper(magnifier_shadows_)); | |
James Cook
2016/10/05 19:42:35
I am not familiar with CreateShadowDrawLooper() bu
sammiequon
2016/10/05 19:56:30
Done.
| |
167 gfx::Rect shadow_bounds(magnifier_window_bounds_.size()); | |
168 recorder.canvas()->DrawCircle( | |
169 shadow_bounds.CenterPoint(), | |
170 shadow_bounds.width() / 2 - kShadowThickness - kShadowOffset, | |
171 shadow_paint); | |
133 | 172 |
134 const int magnifier_radius = magnifier_bounds_.width() / 2; | 173 SkPaint border_paint; |
174 border_paint.setAntiAlias(true); | |
175 border_paint.setStyle(SkPaint::kStroke_Style); | |
176 | |
177 // The radius of the magnifier and its border. | |
178 const int magnifier_radius = kMagnifierRadius + kBorderSize; | |
179 | |
135 // Draw the inner border. | 180 // Draw the inner border. |
136 paint.setStrokeWidth(kBorderSize); | 181 border_paint.setStrokeWidth(kBorderSize); |
137 paint.setColor(kBorderColor); | 182 border_paint.setColor(kBorderColor); |
138 recorder.canvas()->DrawCircle(magnifier_bounds_.CenterPoint(), | 183 recorder.canvas()->DrawCircle(magnifier_window_bounds_.CenterPoint(), |
139 magnifier_radius - kBorderSize / 2, paint); | 184 magnifier_radius - kBorderSize / 2, |
185 border_paint); | |
140 | 186 |
141 // Draw border outer outline and then draw the border inner outline. | 187 // Draw border outer outline and then draw the border inner outline. |
142 paint.setStrokeWidth(kBorderOutlineThickness); | 188 border_paint.setStrokeWidth(kBorderOutlineThickness); |
143 paint.setColor(kBorderOutlineColor); | 189 border_paint.setColor(kBorderOutlineColor); |
144 recorder.canvas()->DrawCircle( | 190 recorder.canvas()->DrawCircle( |
145 magnifier_bounds_.CenterPoint(), | 191 magnifier_window_bounds_.CenterPoint(), |
146 magnifier_radius - kBorderOutlineThickness / 2, paint); | 192 magnifier_radius - kBorderOutlineThickness / 2, border_paint); |
147 recorder.canvas()->DrawCircle( | 193 recorder.canvas()->DrawCircle( |
148 magnifier_bounds_.CenterPoint(), | 194 magnifier_window_bounds_.CenterPoint(), |
149 magnifier_radius - kBorderSize + kBorderOutlineThickness / 2, paint); | 195 magnifier_radius - kBorderSize + kBorderOutlineThickness / 2, |
196 border_paint); | |
150 } | 197 } |
151 | 198 |
152 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} | 199 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} |
153 | 200 |
154 void OnDeviceScaleFactorChanged(float device_scale_factor) override {} | 201 void OnDeviceScaleFactorChanged(float device_scale_factor) override {} |
155 | 202 |
156 base::Closure PrepareForLayerBoundsChange() override { | 203 base::Closure PrepareForLayerBoundsChange() override { |
157 return base::Closure(); | 204 return base::Closure(); |
158 } | 205 } |
159 | 206 |
160 gfx::Rect magnifier_bounds_; | 207 gfx::Rect magnifier_window_bounds_; |
208 std::vector<gfx::ShadowValue> magnifier_shadows_; | |
161 | 209 |
162 DISALLOW_COPY_AND_ASSIGN(BorderRenderer); | 210 DISALLOW_COPY_AND_ASSIGN(BorderRenderer); |
163 }; | 211 }; |
164 | 212 |
165 PartialMagnificationController::PartialMagnificationController() { | 213 PartialMagnificationController::PartialMagnificationController() { |
166 Shell::GetInstance()->AddPreTargetHandler(this); | 214 Shell::GetInstance()->AddPreTargetHandler(this); |
167 } | 215 } |
168 | 216 |
169 PartialMagnificationController::~PartialMagnificationController() { | 217 PartialMagnificationController::~PartialMagnificationController() { |
170 CloseMagnifierWindow(); | 218 CloseMagnifierWindow(); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
225 CloseMagnifierWindow(); | 273 CloseMagnifierWindow(); |
226 } | 274 } |
227 } | 275 } |
228 | 276 |
229 void PartialMagnificationController::OnLocatedEvent( | 277 void PartialMagnificationController::OnLocatedEvent( |
230 ui::LocatedEvent* event, | 278 ui::LocatedEvent* event, |
231 const ui::PointerDetails& pointer_details) { | 279 const ui::PointerDetails& pointer_details) { |
232 if (!is_enabled_) | 280 if (!is_enabled_) |
233 return; | 281 return; |
234 | 282 |
235 if (pointer_details.pointer_type != ui::EventPointerType::POINTER_TYPE_PEN) | 283 if (pointer_details.pointer_type == ui::EventPointerType::POINTER_TYPE_PEN) |
James Cook
2016/10/05 19:42:35
For my edification: What's going on here?
It look
sammiequon
2016/10/05 19:56:30
My mistake I was testing the magnifier and i forgo
| |
236 return; | 284 return; |
237 | 285 |
238 // Compute the event location in screen space. | 286 // Compute the event location in screen space. |
239 aura::Window* target = static_cast<aura::Window*>(event->target()); | 287 aura::Window* target = static_cast<aura::Window*>(event->target()); |
240 aura::Window* event_root = target->GetRootWindow(); | 288 aura::Window* event_root = target->GetRootWindow(); |
241 gfx::Point screen_point = event->root_location(); | 289 gfx::Point screen_point = event->root_location(); |
242 wm::ConvertPointToScreen(event_root, &screen_point); | 290 wm::ConvertPointToScreen(event_root, &screen_point); |
243 | 291 |
244 // If the stylus is pressed on the palette icon or widget, do not activate. | 292 // If the stylus is pressed on the palette icon or widget, do not activate. |
245 if (event->type() == ui::ET_MOUSE_PRESSED && | 293 if (event->type() == ui::ET_MOUSE_PRESSED && |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
304 | 352 |
305 zoom_layer_.reset(new ui::Layer(ui::LayerType::LAYER_SOLID_COLOR)); | 353 zoom_layer_.reset(new ui::Layer(ui::LayerType::LAYER_SOLID_COLOR)); |
306 zoom_layer_->SetBounds(gfx::Rect(GetWindowSize())); | 354 zoom_layer_->SetBounds(gfx::Rect(GetWindowSize())); |
307 zoom_layer_->SetBackgroundZoom(kMagnificationScale, kZoomInset); | 355 zoom_layer_->SetBackgroundZoom(kMagnificationScale, kZoomInset); |
308 root_layer->Add(zoom_layer_.get()); | 356 root_layer->Add(zoom_layer_.get()); |
309 | 357 |
310 border_layer_.reset(new ui::Layer(ui::LayerType::LAYER_TEXTURED)); | 358 border_layer_.reset(new ui::Layer(ui::LayerType::LAYER_TEXTURED)); |
311 border_layer_->SetBounds(gfx::Rect(GetWindowSize())); | 359 border_layer_->SetBounds(gfx::Rect(GetWindowSize())); |
312 border_renderer_.reset(new BorderRenderer(gfx::Rect(GetWindowSize()))); | 360 border_renderer_.reset(new BorderRenderer(gfx::Rect(GetWindowSize()))); |
313 border_layer_->set_delegate(border_renderer_.get()); | 361 border_layer_->set_delegate(border_renderer_.get()); |
362 border_layer_->SetFillsBoundsOpaquely(false); | |
314 root_layer->Add(border_layer_.get()); | 363 root_layer->Add(border_layer_.get()); |
315 | 364 |
316 border_mask_.reset(new ContentMask(true, GetWindowSize())); | 365 border_mask_.reset(new ContentMask(true, GetWindowSize())); |
317 border_layer_->SetMaskLayer(border_mask_->layer()); | 366 border_layer_->SetMaskLayer(border_mask_->layer()); |
318 | 367 |
319 zoom_mask_.reset(new ContentMask(false, GetWindowSize())); | 368 zoom_mask_.reset(new ContentMask(false, GetWindowSize())); |
320 zoom_layer_->SetMaskLayer(zoom_mask_->layer()); | 369 zoom_layer_->SetMaskLayer(zoom_mask_->layer()); |
321 | 370 |
322 host_widget_->AddObserver(this); | 371 host_widget_->AddObserver(this); |
323 } | 372 } |
324 | 373 |
325 void PartialMagnificationController::CloseMagnifierWindow() { | 374 void PartialMagnificationController::CloseMagnifierWindow() { |
326 if (host_widget_) { | 375 if (host_widget_) { |
327 RemoveZoomWidgetObservers(); | 376 RemoveZoomWidgetObservers(); |
328 host_widget_->Close(); | 377 host_widget_->Close(); |
329 host_widget_ = nullptr; | 378 host_widget_ = nullptr; |
330 } | 379 } |
331 } | 380 } |
332 | 381 |
333 void PartialMagnificationController::RemoveZoomWidgetObservers() { | 382 void PartialMagnificationController::RemoveZoomWidgetObservers() { |
334 DCHECK(host_widget_); | 383 DCHECK(host_widget_); |
335 host_widget_->RemoveObserver(this); | 384 host_widget_->RemoveObserver(this); |
336 aura::Window* root_window = host_widget_->GetNativeView()->GetRootWindow(); | 385 aura::Window* root_window = host_widget_->GetNativeView()->GetRootWindow(); |
337 DCHECK(root_window); | 386 DCHECK(root_window); |
338 root_window->RemoveObserver(this); | 387 root_window->RemoveObserver(this); |
339 } | 388 } |
340 | 389 |
341 } // namespace ash | 390 } // namespace ash |
OLD | NEW |