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

Side by Side Diff: components/exo/pointer.cc

Issue 2780623002: exo: Fix multi-display hardware cursor (Closed)
Patch Set: Address comments Created 3 years, 7 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
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 "ash/public/cpp/shell_window_ids.h" 7 #include "ash/public/cpp/shell_window_ids.h"
8 #include "cc/output/copy_output_request.h" 8 #include "cc/output/copy_output_request.h"
9 #include "cc/output/copy_output_result.h" 9 #include "cc/output/copy_output_result.h"
10 #include "components/exo/pointer_delegate.h" 10 #include "components/exo/pointer_delegate.h"
11 #include "components/exo/pointer_stylus_delegate.h" 11 #include "components/exo/pointer_stylus_delegate.h"
12 #include "components/exo/surface.h" 12 #include "components/exo/surface.h"
13 #include "components/exo/wm_helper.h" 13 #include "components/exo/wm_helper.h"
14 #include "ui/aura/client/cursor_client.h" 14 #include "ui/aura/client/cursor_client.h"
15 #include "ui/aura/env.h" 15 #include "ui/aura/env.h"
16 #include "ui/aura/window.h" 16 #include "ui/aura/window.h"
17 #include "ui/base/cursor/cursor_util.h"
17 #include "ui/display/manager/display_manager.h" 18 #include "ui/display/manager/display_manager.h"
18 #include "ui/display/manager/managed_display_info.h" 19 #include "ui/display/manager/managed_display_info.h"
19 #include "ui/display/screen.h" 20 #include "ui/display/screen.h"
20 #include "ui/events/event.h" 21 #include "ui/events/event.h"
21 #include "ui/gfx/geometry/vector2d_conversions.h" 22 #include "ui/gfx/geometry/vector2d_conversions.h"
22 #include "ui/gfx/transform_util.h" 23 #include "ui/gfx/transform_util.h"
23 24
24 #if defined(USE_OZONE) 25 #if defined(USE_OZONE)
25 #include "ui/ozone/public/cursor_factory_ozone.h" 26 #include "ui/ozone/public/cursor_factory_ozone.h"
26 #endif 27 #endif
27 28
28 #if defined(USE_X11) 29 #if defined(USE_X11)
29 #include "ui/base/cursor/cursor_loader_x11.h" 30 #include "ui/base/cursor/cursor_loader_x11.h"
30 #endif 31 #endif
31 32
32 namespace exo { 33 namespace exo {
33 namespace { 34 namespace {
34 35
35 const float kLargeCursorScale = 2.8f; 36 // TODO(oshima): Some accessibility features, including large cursors, disable
37 // hardware cursors. Ash does not support compositing for custom cursors, so it
38 // replaces them with the default cursor. As a result, this scale has no effect
39 // for now. See crbug.com/708378.
40 float GetCursorScale(ui::CursorSetType cursor_set) {
41 return cursor_set == ui::CURSOR_SET_LARGE ? 2.8f : 1.0f;
reveman 2017/05/25 10:52:55 I still prefer if this was folded into UpdateCurso
Dominik Laskowski 2017/05/31 02:06:26 Done.
42 }
36 43
37 // Synthesized events typically lack floating point precision so to avoid 44 // Synthesized events typically lack floating point precision so to avoid
38 // generating mouse event jitter we consider the location of these events 45 // generating mouse event jitter we consider the location of these events
39 // to be the same as |location| if floored values match. 46 // to be the same as |location| if floored values match.
40 bool SameLocation(const ui::LocatedEvent* event, const gfx::PointF& location) { 47 bool SameLocation(const ui::LocatedEvent* event, const gfx::PointF& location) {
41 if (event->flags() & ui::EF_IS_SYNTHESIZED) 48 if (event->flags() & ui::EF_IS_SYNTHESIZED)
42 return event->location() == gfx::ToFlooredPoint(location); 49 return event->location() == gfx::ToFlooredPoint(location);
43 50
44 return event->location_f() == location; 51 return event->location_f() == location;
45 } 52 }
46 53
54 inline const display::ManagedDisplayInfo& GetDisplayInfo(
reveman 2017/05/25 10:52:55 this helper doesn't seem useful. please use WMHelp
Dominik Laskowski 2017/05/31 02:06:26 Done.
55 const display::Display& display) {
56 return WMHelper::GetInstance()->GetDisplayInfo(display.id());
57 }
58
59 constexpr float kCursorCaptureScale = 2.0f;
60
47 } // namespace 61 } // namespace
48 62
49 //////////////////////////////////////////////////////////////////////////////// 63 ////////////////////////////////////////////////////////////////////////////////
50 // Pointer, public: 64 // Pointer, public:
51 65
52 Pointer::Pointer(PointerDelegate* delegate) 66 Pointer::Pointer(PointerDelegate* delegate)
53 : delegate_(delegate), 67 : delegate_(delegate),
54 cursor_(ui::CursorType::kNull),
55 cursor_capture_source_id_(base::UnguessableToken::Create()), 68 cursor_capture_source_id_(base::UnguessableToken::Create()),
56 cursor_capture_weak_ptr_factory_(this) { 69 cursor_capture_weak_ptr_factory_(this) {
57 auto* helper = WMHelper::GetInstance(); 70 auto* helper = WMHelper::GetInstance();
58 helper->AddPreTargetHandler(this); 71 helper->AddPreTargetHandler(this);
59 helper->AddCursorObserver(this); 72 helper->AddCursorObserver(this);
73
74 cursor_scale_ = GetCursorScale(helper->GetCursorSet());
75
76 display::Screen* screen = display::Screen::GetScreen();
77 OnCursorDisplayChanging(
78 screen->GetDisplayNearestPoint(screen->GetCursorScreenPoint()));
reveman 2017/05/25 10:52:55 these lines should not be necessary after addressi
Dominik Laskowski 2017/05/31 02:06:26 Done.
60 } 79 }
61 80
62 Pointer::~Pointer() { 81 Pointer::~Pointer() {
63 delegate_->OnPointerDestroying(this); 82 delegate_->OnPointerDestroying(this);
64 if (surface_) 83 if (surface_)
65 surface_->RemoveSurfaceObserver(this); 84 surface_->RemoveSurfaceObserver(this);
66 if (focus_) { 85 if (focus_) {
67 focus_->RemoveSurfaceObserver(this); 86 focus_->RemoveSurfaceObserver(this);
68 focus_->UnregisterCursorProvider(this); 87 focus_->UnregisterCursorProvider(this);
69 } 88 }
70 auto* helper = WMHelper::GetInstance(); 89 auto* helper = WMHelper::GetInstance();
71 helper->RemoveCursorObserver(this); 90 helper->RemoveCursorObserver(this);
72 helper->RemovePreTargetHandler(this); 91 helper->RemovePreTargetHandler(this);
73 } 92 }
74 93
75 void Pointer::SetCursor(Surface* surface, const gfx::Point& hotspot) { 94 void Pointer::SetCursor(Surface* surface, const gfx::Point& hotspot) {
76 // Early out if the pointer doesn't have a surface in focus. 95 // Early out if the pointer doesn't have a surface in focus.
77 if (!focus_) 96 if (!focus_)
78 return; 97 return;
79 98
80 // This is used to avoid unnecessary cursor changes.
reveman 2017/05/25 10:52:55 I'd like to keep this logic as before.
Dominik Laskowski 2017/05/31 02:06:26 Done.
81 bool cursor_changed = false;
82
83 // If surface is different than the current pointer surface then remove the 99 // If surface is different than the current pointer surface then remove the
84 // current surface and add the new surface. 100 // current surface and add the new surface.
85 if (surface != surface_) { 101 if (surface != surface_) {
86 if (surface && surface->HasSurfaceDelegate()) { 102 if (surface && surface->HasSurfaceDelegate()) {
87 DLOG(ERROR) << "Surface has already been assigned a role"; 103 DLOG(ERROR) << "Surface has already been assigned a role";
88 return; 104 return;
89 } 105 }
90 if (surface_) { 106 if (surface_) {
91 surface_->window()->SetTransform(gfx::Transform()); 107 surface_->window()->SetTransform(gfx::Transform());
92 if (surface_->window()->parent()) 108 if (surface_->window()->parent())
93 surface_->window()->parent()->RemoveChild(surface_->window()); 109 surface_->window()->parent()->RemoveChild(surface_->window());
94 surface_->SetSurfaceDelegate(nullptr); 110 surface_->SetSurfaceDelegate(nullptr);
95 surface_->RemoveSurfaceObserver(this); 111 surface_->RemoveSurfaceObserver(this);
96 } 112 }
97 surface_ = surface; 113 surface_ = surface;
98 if (surface_) { 114 if (surface_) {
99 surface_->SetSurfaceDelegate(this); 115 surface_->SetSurfaceDelegate(this);
100 surface_->AddSurfaceObserver(this); 116 surface_->AddSurfaceObserver(this);
101 // Note: Surface window needs to be added to the tree so we can take a 117 // 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 118 // snapshot. Where in the tree is not important but we might as well use
103 // the cursor container. 119 // the cursor container.
104 WMHelper::GetInstance() 120 WMHelper::GetInstance()
105 ->GetContainer(ash::kShellWindowId_MouseCursorContainer) 121 ->GetContainer(display::Screen::GetScreen()->GetPrimaryDisplay().id(),
122 ash::kShellWindowId_MouseCursorContainer)
106 ->AddChild(surface_->window()); 123 ->AddChild(surface_->window());
107 } 124 }
108 cursor_changed = true; 125 } else if (hotspot == hotspot_) {
126 // Early out if cursor did not change.
127 return;
109 } 128 }
110 129
111 // Update hotspot.
112 if (hotspot != hotspot_) {
113 hotspot_ = hotspot;
114 cursor_changed = true;
115 }
116
117 // Early out if cursor did not change.
118 if (!cursor_changed)
119 return;
120
121 // If |surface_| is set then asynchronously capture a snapshot of cursor, 130 // If |surface_| is set then asynchronously capture a snapshot of cursor,
122 // otherwise cancel pending capture and immediately set the cursor to "none". 131 // otherwise cancel pending capture and immediately set the cursor to "none".
123 if (surface_) { 132 if (surface_) {
124 CaptureCursor(); 133 CaptureCursor(hotspot);
125 } else { 134 } else {
135 cursor_bitmap_.reset();
126 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); 136 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs();
127 cursor_ = ui::CursorType::kNone; 137 SetCursor(ui::CursorType::kNone);
128 UpdateCursor();
129 } 138 }
130 } 139 }
131 140
132 gfx::NativeCursor Pointer::GetCursor() { 141 gfx::NativeCursor Pointer::GetCursor() {
133 return cursor_; 142 if (focus_)
143 if (auto* root_window = focus_->window()->GetRootWindow())
144 if (auto* cursor_client = aura::client::GetCursorClient(root_window))
145 return cursor_client->GetCursor();
146
147 return ui::CursorType::kNull;
134 } 148 }
135 149
136 //////////////////////////////////////////////////////////////////////////////// 150 ////////////////////////////////////////////////////////////////////////////////
137 // ui::EventHandler overrides: 151 // ui::EventHandler overrides:
138 152
139 void Pointer::OnMouseEvent(ui::MouseEvent* event) { 153 void Pointer::OnMouseEvent(ui::MouseEvent* event) {
140 Surface* target = GetEffectiveTargetForEvent(event); 154 Surface* target = GetEffectiveTargetForEvent(event);
141 155
142 // If target is different than the current pointer focus then we need to 156 // If target is different than the current pointer focus then we need to
143 // generate enter and leave events. 157 // generate enter and leave events.
144 if (target != focus_) { 158 if (target != focus_) {
145 // First generate a leave event if we currently have a target in focus. 159 // First generate a leave event if we currently have a target in focus.
146 if (focus_) { 160 if (focus_) {
147 delegate_->OnPointerLeave(focus_); 161 delegate_->OnPointerLeave(focus_);
148 focus_->RemoveSurfaceObserver(this); 162 focus_->RemoveSurfaceObserver(this);
149 // Require SetCursor() to be called and cursor to be re-defined in 163 // Require SetCursor() to be called and cursor to be re-defined in
150 // response to each OnPointerEnter() call. 164 // response to each OnPointerEnter() call.
151 focus_->UnregisterCursorProvider(this); 165 focus_->UnregisterCursorProvider(this);
152 focus_ = nullptr; 166 focus_ = nullptr;
153 cursor_ = ui::CursorType::kNull;
154 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); 167 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs();
155 } 168 }
156 // Second generate an enter event if focus moved to a new target. 169 // Second generate an enter event if focus moved to a new target.
157 if (target) { 170 if (target) {
158 delegate_->OnPointerEnter(target, event->location_f(), 171 delegate_->OnPointerEnter(target, event->location_f(),
159 event->button_flags()); 172 event->button_flags());
160 location_ = event->location_f(); 173 location_ = event->location_f();
161 focus_ = target; 174 focus_ = target;
162 focus_->AddSurfaceObserver(this); 175 focus_->AddSurfaceObserver(this);
163 focus_->RegisterCursorProvider(this); 176 focus_->RegisterCursorProvider(this);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 case ui::ET_MOUSE_ENTERED: 246 case ui::ET_MOUSE_ENTERED:
234 case ui::ET_MOUSE_EXITED: 247 case ui::ET_MOUSE_EXITED:
235 case ui::ET_MOUSE_CAPTURE_CHANGED: 248 case ui::ET_MOUSE_CAPTURE_CHANGED:
236 break; 249 break;
237 default: 250 default:
238 NOTREACHED(); 251 NOTREACHED();
239 break; 252 break;
240 } 253 }
241 254
242 last_event_type_ = event->type(); 255 last_event_type_ = event->type();
243 UpdateCursorScale();
244 } 256 }
245 257
246 void Pointer::OnScrollEvent(ui::ScrollEvent* event) { 258 void Pointer::OnScrollEvent(ui::ScrollEvent* event) {
247 OnMouseEvent(event); 259 OnMouseEvent(event);
248 } 260 }
249 261
250 //////////////////////////////////////////////////////////////////////////////// 262 ////////////////////////////////////////////////////////////////////////////////
251 // WMHelper::CursorObserver overrides: 263 // WMHelper::CursorObserver overrides:
252 264
253 void Pointer::OnCursorSetChanged(ui::CursorSetType cursor_set) { 265 void Pointer::OnCursorSetChanged(ui::CursorSetType cursor_set) {
266 cursor_scale_ = GetCursorScale(cursor_set);
254 if (focus_) 267 if (focus_)
255 UpdateCursorScale(); 268 UpdateCursor();
269 }
270
271 void Pointer::OnCursorDisplayChanging(const display::Display& display) {
272 cursor_device_scale_factor_ = GetDisplayInfo(display).device_scale_factor();
reveman 2017/05/25 10:52:55 hm, do we need |cursor_scale_| and |cursor_rotatio
Dominik Laskowski 2017/05/31 02:06:26 Done.
273 cursor_rotation_ = display.rotation();
256 } 274 }
257 275
258 //////////////////////////////////////////////////////////////////////////////// 276 ////////////////////////////////////////////////////////////////////////////////
259 // SurfaceDelegate overrides: 277 // SurfaceDelegate overrides:
260 278
261 void Pointer::OnSurfaceCommit() { 279 void Pointer::OnSurfaceCommit() {
262 surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces(); 280 surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces();
263 surface_->CommitSurfaceHierarchy(); 281 surface_->CommitSurfaceHierarchy();
264 282
265 // Capture new cursor to reflect result of commit. 283 // Capture new cursor to reflect result of commit.
266 if (focus_) 284 if (focus_)
267 CaptureCursor(); 285 CaptureCursor(hotspot_);
268 } 286 }
269 287
270 bool Pointer::IsSurfaceSynchronized() const { 288 bool Pointer::IsSurfaceSynchronized() const {
271 // A pointer surface is always desynchronized. 289 // A pointer surface is always desynchronized.
272 return false; 290 return false;
273 } 291 }
274 292
275 //////////////////////////////////////////////////////////////////////////////// 293 ////////////////////////////////////////////////////////////////////////////////
276 // SurfaceObserver overrides: 294 // SurfaceObserver overrides:
277 295
(...skipping 11 matching lines...) Expand all
289 307
290 Surface* Pointer::GetEffectiveTargetForEvent(ui::Event* event) const { 308 Surface* Pointer::GetEffectiveTargetForEvent(ui::Event* event) const {
291 Surface* target = 309 Surface* target =
292 Surface::AsSurface(static_cast<aura::Window*>(event->target())); 310 Surface::AsSurface(static_cast<aura::Window*>(event->target()));
293 if (!target) 311 if (!target)
294 return nullptr; 312 return nullptr;
295 313
296 return delegate_->CanAcceptPointerEventsForSurface(target) ? target : nullptr; 314 return delegate_->CanAcceptPointerEventsForSurface(target) ? target : nullptr;
297 } 315 }
298 316
299 void Pointer::UpdateCursorScale() { 317 void Pointer::CaptureCursor(const gfx::Point& hotspot) {
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() {
336 DCHECK(surface_); 318 DCHECK(surface_);
337 DCHECK(focus_); 319 DCHECK(focus_);
338 320
339 // Set UI scale before submitting capture request. 321 // Surface size is in DIPs, while layer size is in pseudo-DIP units that
340 surface_->window()->layer()->SetTransform( 322 // depend on the DSF of the display mode. Scale the layer to capture the
341 gfx::GetScaleTransform(gfx::Point(), cursor_scale_)); 323 // surface at a constant pixel size, regardless of the primary display's
342 324 // UI scale and display mode DSF.
343 float primary_device_scale_factor = 325 display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
344 display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor(); 326 float scale = GetDisplayInfo(display).GetEffectiveUIScale() *
327 kCursorCaptureScale / display.device_scale_factor();
328 surface_->window()->SetTransform(gfx::GetScaleTransform(gfx::Point(), scale));
345 329
346 std::unique_ptr<cc::CopyOutputRequest> request = 330 std::unique_ptr<cc::CopyOutputRequest> request =
347 cc::CopyOutputRequest::CreateBitmapRequest( 331 cc::CopyOutputRequest::CreateBitmapRequest(
348 base::Bind(&Pointer::OnCursorCaptured, 332 base::Bind(&Pointer::OnCursorCaptured,
349 cursor_capture_weak_ptr_factory_.GetWeakPtr(), 333 cursor_capture_weak_ptr_factory_.GetWeakPtr(), hotspot));
350 gfx::ScaleToFlooredPoint( 334
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_); 335 request->set_source(cursor_capture_source_id_);
356 surface_->window()->layer()->RequestCopyOfOutput(std::move(request)); 336 surface_->window()->layer()->RequestCopyOfOutput(std::move(request));
357 } 337 }
358 338
359 void Pointer::OnCursorCaptured(const gfx::Point& hotspot, 339 void Pointer::OnCursorCaptured(const gfx::Point& hotspot,
360 std::unique_ptr<cc::CopyOutputResult> result) { 340 std::unique_ptr<cc::CopyOutputResult> result) {
361 if (!focus_) 341 if (!focus_)
362 return; 342 return;
363 343
364 cursor_ = ui::CursorType::kNone; 344 if (result->IsEmpty()) {
365 if (!result->IsEmpty()) { 345 cursor_bitmap_.reset();
366 DCHECK(result->HasBitmap()); 346 SetCursor(ui::CursorType::kNone);
367 std::unique_ptr<SkBitmap> bitmap = result->TakeBitmap(); 347 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 } 348 }
387 349
350 DCHECK(result->HasBitmap());
351 cursor_bitmap_ = *result->TakeBitmap();
352 hotspot_ = hotspot;
388 UpdateCursor(); 353 UpdateCursor();
389 } 354 }
390 355
391 void Pointer::UpdateCursor() { 356 void Pointer::UpdateCursor() {
392 DCHECK(focus_); 357 DCHECK(focus_);
393 358
359 if (cursor_bitmap_.drawsNothing())
360 return;
361
362 SkBitmap bitmap = cursor_bitmap_;
363 gfx::Point hotspot = gfx::ScaleToFlooredPoint(hotspot_, kCursorCaptureScale);
364
365 ui::ScaleAndRotateCursorBitmapAndHotpoint(
366 cursor_scale_ * cursor_device_scale_factor_ / kCursorCaptureScale,
367 cursor_rotation_, &bitmap, &hotspot);
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, hotspot, 0);
375 #elif defined(USE_X11)
376 XcursorImage* image = ui::SkBitmapToXcursorImage(&bitmap, hotspot);
377 platform_cursor = ui::CreateReffedCustomXCursor(image);
378 #endif
379 gfx::NativeCursor 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
387 SetCursor(cursor);
388 }
389
390 void Pointer::SetCursor(gfx::NativeCursor cursor) {
391 DCHECK(focus_);
392
394 aura::Window* root_window = focus_->window()->GetRootWindow(); 393 aura::Window* root_window = focus_->window()->GetRootWindow();
395 if (!root_window) 394 if (!root_window)
396 return; 395 return;
397 396
398 aura::client::CursorClient* cursor_client = 397 aura::client::CursorClient* cursor_client =
399 aura::client::GetCursorClient(root_window); 398 aura::client::GetCursorClient(root_window);
400 if (cursor_client) 399 if (cursor_client)
401 cursor_client->SetCursor(cursor_); 400 cursor_client->SetCursor(cursor);
402 } 401 }
403 402
404 } // namespace exo 403 } // namespace exo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698