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

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

Issue 2780623002: exo: Fix multi-display hardware cursor (Closed)
Patch Set: Rebase properly Created 3 years, 8 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/display/manager/display_manager.h" 17 #include "ui/display/manager/display_manager.h"
18 #include "ui/display/manager/managed_display_info.h" 18 #include "ui/display/manager/managed_display_info.h"
19 #include "ui/display/screen.h" 19 #include "ui/display/screen.h"
20 #include "ui/events/event.h" 20 #include "ui/events/event.h"
21 #include "ui/gfx/geometry/vector2d_conversions.h" 21 #include "ui/gfx/geometry/vector2d_conversions.h"
22 #include "ui/gfx/transform_util.h" 22 #include "ui/gfx/transform.h"
23 23
24 #if defined(USE_OZONE) 24 #if defined(USE_OZONE)
25 #include "ui/ozone/public/cursor_factory_ozone.h" 25 #include "ui/ozone/public/cursor_factory_ozone.h"
26 #endif 26 #endif
27 27
28 #if defined(USE_X11) 28 #if defined(USE_X11)
29 #include "ui/base/cursor/cursor_loader_x11.h" 29 #include "ui/base/cursor/cursor_loader_x11.h"
30 #endif 30 #endif
31 31
32 namespace exo { 32 namespace exo {
33 namespace { 33 namespace {
34 34
35 const float kLargeCursorScale = 2.8f; 35 // TODO: Some accessibility features, including large cursors, disable hardware
reveman 2017/03/30 07:47:53 nit: TODO(name) and please add a bug number
Dominik Laskowski 2017/04/05 17:59:25 Done. TODO(oshima) to be consistent with: https:/
36 // cursors. Ash does not support compositing for custom cursors, so it replaces
37 // them with the default cursor. As a result, this scale has no effect for now.
38 float GetCursorScale(ui::CursorSetType cursor_set) {
39 return cursor_set == ui::CURSOR_SET_LARGE ? 2.8f : 1.0f;
40 }
36 41
37 // Synthesized events typically lack floating point precision so to avoid 42 // Synthesized events typically lack floating point precision so to avoid
38 // generating mouse event jitter we consider the location of these events 43 // generating mouse event jitter we consider the location of these events
39 // to be the same as |location| if floored values match. 44 // to be the same as |location| if floored values match.
40 bool SameLocation(const ui::LocatedEvent* event, const gfx::PointF& location) { 45 bool SameLocation(const ui::LocatedEvent* event, const gfx::PointF& location) {
41 if (event->flags() & ui::EF_IS_SYNTHESIZED) 46 if (event->flags() & ui::EF_IS_SYNTHESIZED)
42 return event->location() == gfx::ToFlooredPoint(location); 47 return event->location() == gfx::ToFlooredPoint(location);
43 48
44 return event->location_f() == location; 49 return event->location_f() == location;
45 } 50 }
46 51
47 } // namespace 52 } // namespace
48 53
49 //////////////////////////////////////////////////////////////////////////////// 54 ////////////////////////////////////////////////////////////////////////////////
50 // Pointer, public: 55 // Pointer, public:
51 56
52 Pointer::Pointer(PointerDelegate* delegate) 57 Pointer::Pointer(PointerDelegate* delegate)
53 : delegate_(delegate), 58 : delegate_(delegate),
54 cursor_(ui::kCursorNull), 59 cursor_(new aura::Window(nullptr)),
55 cursor_capture_source_id_(base::UnguessableToken::Create()), 60 cursor_capture_source_id_(base::UnguessableToken::Create()),
56 cursor_capture_weak_ptr_factory_(this) { 61 cursor_capture_weak_ptr_factory_(this) {
57 auto* helper = WMHelper::GetInstance(); 62 auto* helper = WMHelper::GetInstance();
58 helper->AddPreTargetHandler(this); 63 helper->AddPreTargetHandler(this);
59 helper->AddCursorObserver(this); 64 helper->AddCursorObserver(this);
65
66 cursor_scale_ = GetCursorScale(helper->GetCursorSet());
67
68 cursor_->SetName("ExoCursor");
69 cursor_->Init(ui::LAYER_NOT_DRAWN);
70 cursor_->set_owned_by_parent(false);
71 OnCursorDisplayChanging(display::Screen::GetScreen()->GetPrimaryDisplay());
60 } 72 }
61 73
62 Pointer::~Pointer() { 74 Pointer::~Pointer() {
63 delegate_->OnPointerDestroying(this); 75 delegate_->OnPointerDestroying(this);
64 if (surface_) 76 if (surface_)
65 surface_->RemoveSurfaceObserver(this); 77 surface_->RemoveSurfaceObserver(this);
66 if (focus_) { 78 if (focus_) {
67 focus_->RemoveSurfaceObserver(this); 79 focus_->RemoveSurfaceObserver(this);
68 focus_->UnregisterCursorProvider(this); 80 focus_->UnregisterCursorProvider(this);
69 } 81 }
(...skipping 11 matching lines...) Expand all
81 bool cursor_changed = false; 93 bool cursor_changed = false;
82 94
83 // If surface is different than the current pointer surface then remove the 95 // If surface is different than the current pointer surface then remove the
84 // current surface and add the new surface. 96 // current surface and add the new surface.
85 if (surface != surface_) { 97 if (surface != surface_) {
86 if (surface && surface->HasSurfaceDelegate()) { 98 if (surface && surface->HasSurfaceDelegate()) {
87 DLOG(ERROR) << "Surface has already been assigned a role"; 99 DLOG(ERROR) << "Surface has already been assigned a role";
88 return; 100 return;
89 } 101 }
90 if (surface_) { 102 if (surface_) {
91 surface_->window()->SetTransform(gfx::Transform()); 103 cursor_->RemoveChild(surface_->window());
92 WMHelper::GetInstance()
93 ->GetContainer(ash::kShellWindowId_MouseCursorContainer)
94 ->RemoveChild(surface_->window());
95 surface_->SetSurfaceDelegate(nullptr); 104 surface_->SetSurfaceDelegate(nullptr);
96 surface_->RemoveSurfaceObserver(this); 105 surface_->RemoveSurfaceObserver(this);
97 } 106 }
98 surface_ = surface; 107 surface_ = surface;
99 if (surface_) { 108 if (surface_) {
100 surface_->SetSurfaceDelegate(this); 109 surface_->SetSurfaceDelegate(this);
101 surface_->AddSurfaceObserver(this); 110 surface_->AddSurfaceObserver(this);
102 // Note: Surface window needs to be added to the tree so we can take a 111 cursor_->AddChild(surface_->window());
103 // snapshot. Where in the tree is not important but we might as well use 112 surface_->window()->Show();
104 // the cursor container.
105 WMHelper::GetInstance()
106 ->GetContainer(ash::kShellWindowId_MouseCursorContainer)
107 ->AddChild(surface_->window());
108 } 113 }
109 cursor_changed = true; 114 cursor_changed = true;
110 } 115 }
111 116
112 // Update hotspot. 117 // Update hotspot.
113 if (hotspot != hotspot_) { 118 if (hotspot != hotspot_) {
114 hotspot_ = hotspot; 119 hotspot_ = hotspot;
115 cursor_changed = true; 120 cursor_changed = true;
116 } 121 }
117 122
118 // Early out if cursor did not change. 123 // Early out if cursor did not change.
119 if (!cursor_changed) 124 if (!cursor_changed)
120 return; 125 return;
121 126
122 // If |surface_| is set then asynchronously capture a snapshot of cursor, 127 // If |surface_| is set then asynchronously capture a snapshot of cursor,
123 // otherwise cancel pending capture and immediately set the cursor to "none". 128 // otherwise cancel pending capture and immediately set the cursor to "none".
124 if (surface_) { 129 if (surface_) {
125 CaptureCursor(); 130 CaptureCursor(false);
126 } else { 131 } else {
127 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); 132 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs();
128 cursor_ = ui::kCursorNone; 133 UpdateCursor(ui::kCursorNone, false);
129 UpdateCursor();
130 } 134 }
131 } 135 }
132 136
133 gfx::NativeCursor Pointer::GetCursor() { 137 gfx::NativeCursor Pointer::GetCursor() {
134 return cursor_; 138 if (!focus_)
reveman 2017/03/30 07:47:53 why does all this need to change? I think the prev
Dominik Laskowski 2017/04/05 17:59:25 Keeping track of the latest cursor is unnecessary,
139 return ui::kCursorNull;
reveman 2017/03/30 07:47:53 I think returning null cursor in this case is inco
Dominik Laskowski 2017/04/05 17:59:25 This is equivalent to the old code. Also, the curs
140
141 aura::client::CursorClient* cursor_client =
142 aura::client::GetCursorClient(focus_->window()->GetRootWindow());
143 return cursor_client ? cursor_client->GetCursor() : ui::kCursorNull;
135 } 144 }
136 145
137 //////////////////////////////////////////////////////////////////////////////// 146 ////////////////////////////////////////////////////////////////////////////////
138 // ui::EventHandler overrides: 147 // ui::EventHandler overrides:
139 148
140 void Pointer::OnMouseEvent(ui::MouseEvent* event) { 149 void Pointer::OnMouseEvent(ui::MouseEvent* event) {
141 Surface* target = GetEffectiveTargetForEvent(event); 150 Surface* target = GetEffectiveTargetForEvent(event);
142 151
143 // If target is different than the current pointer focus then we need to 152 // If target is different than the current pointer focus then we need to
144 // generate enter and leave events. 153 // generate enter and leave events.
145 if (target != focus_) { 154 if (target != focus_) {
146 // First generate a leave event if we currently have a target in focus. 155 // First generate a leave event if we currently have a target in focus.
147 if (focus_) { 156 if (focus_) {
148 delegate_->OnPointerLeave(focus_); 157 delegate_->OnPointerLeave(focus_);
149 focus_->RemoveSurfaceObserver(this); 158 focus_->RemoveSurfaceObserver(this);
150 // Require SetCursor() to be called and cursor to be re-defined in 159 // Require SetCursor() to be called and cursor to be re-defined in
151 // response to each OnPointerEnter() call. 160 // response to each OnPointerEnter() call.
152 focus_->UnregisterCursorProvider(this); 161 focus_->UnregisterCursorProvider(this);
153 focus_ = nullptr; 162 focus_ = nullptr;
154 cursor_ = ui::kCursorNull;
155 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); 163 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs();
156 } 164 }
157 // Second generate an enter event if focus moved to a new target. 165 // Second generate an enter event if focus moved to a new target.
158 if (target) { 166 if (target) {
159 delegate_->OnPointerEnter(target, event->location_f(), 167 delegate_->OnPointerEnter(target, event->location_f(),
160 event->button_flags()); 168 event->button_flags());
161 location_ = event->location_f(); 169 location_ = event->location_f();
162 focus_ = target; 170 focus_ = target;
163 focus_->AddSurfaceObserver(this); 171 focus_->AddSurfaceObserver(this);
164 focus_->RegisterCursorProvider(this); 172 focus_->RegisterCursorProvider(this);
173
174 if (surface_)
reveman 2017/03/30 07:47:53 this is incorrect I think. the client needs to pro
Dominik Laskowski 2017/04/05 17:59:25 The client does not do that currently. Is that req
175 CaptureCursor(false);
165 } 176 }
166 delegate_->OnPointerFrame(); 177 delegate_->OnPointerFrame();
167 } 178 }
168 179
169 if (!focus_) 180 if (!focus_)
170 return; 181 return;
171 182
172 if (event->IsMouseEvent() && event->type() != ui::ET_MOUSE_EXITED) { 183 if (event->IsMouseEvent() && event->type() != ui::ET_MOUSE_EXITED) {
173 // Generate motion event if location changed. We need to check location 184 // Generate motion event if location changed. We need to check location
174 // here as mouse movement can generate both "moved" and "entered" events 185 // here as mouse movement can generate both "moved" and "entered" events
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 case ui::ET_MOUSE_MOVED: 230 case ui::ET_MOUSE_MOVED:
220 case ui::ET_MOUSE_DRAGGED: 231 case ui::ET_MOUSE_DRAGGED:
221 case ui::ET_MOUSE_ENTERED: 232 case ui::ET_MOUSE_ENTERED:
222 case ui::ET_MOUSE_EXITED: 233 case ui::ET_MOUSE_EXITED:
223 case ui::ET_MOUSE_CAPTURE_CHANGED: 234 case ui::ET_MOUSE_CAPTURE_CHANGED:
224 break; 235 break;
225 default: 236 default:
226 NOTREACHED(); 237 NOTREACHED();
227 break; 238 break;
228 } 239 }
229
230 UpdateCursorScale();
231 } 240 }
232 241
233 void Pointer::OnScrollEvent(ui::ScrollEvent* event) { 242 void Pointer::OnScrollEvent(ui::ScrollEvent* event) {
234 OnMouseEvent(event); 243 OnMouseEvent(event);
235 } 244 }
236 245
237 //////////////////////////////////////////////////////////////////////////////// 246 ////////////////////////////////////////////////////////////////////////////////
238 // WMHelper::CursorObserver overrides: 247 // WMHelper::CursorObserver overrides:
239 248
240 void Pointer::OnCursorSetChanged(ui::CursorSetType cursor_set) { 249 void Pointer::OnCursorSetChanged(ui::CursorSetType cursor_set) {
241 if (focus_) 250 cursor_scale_ = GetCursorScale(cursor_set);
242 UpdateCursorScale(); 251 if (focus_ && surface_)
252 CaptureCursor(false);
253 }
254
255 void Pointer::OnCursorDisplayChanging(const display::Display& display) {
256 WMHelper* helper = WMHelper::GetInstance();
257 aura::Window* container = helper->GetContainer(
258 display.id(), ash::kShellWindowId_MouseCursorContainer);
259
260 // Reparent the cursor to the root window where the mouse is located.
261 if (container->GetRootWindow() != cursor_->GetRootWindow()) {
262 if (cursor_->parent())
263 cursor_->parent()->RemoveChild(cursor_.get());
264 container->AddChild(cursor_.get());
265 }
266
267 auto info = helper->GetDisplayInfo(display.id());
268 display_scale_ = info.GetEffectiveUIScale() * info.device_scale_factor();
269 device_scale_factor_ = display.device_scale_factor();
270
271 if (focus_ && surface_) {
272 // Capture is asynchronous, so avoid rendering old cursor in the meantime.
reveman 2017/03/30 07:47:53 I don't understand why we need to do all this. Thi
Dominik Laskowski 2017/04/05 17:59:25 This special case is needed when dragging across d
273 cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs();
274 UpdateCursor(ui::kCursorNone, true);
275 // Force the cursor to be updated even if locked.
276 CaptureCursor(true);
277 }
243 } 278 }
244 279
245 //////////////////////////////////////////////////////////////////////////////// 280 ////////////////////////////////////////////////////////////////////////////////
246 // SurfaceDelegate overrides: 281 // SurfaceDelegate overrides:
247 282
248 void Pointer::OnSurfaceCommit() { 283 void Pointer::OnSurfaceCommit() {
249 surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces(); 284 surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces();
250 surface_->CommitSurfaceHierarchy(); 285 surface_->CommitSurfaceHierarchy();
251 286
252 // Capture new cursor to reflect result of commit. 287 // Capture new cursor to reflect result of commit.
253 if (focus_) 288 if (focus_)
254 CaptureCursor(); 289 CaptureCursor(false);
255 } 290 }
256 291
257 bool Pointer::IsSurfaceSynchronized() const { 292 bool Pointer::IsSurfaceSynchronized() const {
258 // A pointer surface is always desynchronized. 293 // A pointer surface is always desynchronized.
259 return false; 294 return false;
260 } 295 }
261 296
262 //////////////////////////////////////////////////////////////////////////////// 297 ////////////////////////////////////////////////////////////////////////////////
263 // SurfaceObserver overrides: 298 // SurfaceObserver overrides:
264 299
(...skipping 11 matching lines...) Expand all
276 311
277 Surface* Pointer::GetEffectiveTargetForEvent(ui::Event* event) const { 312 Surface* Pointer::GetEffectiveTargetForEvent(ui::Event* event) const {
278 Surface* target = 313 Surface* target =
279 Surface::AsSurface(static_cast<aura::Window*>(event->target())); 314 Surface::AsSurface(static_cast<aura::Window*>(event->target()));
280 if (!target) 315 if (!target)
281 return nullptr; 316 return nullptr;
282 317
283 return delegate_->CanAcceptPointerEventsForSurface(target) ? target : nullptr; 318 return delegate_->CanAcceptPointerEventsForSurface(target) ? target : nullptr;
284 } 319 }
285 320
286 void Pointer::UpdateCursorScale() { 321 void Pointer::CaptureCursor(bool force) {
287 DCHECK(focus_);
288
289 display::Screen* screen = display::Screen::GetScreen();
290 WMHelper* helper = WMHelper::GetInstance();
291
292 // Update cursor scale if the effective UI scale has changed.
293 display::Display display = screen->GetDisplayNearestWindow(focus_->window());
294 float scale = helper->GetDisplayInfo(display.id()).GetEffectiveUIScale();
295
296 if (display::Display::HasInternalDisplay()) {
297 float primary_device_scale_factor =
298 screen->GetPrimaryDisplay().device_scale_factor();
299 // The size of the cursor surface is the quotient of its physical size and
300 // the DSF of the primary display. The physical size is proportional to the
301 // DSF of the internal display. For external displays (and the internal
302 // display when secondary to a display with a different DSF), scale the
303 // cursor so its physical size matches with the single display case.
304 if (!display.IsInternal() ||
305 display.device_scale_factor() != primary_device_scale_factor) {
306 scale *= primary_device_scale_factor /
307 helper->GetDisplayInfo(display::Display::InternalDisplayId())
308 .device_scale_factor();
309 }
310 }
311
312 if (helper->GetCursorSet() == ui::CURSOR_SET_LARGE)
313 scale *= kLargeCursorScale;
314
315 if (scale != cursor_scale_) {
316 cursor_scale_ = scale;
317 if (surface_)
318 CaptureCursor();
319 }
320 }
321
322 void Pointer::CaptureCursor() {
323 DCHECK(surface_); 322 DCHECK(surface_);
324 DCHECK(focus_); 323 DCHECK(focus_);
325 324
326 // Set UI scale before submitting capture request. 325 float scale = cursor_scale_ * display_scale_;
327 surface_->window()->layer()->SetTransform( 326 float layer_scale = scale / device_scale_factor_;
328 gfx::GetScaleTransform(gfx::Point(), cursor_scale_));
329 327
330 float primary_device_scale_factor = 328 gfx::Transform transform;
331 display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor(); 329 transform.Scale(layer_scale, layer_scale);
330 surface_->window()->SetTransform(transform);
332 331
333 std::unique_ptr<cc::CopyOutputRequest> request = 332 std::unique_ptr<cc::CopyOutputRequest> request =
334 cc::CopyOutputRequest::CreateBitmapRequest( 333 cc::CopyOutputRequest::CreateBitmapRequest(
335 base::Bind(&Pointer::OnCursorCaptured, 334 base::Bind(&Pointer::OnCursorCaptured,
336 cursor_capture_weak_ptr_factory_.GetWeakPtr(), 335 cursor_capture_weak_ptr_factory_.GetWeakPtr(),
337 gfx::ScaleToFlooredPoint( 336 gfx::ScaleToFlooredPoint(hotspot_, scale), force));
338 hotspot_, 337
339 // |hotspot_| is in surface coordinate space so apply
340 // both device scale and UI scale.
341 cursor_scale_ * primary_device_scale_factor)));
342 request->set_source(cursor_capture_source_id_); 338 request->set_source(cursor_capture_source_id_);
343 surface_->window()->layer()->RequestCopyOfOutput(std::move(request)); 339 cursor_->layer()->RequestCopyOfOutput(std::move(request));
340
341 // Prevent subsequent requests in the same frame from aborting this capture.
reveman 2017/03/30 07:47:53 why is this needed?
Dominik Laskowski 2017/04/05 17:59:25 If the client happens to commit or call wl_pointer
342 if (force)
343 cursor_capture_source_id_ = base::UnguessableToken::Create();
344 } 344 }
345 345
346 void Pointer::OnCursorCaptured(const gfx::Point& hotspot, 346 void Pointer::OnCursorCaptured(gfx::Point hotspot,
347 bool force,
347 std::unique_ptr<cc::CopyOutputResult> result) { 348 std::unique_ptr<cc::CopyOutputResult> result) {
348 if (!focus_) 349 if (!focus_)
349 return; 350 return;
350 351
351 cursor_ = ui::kCursorNone; 352 gfx::NativeCursor cursor = ui::kCursorNull;
352 if (!result->IsEmpty()) { 353 if (!result->IsEmpty()) {
353 DCHECK(result->HasBitmap()); 354 DCHECK(result->HasBitmap());
354 std::unique_ptr<SkBitmap> bitmap = result->TakeBitmap(); 355 std::unique_ptr<SkBitmap> bitmap = result->TakeBitmap();
355 356
356 ui::PlatformCursor platform_cursor; 357 ui::PlatformCursor platform_cursor;
357 #if defined(USE_OZONE) 358 #if defined(USE_OZONE)
358 // TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers 359 // TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers
359 // and use that here instead of the current bitmap API. crbug.com/686600 360 // and use that here instead of the current bitmap API. crbug.com/686600
360 platform_cursor = ui::CursorFactoryOzone::GetInstance()->CreateImageCursor( 361 platform_cursor = ui::CursorFactoryOzone::GetInstance()->CreateImageCursor(
361 *bitmap.get(), hotspot); 362 *bitmap.get(), hotspot);
362 #elif defined(USE_X11) 363 #elif defined(USE_X11)
363 XcursorImage* image = ui::SkBitmapToXcursorImage(bitmap.get(), hotspot); 364 XcursorImage* image = ui::SkBitmapToXcursorImage(bitmap.get(), hotspot);
364 platform_cursor = ui::CreateReffedCustomXCursor(image); 365 platform_cursor = ui::CreateReffedCustomXCursor(image);
365 #endif 366 #endif
366 cursor_ = ui::kCursorCustom; 367 cursor = ui::kCursorCustom;
367 cursor_.SetPlatformCursor(platform_cursor); 368 cursor.SetPlatformCursor(platform_cursor);
368 #if defined(USE_OZONE) 369 #if defined(USE_OZONE)
369 ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor); 370 ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor);
370 #elif defined(USE_X11) 371 #elif defined(USE_X11)
371 ui::UnrefCustomXCursor(platform_cursor); 372 ui::UnrefCustomXCursor(platform_cursor);
372 #endif 373 #endif
373 } 374 }
374 375
375 UpdateCursor(); 376 UpdateCursor(cursor, force);
376 } 377 }
377 378
378 void Pointer::UpdateCursor() { 379 void Pointer::UpdateCursor(gfx::NativeCursor cursor, bool force) {
379 DCHECK(focus_); 380 DCHECK(focus_);
380 381
381 aura::client::CursorClient* cursor_client = 382 aura::client::CursorClient* cursor_client =
382 aura::client::GetCursorClient(focus_->window()->GetRootWindow()); 383 aura::client::GetCursorClient(focus_->window()->GetRootWindow());
383 if (cursor_client) 384 if (!cursor_client)
384 cursor_client->SetCursor(cursor_); 385 return;
386
387 cursor_client->SetCursor(cursor);
388
389 if (force && cursor_client->IsCursorLocked())
reveman 2017/03/30 07:47:53 what's the situation where this is currently causi
Dominik Laskowski 2017/04/05 17:59:25 |force| being true implies that the cursor is lock
390 WMHelper::GetInstance()->SetCursor(cursor);
385 } 391 }
386 392
387 } // namespace exo 393 } // namespace exo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698