OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "components/exo/pointer.h" | 5 #include "components/exo/pointer.h" |
6 | 6 |
7 #include <algorithm> | |
8 | |
7 #include "ash/public/cpp/shell_window_ids.h" | 9 #include "ash/public/cpp/shell_window_ids.h" |
8 #include "cc/output/copy_output_request.h" | 10 #include "cc/output/copy_output_request.h" |
9 #include "cc/output/copy_output_result.h" | 11 #include "cc/output/copy_output_result.h" |
10 #include "components/exo/pointer_delegate.h" | 12 #include "components/exo/pointer_delegate.h" |
11 #include "components/exo/pointer_stylus_delegate.h" | 13 #include "components/exo/pointer_stylus_delegate.h" |
12 #include "components/exo/surface.h" | 14 #include "components/exo/surface.h" |
13 #include "components/exo/wm_helper.h" | 15 #include "components/exo/wm_helper.h" |
14 #include "ui/aura/client/cursor_client.h" | 16 #include "ui/aura/client/cursor_client.h" |
15 #include "ui/aura/env.h" | 17 #include "ui/aura/env.h" |
16 #include "ui/aura/window.h" | 18 #include "ui/aura/window.h" |
19 #include "ui/base/cursor/cursor_util.h" | |
17 #include "ui/display/manager/display_manager.h" | 20 #include "ui/display/manager/display_manager.h" |
18 #include "ui/display/manager/managed_display_info.h" | 21 #include "ui/display/manager/managed_display_info.h" |
19 #include "ui/display/screen.h" | 22 #include "ui/display/screen.h" |
20 #include "ui/events/event.h" | 23 #include "ui/events/event.h" |
21 #include "ui/gfx/geometry/vector2d_conversions.h" | 24 #include "ui/gfx/geometry/vector2d_conversions.h" |
22 #include "ui/gfx/transform_util.h" | 25 #include "ui/gfx/transform_util.h" |
23 | 26 |
24 #if defined(USE_OZONE) | 27 #if defined(USE_OZONE) |
25 #include "ui/ozone/public/cursor_factory_ozone.h" | 28 #include "ui/ozone/public/cursor_factory_ozone.h" |
26 #endif | 29 #endif |
27 | 30 |
28 #if defined(USE_X11) | 31 #if defined(USE_X11) |
29 #include "ui/base/cursor/cursor_loader_x11.h" | 32 #include "ui/base/cursor/cursor_loader_x11.h" |
30 #endif | 33 #endif |
31 | 34 |
32 namespace exo { | 35 namespace exo { |
33 namespace { | 36 namespace { |
34 | 37 |
35 const float kLargeCursorScale = 2.8f; | 38 // TODO(oshima): Some accessibility features, including large cursors, disable |
reveman
2017/05/23 17:06:57
please minimize the patch and avoid this change th
Dominik Laskowski
2017/05/24 00:43:04
It's needed due to the new logic for updating scal
reveman
2017/05/25 10:52:55
I'm failing to see why. Please explain.
Dominik Laskowski
2017/05/31 02:06:26
Folded into UpdateCursor.
| |
39 // hardware cursors. Ash does not support compositing for custom cursors, so it | |
40 // replaces them with the default cursor. As a result, this scale has no effect | |
41 // for now. See crbug.com/708378. | |
42 float GetCursorScale(ui::CursorSetType cursor_set) { | |
43 return cursor_set == ui::CURSOR_SET_LARGE ? 2.8f : 1.0f; | |
44 } | |
36 | 45 |
37 // Synthesized events typically lack floating point precision so to avoid | 46 // Synthesized events typically lack floating point precision so to avoid |
38 // generating mouse event jitter we consider the location of these events | 47 // generating mouse event jitter we consider the location of these events |
39 // to be the same as |location| if floored values match. | 48 // to be the same as |location| if floored values match. |
40 bool SameLocation(const ui::LocatedEvent* event, const gfx::PointF& location) { | 49 bool SameLocation(const ui::LocatedEvent* event, const gfx::PointF& location) { |
41 if (event->flags() & ui::EF_IS_SYNTHESIZED) | 50 if (event->flags() & ui::EF_IS_SYNTHESIZED) |
42 return event->location() == gfx::ToFlooredPoint(location); | 51 return event->location() == gfx::ToFlooredPoint(location); |
43 | 52 |
44 return event->location_f() == location; | 53 return event->location_f() == location; |
45 } | 54 } |
46 | 55 |
56 inline const display::ManagedDisplayInfo& GetDisplayInfo( | |
57 const display::Display& display) { | |
58 return WMHelper::GetInstance()->GetDisplayInfo(display.id()); | |
59 } | |
60 | |
61 display::Display GetCaptureDisplay() { | |
reveman
2017/05/23 17:06:57
What if no DSF 2.0 display exists but is later add
Dominik Laskowski
2017/05/24 00:43:04
Good point. Capturing at constant pixel size is si
| |
62 const auto& displays = display::Screen::GetScreen()->GetAllDisplays(); | |
63 DCHECK(!displays.empty()); | |
64 return *std::max_element( | |
65 displays.begin(), displays.end(), | |
66 [](const display::Display& lhs, const display::Display& rhs) -> bool { | |
67 return GetDisplayInfo(lhs).device_scale_factor() < | |
68 GetDisplayInfo(rhs).device_scale_factor(); | |
69 }); | |
70 } | |
71 | |
47 } // namespace | 72 } // namespace |
48 | 73 |
49 //////////////////////////////////////////////////////////////////////////////// | 74 //////////////////////////////////////////////////////////////////////////////// |
50 // Pointer, public: | 75 // Pointer, public: |
51 | 76 |
52 Pointer::Pointer(PointerDelegate* delegate) | 77 Pointer::Pointer(PointerDelegate* delegate) |
53 : delegate_(delegate), | 78 : delegate_(delegate), |
54 cursor_(ui::CursorType::kNull), | |
55 cursor_capture_source_id_(base::UnguessableToken::Create()), | 79 cursor_capture_source_id_(base::UnguessableToken::Create()), |
56 cursor_capture_weak_ptr_factory_(this) { | 80 cursor_capture_weak_ptr_factory_(this) { |
57 auto* helper = WMHelper::GetInstance(); | 81 auto* helper = WMHelper::GetInstance(); |
58 helper->AddPreTargetHandler(this); | 82 helper->AddPreTargetHandler(this); |
59 helper->AddCursorObserver(this); | 83 helper->AddCursorObserver(this); |
84 | |
reveman
2017/05/23 17:06:57
why are the following 4 lines needed?
Dominik Laskowski
2017/05/24 00:43:04
To initialize the state updated by OnCursorSetChan
| |
85 cursor_scale_ = GetCursorScale(helper->GetCursorSet()); | |
86 | |
87 OnCursorDisplayChanging(display::Screen::GetScreen()->GetPrimaryDisplay()); | |
60 } | 88 } |
61 | 89 |
62 Pointer::~Pointer() { | 90 Pointer::~Pointer() { |
63 delegate_->OnPointerDestroying(this); | 91 delegate_->OnPointerDestroying(this); |
64 if (surface_) | 92 if (surface_) |
65 surface_->RemoveSurfaceObserver(this); | 93 surface_->RemoveSurfaceObserver(this); |
66 if (focus_) { | 94 if (focus_) { |
67 focus_->RemoveSurfaceObserver(this); | 95 focus_->RemoveSurfaceObserver(this); |
68 focus_->UnregisterCursorProvider(this); | 96 focus_->UnregisterCursorProvider(this); |
69 } | 97 } |
(...skipping 25 matching lines...) Expand all Loading... | |
95 surface_->RemoveSurfaceObserver(this); | 123 surface_->RemoveSurfaceObserver(this); |
96 } | 124 } |
97 surface_ = surface; | 125 surface_ = surface; |
98 if (surface_) { | 126 if (surface_) { |
99 surface_->SetSurfaceDelegate(this); | 127 surface_->SetSurfaceDelegate(this); |
100 surface_->AddSurfaceObserver(this); | 128 surface_->AddSurfaceObserver(this); |
101 // Note: Surface window needs to be added to the tree so we can take a | 129 // Note: Surface window needs to be added to the tree so we can take a |
102 // snapshot. Where in the tree is not important but we might as well use | 130 // snapshot. Where in the tree is not important but we might as well use |
103 // the cursor container. | 131 // the cursor container. |
104 WMHelper::GetInstance() | 132 WMHelper::GetInstance() |
105 ->GetContainer(ash::kShellWindowId_MouseCursorContainer) | 133 ->GetContainer(GetCaptureDisplay().id(), |
134 ash::kShellWindowId_MouseCursorContainer) | |
106 ->AddChild(surface_->window()); | 135 ->AddChild(surface_->window()); |
107 } | 136 } |
108 cursor_changed = true; | 137 cursor_changed = true; |
109 } | 138 } |
110 | 139 |
111 // Update hotspot. | 140 // Update hotspot. |
112 if (hotspot != hotspot_) { | 141 if (hotspot != hotspot_) { |
113 hotspot_ = hotspot; | 142 hotspot_ = hotspot; |
114 cursor_changed = true; | 143 cursor_changed = true; |
115 } | 144 } |
116 | 145 |
117 // Early out if cursor did not change. | 146 // Early out if cursor did not change. |
118 if (!cursor_changed) | 147 if (!cursor_changed) |
119 return; | 148 return; |
120 | 149 |
121 // If |surface_| is set then asynchronously capture a snapshot of cursor, | 150 // If |surface_| is set then asynchronously capture a snapshot of cursor, |
122 // otherwise cancel pending capture and immediately set the cursor to "none". | 151 // otherwise cancel pending capture and immediately set the cursor to "none". |
123 if (surface_) { | 152 if (surface_) { |
124 CaptureCursor(); | 153 CaptureCursor(); |
125 } else { | 154 } else { |
155 cursor_.reset(); | |
126 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); | 156 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); |
127 cursor_ = ui::CursorType::kNone; | 157 SetCursor(ui::CursorType::kNone); |
128 UpdateCursor(); | |
129 } | 158 } |
130 } | 159 } |
131 | 160 |
132 gfx::NativeCursor Pointer::GetCursor() { | 161 gfx::NativeCursor Pointer::GetCursor() { |
133 return cursor_; | 162 if (focus_) |
163 if (auto* root_window = focus_->window()->GetRootWindow()) | |
164 if (auto* cursor_client = aura::client::GetCursorClient(root_window)) | |
165 return cursor_client->GetCursor(); | |
166 | |
167 return ui::CursorType::kNull; | |
134 } | 168 } |
135 | 169 |
136 //////////////////////////////////////////////////////////////////////////////// | 170 //////////////////////////////////////////////////////////////////////////////// |
137 // ui::EventHandler overrides: | 171 // ui::EventHandler overrides: |
138 | 172 |
139 void Pointer::OnMouseEvent(ui::MouseEvent* event) { | 173 void Pointer::OnMouseEvent(ui::MouseEvent* event) { |
140 Surface* target = GetEffectiveTargetForEvent(event); | 174 Surface* target = GetEffectiveTargetForEvent(event); |
141 | 175 |
142 // If target is different than the current pointer focus then we need to | 176 // If target is different than the current pointer focus then we need to |
143 // generate enter and leave events. | 177 // generate enter and leave events. |
144 if (target != focus_) { | 178 if (target != focus_) { |
145 // First generate a leave event if we currently have a target in focus. | 179 // First generate a leave event if we currently have a target in focus. |
146 if (focus_) { | 180 if (focus_) { |
147 delegate_->OnPointerLeave(focus_); | 181 delegate_->OnPointerLeave(focus_); |
148 focus_->RemoveSurfaceObserver(this); | 182 focus_->RemoveSurfaceObserver(this); |
149 // Require SetCursor() to be called and cursor to be re-defined in | 183 // Require SetCursor() to be called and cursor to be re-defined in |
150 // response to each OnPointerEnter() call. | 184 // response to each OnPointerEnter() call. |
151 focus_->UnregisterCursorProvider(this); | 185 focus_->UnregisterCursorProvider(this); |
152 focus_ = nullptr; | 186 focus_ = nullptr; |
153 cursor_ = ui::CursorType::kNull; | |
154 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); | 187 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); |
155 } | 188 } |
156 // Second generate an enter event if focus moved to a new target. | 189 // Second generate an enter event if focus moved to a new target. |
157 if (target) { | 190 if (target) { |
158 delegate_->OnPointerEnter(target, event->location_f(), | 191 delegate_->OnPointerEnter(target, event->location_f(), |
159 event->button_flags()); | 192 event->button_flags()); |
160 location_ = event->location_f(); | 193 location_ = event->location_f(); |
161 focus_ = target; | 194 focus_ = target; |
162 focus_->AddSurfaceObserver(this); | 195 focus_->AddSurfaceObserver(this); |
163 focus_->RegisterCursorProvider(this); | 196 focus_->RegisterCursorProvider(this); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
233 case ui::ET_MOUSE_ENTERED: | 266 case ui::ET_MOUSE_ENTERED: |
234 case ui::ET_MOUSE_EXITED: | 267 case ui::ET_MOUSE_EXITED: |
235 case ui::ET_MOUSE_CAPTURE_CHANGED: | 268 case ui::ET_MOUSE_CAPTURE_CHANGED: |
236 break; | 269 break; |
237 default: | 270 default: |
238 NOTREACHED(); | 271 NOTREACHED(); |
239 break; | 272 break; |
240 } | 273 } |
241 | 274 |
242 last_event_type_ = event->type(); | 275 last_event_type_ = event->type(); |
243 UpdateCursorScale(); | |
244 } | 276 } |
245 | 277 |
246 void Pointer::OnScrollEvent(ui::ScrollEvent* event) { | 278 void Pointer::OnScrollEvent(ui::ScrollEvent* event) { |
247 OnMouseEvent(event); | 279 OnMouseEvent(event); |
248 } | 280 } |
249 | 281 |
250 //////////////////////////////////////////////////////////////////////////////// | 282 //////////////////////////////////////////////////////////////////////////////// |
251 // WMHelper::CursorObserver overrides: | 283 // WMHelper::CursorObserver overrides: |
252 | 284 |
253 void Pointer::OnCursorSetChanged(ui::CursorSetType cursor_set) { | 285 void Pointer::OnCursorSetChanged(ui::CursorSetType cursor_set) { |
286 cursor_scale_ = GetCursorScale(cursor_set); | |
254 if (focus_) | 287 if (focus_) |
255 UpdateCursorScale(); | 288 UpdateCursor(); |
289 } | |
290 | |
291 void Pointer::OnCursorDisplayChanging(const display::Display& display) { | |
292 device_scale_factor_ = GetDisplayInfo(display).device_scale_factor(); | |
293 rotation_ = display.rotation(); | |
256 } | 294 } |
257 | 295 |
258 //////////////////////////////////////////////////////////////////////////////// | 296 //////////////////////////////////////////////////////////////////////////////// |
259 // SurfaceDelegate overrides: | 297 // SurfaceDelegate overrides: |
260 | 298 |
261 void Pointer::OnSurfaceCommit() { | 299 void Pointer::OnSurfaceCommit() { |
262 surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces(); | 300 surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces(); |
263 surface_->CommitSurfaceHierarchy(); | 301 surface_->CommitSurfaceHierarchy(); |
264 | 302 |
265 // Capture new cursor to reflect result of commit. | 303 // Capture new cursor to reflect result of commit. |
(...skipping 23 matching lines...) Expand all Loading... | |
289 | 327 |
290 Surface* Pointer::GetEffectiveTargetForEvent(ui::Event* event) const { | 328 Surface* Pointer::GetEffectiveTargetForEvent(ui::Event* event) const { |
291 Surface* target = | 329 Surface* target = |
292 Surface::AsSurface(static_cast<aura::Window*>(event->target())); | 330 Surface::AsSurface(static_cast<aura::Window*>(event->target())); |
293 if (!target) | 331 if (!target) |
294 return nullptr; | 332 return nullptr; |
295 | 333 |
296 return delegate_->CanAcceptPointerEventsForSurface(target) ? target : nullptr; | 334 return delegate_->CanAcceptPointerEventsForSurface(target) ? target : nullptr; |
297 } | 335 } |
298 | 336 |
299 void Pointer::UpdateCursorScale() { | |
300 DCHECK(focus_); | |
301 | |
302 display::Screen* screen = display::Screen::GetScreen(); | |
303 WMHelper* helper = WMHelper::GetInstance(); | |
304 | |
305 // Update cursor scale if the effective UI scale has changed. | |
306 display::Display display = screen->GetDisplayNearestWindow(focus_->window()); | |
307 float scale = helper->GetDisplayInfo(display.id()).GetEffectiveUIScale(); | |
308 | |
309 if (display::Display::HasInternalDisplay()) { | |
310 float primary_device_scale_factor = | |
311 screen->GetPrimaryDisplay().device_scale_factor(); | |
312 // The size of the cursor surface is the quotient of its physical size and | |
313 // the DSF of the primary display. The physical size is proportional to the | |
314 // DSF of the internal display. For external displays (and the internal | |
315 // display when secondary to a display with a different DSF), scale the | |
316 // cursor so its physical size matches with the single display case. | |
317 if (!display.IsInternal() || | |
318 display.device_scale_factor() != primary_device_scale_factor) { | |
319 scale *= primary_device_scale_factor / | |
320 helper->GetDisplayInfo(display::Display::InternalDisplayId()) | |
321 .device_scale_factor(); | |
322 } | |
323 } | |
324 | |
325 if (helper->GetCursorSet() == ui::CURSOR_SET_LARGE) | |
326 scale *= kLargeCursorScale; | |
327 | |
328 if (scale != cursor_scale_) { | |
329 cursor_scale_ = scale; | |
330 if (surface_) | |
331 CaptureCursor(); | |
332 } | |
333 } | |
334 | |
335 void Pointer::CaptureCursor() { | 337 void Pointer::CaptureCursor() { |
336 DCHECK(surface_); | 338 DCHECK(surface_); |
337 DCHECK(focus_); | 339 DCHECK(focus_); |
338 | 340 |
339 // Set UI scale before submitting capture request. | 341 // Surface size is in DIPs, while layer size is in pseudo-DIP units that |
340 surface_->window()->layer()->SetTransform( | 342 // depend on the DSF of the display mode. Scale the layer to capture the |
341 gfx::GetScaleTransform(gfx::Point(), cursor_scale_)); | 343 // surface at a constant pixel size converted from DIPs using the DSF of |
342 | 344 // the capture display, regardless of its UI scale and display mode DSF. |
343 float primary_device_scale_factor = | 345 display::Display display = GetCaptureDisplay(); |
344 display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor(); | 346 const auto& info = GetDisplayInfo(display); |
347 float display_scale = info.GetEffectiveUIScale() * info.device_scale_factor(); | |
348 surface_->window()->SetTransform(gfx::GetScaleTransform( | |
349 gfx::Point(), display_scale / display.device_scale_factor())); | |
345 | 350 |
346 std::unique_ptr<cc::CopyOutputRequest> request = | 351 std::unique_ptr<cc::CopyOutputRequest> request = |
347 cc::CopyOutputRequest::CreateBitmapRequest( | 352 cc::CopyOutputRequest::CreateBitmapRequest( |
348 base::Bind(&Pointer::OnCursorCaptured, | 353 base::Bind(&Pointer::OnCursorCaptured, |
349 cursor_capture_weak_ptr_factory_.GetWeakPtr(), | 354 cursor_capture_weak_ptr_factory_.GetWeakPtr())); |
350 gfx::ScaleToFlooredPoint( | 355 |
351 hotspot_, | |
352 // |hotspot_| is in surface coordinate space so apply | |
353 // both device scale and UI scale. | |
354 cursor_scale_ * primary_device_scale_factor))); | |
355 request->set_source(cursor_capture_source_id_); | 356 request->set_source(cursor_capture_source_id_); |
356 surface_->window()->layer()->RequestCopyOfOutput(std::move(request)); | 357 surface_->window()->layer()->RequestCopyOfOutput(std::move(request)); |
357 } | 358 } |
358 | 359 |
359 void Pointer::OnCursorCaptured(const gfx::Point& hotspot, | 360 void Pointer::OnCursorCaptured(std::unique_ptr<cc::CopyOutputResult> result) { |
360 std::unique_ptr<cc::CopyOutputResult> result) { | |
361 if (!focus_) | 361 if (!focus_) |
362 return; | 362 return; |
363 | 363 |
364 cursor_ = ui::CursorType::kNone; | 364 if (result->IsEmpty()) { |
365 if (!result->IsEmpty()) { | 365 cursor_.reset(); |
366 DCHECK(result->HasBitmap()); | 366 SetCursor(ui::CursorType::kNone); |
367 std::unique_ptr<SkBitmap> bitmap = result->TakeBitmap(); | 367 return; |
368 | |
369 ui::PlatformCursor platform_cursor; | |
370 #if defined(USE_OZONE) | |
371 // TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers | |
372 // and use that here instead of the current bitmap API. crbug.com/686600 | |
373 platform_cursor = ui::CursorFactoryOzone::GetInstance()->CreateImageCursor( | |
374 *bitmap.get(), hotspot, cursor_scale_); | |
375 #elif defined(USE_X11) | |
376 XcursorImage* image = ui::SkBitmapToXcursorImage(bitmap.get(), hotspot); | |
377 platform_cursor = ui::CreateReffedCustomXCursor(image); | |
378 #endif | |
379 cursor_ = ui::CursorType::kCustom; | |
380 cursor_.SetPlatformCursor(platform_cursor); | |
381 #if defined(USE_OZONE) | |
382 ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor); | |
383 #elif defined(USE_X11) | |
384 ui::UnrefCustomXCursor(platform_cursor); | |
385 #endif | |
386 } | 368 } |
387 | 369 |
370 DCHECK(result->HasBitmap()); | |
371 cursor_ = *result->TakeBitmap(); | |
388 UpdateCursor(); | 372 UpdateCursor(); |
389 } | 373 } |
390 | 374 |
391 void Pointer::UpdateCursor() { | 375 void Pointer::UpdateCursor() { |
392 DCHECK(focus_); | 376 DCHECK(focus_); |
393 | 377 |
378 if (cursor_.drawsNothing()) | |
379 return; | |
380 | |
381 const auto& info = GetDisplayInfo(GetCaptureDisplay()); | |
382 | |
383 SkBitmap bitmap = cursor_; | |
384 gfx::Point hotspot = | |
385 gfx::ScaleToFlooredPoint(hotspot_, info.device_scale_factor()); | |
386 | |
387 ui::ScaleAndRotateCursorBitmapAndHotpoint( | |
388 cursor_scale_ * device_scale_factor_ / info.device_scale_factor(), | |
389 rotation_, &bitmap, &hotspot); | |
390 | |
391 ui::PlatformCursor platform_cursor; | |
392 #if defined(USE_OZONE) | |
393 // TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers | |
394 // and use that here instead of the current bitmap API. crbug.com/686600 | |
395 platform_cursor = ui::CursorFactoryOzone::GetInstance()->CreateImageCursor( | |
396 bitmap, hotspot, 0); | |
397 #elif defined(USE_X11) | |
398 XcursorImage* image = ui::SkBitmapToXcursorImage(&bitmap, hotspot); | |
399 platform_cursor = ui::CreateReffedCustomXCursor(image); | |
400 #endif | |
401 gfx::NativeCursor cursor = ui::CursorType::kCustom; | |
402 cursor.SetPlatformCursor(platform_cursor); | |
403 #if defined(USE_OZONE) | |
404 ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor); | |
405 #elif defined(USE_X11) | |
406 ui::UnrefCustomXCursor(platform_cursor); | |
407 #endif | |
408 | |
409 SetCursor(cursor); | |
410 } | |
411 | |
412 void Pointer::SetCursor(gfx::NativeCursor cursor) { | |
413 DCHECK(focus_); | |
414 | |
394 aura::Window* root_window = focus_->window()->GetRootWindow(); | 415 aura::Window* root_window = focus_->window()->GetRootWindow(); |
395 if (!root_window) | 416 if (!root_window) |
396 return; | 417 return; |
397 | 418 |
398 aura::client::CursorClient* cursor_client = | 419 aura::client::CursorClient* cursor_client = |
399 aura::client::GetCursorClient(root_window); | 420 aura::client::GetCursorClient(root_window); |
400 if (cursor_client) | 421 if (cursor_client) |
401 cursor_client->SetCursor(cursor_); | 422 cursor_client->SetCursor(cursor); |
402 } | 423 } |
403 | 424 |
404 } // namespace exo | 425 } // namespace exo |
OLD | NEW |