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

Unified Diff: components/exo/pointer.cc

Issue 2780623002: exo: Fix multi-display hardware cursor (Closed)
Patch Set: Fix style error 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/exo/pointer.h ('k') | components/exo/shell_surface.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/exo/pointer.cc
diff --git a/components/exo/pointer.cc b/components/exo/pointer.cc
index 273a74208214f2b2ab82ffb7c1ed1a3cc69cc6cb..7f1d352bd13f2bbd033db9fde2afaf30d1d60eb6 100644
--- a/components/exo/pointer.cc
+++ b/components/exo/pointer.cc
@@ -16,6 +16,7 @@
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
+#include "ui/base/cursor/cursor_util.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/manager/managed_display_info.h"
#include "ui/display/screen.h"
@@ -34,7 +35,16 @@
namespace exo {
namespace {
+// TODO(oshima): Some accessibility features, including large cursors, disable
+// hardware cursors. Ash does not support compositing for custom cursors, so it
+// replaces them with the default cursor. As a result, this scale has no effect
+// for now. See crbug.com/708378.
const float kLargeCursorScale = 2.8f;
+
+// Scale at which cursor snapshot is captured. The resulting bitmap is scaled on
+// displays whose DSF does not match this scale.
+const float kCursorCaptureScale = 2.0f;
+
const double kLocatedEventEpsilonSquared = 1.0 / (2000.0 * 2000.0);
// Synthesized events typically lack floating point precision so to avoid
@@ -113,17 +123,14 @@ void Pointer::SetCursor(Surface* surface, const gfx::Point& hotspot) {
// snapshot. Where in the tree is not important but we might as well use
// the cursor container.
WMHelper::GetInstance()
- ->GetContainer(ash::kShellWindowId_MouseCursorContainer)
+ ->GetPrimaryDisplayContainer(ash::kShellWindowId_MouseCursorContainer)
->AddChild(surface_->window());
}
cursor_changed = true;
}
- // Update hotspot.
- if (hotspot != hotspot_) {
- hotspot_ = hotspot;
+ if (hotspot != hotspot_)
cursor_changed = true;
- }
// Early out if cursor did not change.
if (!cursor_changed)
@@ -132,10 +139,10 @@ void Pointer::SetCursor(Surface* surface, const gfx::Point& hotspot) {
// If |surface_| is set then asynchronously capture a snapshot of cursor,
// otherwise cancel pending capture and immediately set the cursor to "none".
if (surface_) {
- CaptureCursor();
+ CaptureCursor(hotspot);
} else {
+ cursor_bitmap_.reset();
cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs();
- cursor_ = ui::CursorType::kNone;
UpdateCursor();
}
}
@@ -251,7 +258,6 @@ void Pointer::OnMouseEvent(ui::MouseEvent* event) {
}
last_event_type_ = event->type();
- UpdateCursorScale();
}
void Pointer::OnScrollEvent(ui::ScrollEvent* event) {
@@ -263,7 +269,12 @@ void Pointer::OnScrollEvent(ui::ScrollEvent* event) {
void Pointer::OnCursorSetChanged(ui::CursorSetType cursor_set) {
if (focus_)
- UpdateCursorScale();
+ UpdateCursor();
+}
+
+void Pointer::OnCursorDisplayChanged(const display::Display& display) {
+ if (focus_)
+ UpdateCursor();
}
////////////////////////////////////////////////////////////////////////////////
@@ -275,7 +286,7 @@ void Pointer::OnSurfaceCommit() {
// Capture new cursor to reflect result of commit.
if (focus_)
- CaptureCursor();
+ CaptureCursor(hotspot_);
}
bool Pointer::IsSurfaceSynchronized() const {
@@ -307,62 +318,25 @@ Surface* Pointer::GetEffectiveTargetForEvent(ui::Event* event) const {
return delegate_->CanAcceptPointerEventsForSurface(target) ? target : nullptr;
}
-void Pointer::UpdateCursorScale() {
- DCHECK(focus_);
-
- display::Screen* screen = display::Screen::GetScreen();
- WMHelper* helper = WMHelper::GetInstance();
-
- // Update cursor scale if the effective UI scale has changed.
- display::Display display = screen->GetDisplayNearestWindow(focus_->window());
- float scale = helper->GetDisplayInfo(display.id()).GetEffectiveUIScale();
-
- if (display::Display::HasInternalDisplay()) {
- float primary_device_scale_factor =
- screen->GetPrimaryDisplay().device_scale_factor();
- // The size of the cursor surface is the quotient of its physical size and
- // the DSF of the primary display. The physical size is proportional to the
- // DSF of the internal display. For external displays (and the internal
- // display when secondary to a display with a different DSF), scale the
- // cursor so its physical size matches with the single display case.
- if (!display.IsInternal() ||
- display.device_scale_factor() != primary_device_scale_factor) {
- scale *= primary_device_scale_factor /
- helper->GetDisplayInfo(display::Display::InternalDisplayId())
- .device_scale_factor();
- }
- }
-
- if (helper->GetCursorSet() == ui::CURSOR_SET_LARGE)
- scale *= kLargeCursorScale;
-
- if (scale != cursor_scale_) {
- cursor_scale_ = scale;
- if (surface_)
- CaptureCursor();
- }
-}
-
-void Pointer::CaptureCursor() {
+void Pointer::CaptureCursor(const gfx::Point& hotspot) {
DCHECK(surface_);
DCHECK(focus_);
- // Set UI scale before submitting capture request.
- surface_->window()->layer()->SetTransform(
- gfx::GetScaleTransform(gfx::Point(), cursor_scale_));
-
- float primary_device_scale_factor =
- display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
+ // Surface size is in DIPs, while layer size is in pseudo-DIP units that
+ // depend on the DSF of the display mode. Scale the layer to capture the
+ // surface at a constant pixel size, regardless of the primary display's
+ // UI scale and display mode DSF.
+ display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
+ auto* helper = WMHelper::GetInstance();
+ float scale = helper->GetDisplayInfo(display.id()).GetEffectiveUIScale() *
+ kCursorCaptureScale / display.device_scale_factor();
+ surface_->window()->SetTransform(gfx::GetScaleTransform(gfx::Point(), scale));
std::unique_ptr<cc::CopyOutputRequest> request =
cc::CopyOutputRequest::CreateBitmapRequest(
base::Bind(&Pointer::OnCursorCaptured,
- cursor_capture_weak_ptr_factory_.GetWeakPtr(),
- gfx::ScaleToFlooredPoint(
- hotspot_,
- // |hotspot_| is in surface coordinate space so apply
- // both device scale and UI scale.
- cursor_scale_ * primary_device_scale_factor)));
+ cursor_capture_weak_ptr_factory_.GetWeakPtr(), hotspot));
+
request->set_source(cursor_capture_source_id_);
surface_->window()->layer()->RequestCopyOfOutput(std::move(request));
}
@@ -372,19 +346,46 @@ void Pointer::OnCursorCaptured(const gfx::Point& hotspot,
if (!focus_)
return;
- cursor_ = ui::CursorType::kNone;
- if (!result->IsEmpty()) {
+ if (result->IsEmpty()) {
+ cursor_bitmap_.reset();
+ } else {
DCHECK(result->HasBitmap());
- std::unique_ptr<SkBitmap> bitmap = result->TakeBitmap();
+ cursor_bitmap_ = *result->TakeBitmap();
+ hotspot_ = hotspot;
+ }
+
+ UpdateCursor();
+}
+
+void Pointer::UpdateCursor() {
+ DCHECK(focus_);
+
+ if (cursor_bitmap_.drawsNothing()) {
+ cursor_ = ui::CursorType::kNone;
+ } else {
+ SkBitmap bitmap = cursor_bitmap_;
+ gfx::Point hotspot =
+ gfx::ScaleToFlooredPoint(hotspot_, kCursorCaptureScale);
+
+ auto* helper = WMHelper::GetInstance();
+ const display::Display& display = helper->GetCursorDisplay();
+ float scale = helper->GetDisplayInfo(display.id()).device_scale_factor() /
+ kCursorCaptureScale;
+
+ if (helper->GetCursorSet() == ui::CURSOR_SET_LARGE)
+ scale *= kLargeCursorScale;
+
+ ui::ScaleAndRotateCursorBitmapAndHotpoint(scale, display.rotation(),
+ &bitmap, &hotspot);
ui::PlatformCursor platform_cursor;
#if defined(USE_OZONE)
// TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers
// and use that here instead of the current bitmap API. crbug.com/686600
platform_cursor = ui::CursorFactoryOzone::GetInstance()->CreateImageCursor(
- *bitmap.get(), hotspot, cursor_scale_);
+ bitmap, hotspot, 0);
#elif defined(USE_X11)
- XcursorImage* image = ui::SkBitmapToXcursorImage(bitmap.get(), hotspot);
+ XcursorImage* image = ui::SkBitmapToXcursorImage(&bitmap, hotspot);
platform_cursor = ui::CreateReffedCustomXCursor(image);
#endif
cursor_ = ui::CursorType::kCustom;
@@ -396,12 +397,6 @@ void Pointer::OnCursorCaptured(const gfx::Point& hotspot,
#endif
}
- UpdateCursor();
-}
-
-void Pointer::UpdateCursor() {
- DCHECK(focus_);
-
aura::Window* root_window = focus_->window()->GetRootWindow();
if (!root_window)
return;
« no previous file with comments | « components/exo/pointer.h ('k') | components/exo/shell_surface.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698