Chromium Code Reviews| 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 "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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |