Commit 726a07cc authored by James Cook's avatar James Cook Committed by Commit Bot

lacros: Use Wayland server-side cursors for non-bitmap cursors

Use the zcr_cursor_shapes_v1 Wayland protocol extension to allow the
exo server to set the cursor. Use this for standard cursors (pointer,
hand) and animated cursors (progress, wait). Bitmap cursors continue
to use the existing code path.

Introduce a test API for WaylandConnection so we can mock out the
WaylandZcrCursorShapes object.

In addition to the automated tests, I tested manually on a Pixelbook
(eve). High DPI cursors are sharp. Accessibility cursors work fine,
including large cursor and cursor coloring. The cursor size is
correct for multi-monitor window drags from high DPI to low DPI
monitors and vice versa. All CSS cursors listed on the MDN CSS
cursors page look correct:
https://developer.mozilla.org/en-US/docs/Web/CSS/cursor

Bug: 1143790
Test: added to ui_base_unittests and ozone_unittests

Change-Id: Ic46fc083a0ec662edf40b370572e907a2877c59a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2516972
Auto-Submit: James Cook <jamescook@chromium.org>
Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Reviewed-by: default avatarHenrique Ferreiro <hferreiro@igalia.com>
Reviewed-by: default avatarMaksim Sisov (GMT+2) <msisov@igalia.com>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Reviewed-by: default avatarAntonio Gomes <tonikitoo@igalia.com>
Commit-Queue: James Cook <jamescook@chromium.org>
Cr-Commit-Position: refs/heads/master@{#825133}
parent 81c50f4f
...@@ -153,7 +153,7 @@ void CaptureWindowObserver::UpdateMouseCursor() { ...@@ -153,7 +153,7 @@ void CaptureWindowObserver::UpdateMouseCursor() {
device_scale_factor, display.panel_rotation(), &bitmap, &hotspot); device_scale_factor, display.panel_rotation(), &bitmap, &hotspot);
auto* cursor_factory = ui::CursorFactory::GetInstance(); auto* cursor_factory = ui::CursorFactory::GetInstance();
ui::PlatformCursor platform_cursor = ui::PlatformCursor platform_cursor =
cursor_factory->CreateImageCursor(bitmap, hotspot); cursor_factory->CreateImageCursor(cursor.type(), bitmap, hotspot);
cursor.SetPlatformCursor(platform_cursor); cursor.SetPlatformCursor(platform_cursor);
cursor.set_custom_bitmap(bitmap); cursor.set_custom_bitmap(bitmap);
cursor.set_custom_hotspot(hotspot); cursor.set_custom_hotspot(hotspot);
......
...@@ -767,8 +767,8 @@ void Pointer::UpdateCursor() { ...@@ -767,8 +767,8 @@ void Pointer::UpdateCursor() {
// TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers // TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers
// and use that here instead of the current bitmap API. // and use that here instead of the current bitmap API.
// https://crbug.com/686600 // https://crbug.com/686600
platform_cursor = platform_cursor = ui::CursorFactory::GetInstance()->CreateImageCursor(
ui::CursorFactory::GetInstance()->CreateImageCursor(bitmap, hotspot); cursor_.type(), bitmap, hotspot);
cursor_.SetPlatformCursor(platform_cursor); cursor_.SetPlatformCursor(platform_cursor);
cursor_.set_custom_bitmap(bitmap); cursor_.set_custom_bitmap(bitmap);
cursor_.set_custom_hotspot(hotspot); cursor_.set_custom_hotspot(hotspot);
......
...@@ -19,7 +19,7 @@ ui::PlatformCursor WebCursor::GetPlatformCursor(const ui::Cursor& cursor) { ...@@ -19,7 +19,7 @@ ui::PlatformCursor WebCursor::GetPlatformCursor(const ui::Cursor& cursor) {
if (!platform_cursor_) { if (!platform_cursor_) {
platform_cursor_ = ui::CursorFactory::GetInstance()->CreateImageCursor( platform_cursor_ = ui::CursorFactory::GetInstance()->CreateImageCursor(
cursor.custom_bitmap(), cursor.custom_hotspot()); cursor.type(), cursor.custom_bitmap(), cursor.custom_hotspot());
} }
return platform_cursor_; return platform_cursor_;
......
...@@ -90,6 +90,7 @@ if (use_aura) { ...@@ -90,6 +90,7 @@ if (use_aura) {
"//skia", "//skia",
"//ui/gfx/geometry", "//ui/gfx/geometry",
] ]
deps += [ "//build:chromeos_buildflags" ]
} }
if (use_x11 || use_ozone) { if (use_x11 || use_ozone) {
...@@ -144,6 +145,7 @@ source_set("unittests") { ...@@ -144,6 +145,7 @@ source_set("unittests") {
deps += [ deps += [
":cursor", ":cursor",
"//base", "//base",
"//build:chromeos_buildflags",
] ]
} }
} }
...@@ -20,6 +20,8 @@ namespace ui { ...@@ -20,6 +20,8 @@ namespace ui {
#if defined(OS_WIN) #if defined(OS_WIN)
typedef ::HCURSOR PlatformCursor; typedef ::HCURSOR PlatformCursor;
#else #else
// NOTE: On Ozone platforms, the type is chosen at runtime, and is either
// X11Cursor* or BitmapCursorOzone*.
typedef void* PlatformCursor; typedef void* PlatformCursor;
#endif #endif
......
...@@ -39,13 +39,15 @@ base::Optional<PlatformCursor> CursorFactory::GetDefaultCursor( ...@@ -39,13 +39,15 @@ base::Optional<PlatformCursor> CursorFactory::GetDefaultCursor(
return base::nullopt; return base::nullopt;
} }
PlatformCursor CursorFactory::CreateImageCursor(const SkBitmap& bitmap, PlatformCursor CursorFactory::CreateImageCursor(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) { const gfx::Point& hotspot) {
NOTIMPLEMENTED(); NOTIMPLEMENTED();
return 0; return 0;
} }
PlatformCursor CursorFactory::CreateAnimatedCursor( PlatformCursor CursorFactory::CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps, const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot, const gfx::Point& hotspot,
int frame_delay_ms) { int frame_delay_ms) {
......
...@@ -36,10 +36,12 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactory { ...@@ -36,10 +36,12 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactory {
virtual base::Optional<PlatformCursor> GetDefaultCursor( virtual base::Optional<PlatformCursor> GetDefaultCursor(
mojom::CursorType type); mojom::CursorType type);
// Return a image cursor from the specified image & hotspot. Image cursors // Return an image cursor for the specified |type| with a |bitmap| and
// are referenced counted and have an initial refcount of 1. Therefore, each // |hotspot|. Image cursors are referenced counted and have an initial
// CreateImageCursor call must be matched with a call to UnrefImageCursor. // refcount of 1. Therefore, each CreateImageCursor call must be matched with
virtual PlatformCursor CreateImageCursor(const SkBitmap& bitmap, // a call to UnrefImageCursor.
virtual PlatformCursor CreateImageCursor(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot); const gfx::Point& hotspot);
// Return a animated cursor from the specified image & hotspot. Animated // Return a animated cursor from the specified image & hotspot. Animated
...@@ -48,6 +50,7 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactory { ...@@ -48,6 +50,7 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactory {
// UnrefImageCursor. // UnrefImageCursor.
// |frame_delay_ms| is the delay between frames in millisecond. // |frame_delay_ms| is the delay between frames in millisecond.
virtual PlatformCursor CreateAnimatedCursor( virtual PlatformCursor CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps, const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot, const gfx::Point& hotspot,
int frame_delay_ms); int frame_delay_ms);
......
...@@ -57,13 +57,13 @@ void CursorLoaderOzone::LoadImageCursor(mojom::CursorType type, ...@@ -57,13 +57,13 @@ void CursorLoaderOzone::LoadImageCursor(mojom::CursorType type,
if (base::ranges::count(kAnimatedCursorTypes, type) == 0) { if (base::ranges::count(kAnimatedCursorTypes, type) == 0) {
SkBitmap bitmap; SkBitmap bitmap;
GetImageCursorBitmap(resource_id, scale(), rotation(), &hotspot, &bitmap); GetImageCursorBitmap(resource_id, scale(), rotation(), &hotspot, &bitmap);
image_cursors_[type] = factory_->CreateImageCursor(bitmap, hotspot); image_cursors_[type] = factory_->CreateImageCursor(type, bitmap, hotspot);
} else { } else {
std::vector<SkBitmap> bitmaps; std::vector<SkBitmap> bitmaps;
GetAnimatedCursorBitmaps(resource_id, scale(), rotation(), &hotspot, GetAnimatedCursorBitmaps(resource_id, scale(), rotation(), &hotspot,
&bitmaps); &bitmaps);
image_cursors_[type] = factory_->CreateAnimatedCursor( image_cursors_[type] = factory_->CreateAnimatedCursor(
bitmaps, hotspot, kAnimatedCursorFrameDelayMs); type, bitmaps, hotspot, kAnimatedCursorFrameDelayMs);
} }
} }
......
...@@ -46,7 +46,7 @@ TEST(CursorLoaderTest, InvisibleCursorOnX11) { ...@@ -46,7 +46,7 @@ TEST(CursorLoaderTest, InvisibleCursorOnX11) {
// Building an image cursor with an invalid SkBitmap should return the // Building an image cursor with an invalid SkBitmap should return the
// invisible cursor in X11. // invisible cursor in X11.
auto* invisible_cursor = auto* invisible_cursor =
cursor_factory.CreateImageCursor(SkBitmap(), gfx::Point()); cursor_factory.CreateImageCursor({}, SkBitmap(), gfx::Point());
EXPECT_EQ(LoadInvisibleCursor(), invisible_cursor); EXPECT_EQ(LoadInvisibleCursor(), invisible_cursor);
// Release our refcount on the cursor // Release our refcount on the cursor
......
...@@ -7,11 +7,78 @@ ...@@ -7,11 +7,78 @@
#include <algorithm> #include <algorithm>
#include "base/check_op.h" #include "base/check_op.h"
#include "base/notreached.h"
#include "build/chromeos_buildflags.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
namespace ui { namespace ui {
namespace { namespace {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
// Returns true if ozone should use the default cursor for |type|, instead of
// loading and storing bitmaps for it. Used on Lacros to skip client-side bitmap
// loading for server-side cursors.
bool UseDefaultCursorForType(mojom::CursorType type) {
using mojom::CursorType;
switch (type) {
case CursorType::kNull:
case CursorType::kPointer:
case CursorType::kCross:
case CursorType::kHand:
case CursorType::kIBeam:
case CursorType::kWait:
case CursorType::kHelp:
case CursorType::kEastResize:
case CursorType::kNorthResize:
case CursorType::kNorthEastResize:
case CursorType::kNorthWestResize:
case CursorType::kSouthResize:
case CursorType::kSouthEastResize:
case CursorType::kSouthWestResize:
case CursorType::kWestResize:
case CursorType::kNorthSouthResize:
case CursorType::kEastWestResize:
case CursorType::kNorthEastSouthWestResize:
case CursorType::kNorthWestSouthEastResize:
case CursorType::kColumnResize:
case CursorType::kRowResize:
case CursorType::kMiddlePanning:
case CursorType::kEastPanning:
case CursorType::kNorthPanning:
case CursorType::kNorthEastPanning:
case CursorType::kNorthWestPanning:
case CursorType::kSouthPanning:
case CursorType::kSouthEastPanning:
case CursorType::kSouthWestPanning:
case CursorType::kWestPanning:
case CursorType::kMove:
case CursorType::kVerticalText:
case CursorType::kCell:
case CursorType::kContextMenu:
case CursorType::kAlias:
case CursorType::kProgress:
case CursorType::kNoDrop:
case CursorType::kCopy:
case CursorType::kNotAllowed:
case CursorType::kZoomIn:
case CursorType::kZoomOut:
case CursorType::kGrab:
case CursorType::kGrabbing:
case CursorType::kDndNone:
case CursorType::kDndMove:
case CursorType::kDndCopy:
case CursorType::kDndLink:
return true;
case CursorType::kNone:
case CursorType::kMiddlePanningVertical:
case CursorType::kMiddlePanningHorizontal:
case CursorType::kCustom:
return false;
}
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
BitmapCursorOzone* ToBitmapCursorOzone(PlatformCursor cursor) { BitmapCursorOzone* ToBitmapCursorOzone(PlatformCursor cursor) {
return static_cast<BitmapCursorOzone*>(cursor); return static_cast<BitmapCursorOzone*>(cursor);
} }
...@@ -22,17 +89,25 @@ PlatformCursor ToPlatformCursor(BitmapCursorOzone* cursor) { ...@@ -22,17 +89,25 @@ PlatformCursor ToPlatformCursor(BitmapCursorOzone* cursor) {
} // namespace } // namespace
BitmapCursorOzone::BitmapCursorOzone(const SkBitmap& bitmap, BitmapCursorOzone::BitmapCursorOzone(mojom::CursorType type)
: type_(type), frame_delay_ms_(0) {}
BitmapCursorOzone::BitmapCursorOzone(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) const gfx::Point& hotspot)
: hotspot_(hotspot), frame_delay_ms_(0) { : type_(type), hotspot_(hotspot), frame_delay_ms_(0) {
if (!bitmap.isNull()) if (!bitmap.isNull())
bitmaps_.push_back(bitmap); bitmaps_.push_back(bitmap);
} }
BitmapCursorOzone::BitmapCursorOzone(const std::vector<SkBitmap>& bitmaps, BitmapCursorOzone::BitmapCursorOzone(mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot, const gfx::Point& hotspot,
int frame_delay_ms) int frame_delay_ms)
: bitmaps_(bitmaps), hotspot_(hotspot), frame_delay_ms_(frame_delay_ms) { : type_(type),
bitmaps_(bitmaps),
hotspot_(hotspot),
frame_delay_ms_(frame_delay_ms) {
DCHECK_LT(0U, bitmaps.size()); DCHECK_LT(0U, bitmaps.size());
DCHECK_LE(0, frame_delay_ms); DCHECK_LE(0, frame_delay_ms);
// No null bitmap should be in the list. Blank cursors should just be an empty // No null bitmap should be in the list. Blank cursors should just be an empty
...@@ -42,8 +117,7 @@ BitmapCursorOzone::BitmapCursorOzone(const std::vector<SkBitmap>& bitmaps, ...@@ -42,8 +117,7 @@ BitmapCursorOzone::BitmapCursorOzone(const std::vector<SkBitmap>& bitmaps,
bitmaps_.end()); bitmaps_.end());
} }
BitmapCursorOzone::~BitmapCursorOzone() { BitmapCursorOzone::~BitmapCursorOzone() = default;
}
const gfx::Point& BitmapCursorOzone::hotspot() { const gfx::Point& BitmapCursorOzone::hotspot() {
return hotspot_; return hotspot_;
...@@ -75,24 +149,35 @@ base::Optional<PlatformCursor> BitmapCursorFactoryOzone::GetDefaultCursor( ...@@ -75,24 +149,35 @@ base::Optional<PlatformCursor> BitmapCursorFactoryOzone::GetDefaultCursor(
mojom::CursorType type) { mojom::CursorType type) {
if (type == mojom::CursorType::kNone) if (type == mojom::CursorType::kNone)
return nullptr; // nullptr is used for the hidden cursor. return nullptr; // nullptr is used for the hidden cursor.
#if BUILDFLAG(IS_CHROMEOS_LACROS)
if (UseDefaultCursorForType(type)) {
// Lacros uses server-side cursors for most types. These cursors don't need
// to load bitmap images on the client.
BitmapCursorOzone* cursor = new BitmapCursorOzone(type);
cursor->AddRef(); // Balanced by UnrefImageCursor.
return ToPlatformCursor(cursor);
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
return base::nullopt; return base::nullopt;
} }
PlatformCursor BitmapCursorFactoryOzone::CreateImageCursor( PlatformCursor BitmapCursorFactoryOzone::CreateImageCursor(
mojom::CursorType type,
const SkBitmap& bitmap, const SkBitmap& bitmap,
const gfx::Point& hotspot) { const gfx::Point& hotspot) {
BitmapCursorOzone* cursor = new BitmapCursorOzone(bitmap, hotspot); BitmapCursorOzone* cursor = new BitmapCursorOzone(type, bitmap, hotspot);
cursor->AddRef(); // Balanced by UnrefImageCursor. cursor->AddRef(); // Balanced by UnrefImageCursor.
return ToPlatformCursor(cursor); return ToPlatformCursor(cursor);
} }
PlatformCursor BitmapCursorFactoryOzone::CreateAnimatedCursor( PlatformCursor BitmapCursorFactoryOzone::CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps, const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot, const gfx::Point& hotspot,
int frame_delay_ms) { int frame_delay_ms) {
DCHECK_LT(0U, bitmaps.size()); DCHECK_LT(0U, bitmaps.size());
BitmapCursorOzone* cursor = BitmapCursorOzone* cursor =
new BitmapCursorOzone(bitmaps, hotspot, frame_delay_ms); new BitmapCursorOzone(type, bitmaps, hotspot, frame_delay_ms);
cursor->AddRef(); // Balanced by UnrefImageCursor. cursor->AddRef(); // Balanced by UnrefImageCursor.
return ToPlatformCursor(cursor); return ToPlatformCursor(cursor);
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/cursor_factory.h" #include "ui/base/cursor/cursor_factory.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
#include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point.h"
namespace ui { namespace ui {
...@@ -21,11 +22,22 @@ namespace ui { ...@@ -21,11 +22,22 @@ namespace ui {
class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorOzone class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorOzone
: public base::RefCounted<BitmapCursorOzone> { : public base::RefCounted<BitmapCursorOzone> {
public: public:
BitmapCursorOzone(const SkBitmap& bitmap, const gfx::Point& hotspot); // Creates a cursor that doesn't need backing bitmaps (for example, a
BitmapCursorOzone(const std::vector<SkBitmap>& bitmaps, // server-side cursor for Lacros).
explicit BitmapCursorOzone(mojom::CursorType type);
// Creates a cursor with a single backing bitmap.
BitmapCursorOzone(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot);
// Creates a cursor with multiple bitmaps for animation.
BitmapCursorOzone(mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot, const gfx::Point& hotspot,
int frame_delay_ms); int frame_delay_ms);
mojom::CursorType type() const { return type_; }
const gfx::Point& hotspot(); const gfx::Point& hotspot();
const SkBitmap& bitmap(); const SkBitmap& bitmap();
...@@ -37,6 +49,7 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorOzone ...@@ -37,6 +49,7 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorOzone
friend class base::RefCounted<BitmapCursorOzone>; friend class base::RefCounted<BitmapCursorOzone>;
~BitmapCursorOzone(); ~BitmapCursorOzone();
const mojom::CursorType type_;
std::vector<SkBitmap> bitmaps_; std::vector<SkBitmap> bitmaps_;
gfx::Point hotspot_; gfx::Point hotspot_;
int frame_delay_ms_; int frame_delay_ms_;
...@@ -64,9 +77,11 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorFactoryOzone ...@@ -64,9 +77,11 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorFactoryOzone
// CursorFactoryOzone: // CursorFactoryOzone:
base::Optional<PlatformCursor> GetDefaultCursor( base::Optional<PlatformCursor> GetDefaultCursor(
mojom::CursorType type) override; mojom::CursorType type) override;
PlatformCursor CreateImageCursor(const SkBitmap& bitmap, PlatformCursor CreateImageCursor(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) override; const gfx::Point& hotspot) override;
PlatformCursor CreateAnimatedCursor(const std::vector<SkBitmap>& bitmaps, PlatformCursor CreateAnimatedCursor(mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot, const gfx::Point& hotspot,
int frame_delay_ms) override; int frame_delay_ms) override;
void RefImageCursor(PlatformCursor cursor) override; void RefImageCursor(PlatformCursor cursor) override;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h" #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "base/optional.h" #include "base/optional.h"
#include "build/chromeos_buildflags.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
...@@ -21,4 +22,35 @@ TEST(BitmapCursorFactoryOzoneTest, InvisibleCursor) { ...@@ -21,4 +22,35 @@ TEST(BitmapCursorFactoryOzoneTest, InvisibleCursor) {
EXPECT_EQ(cursor, nullptr); EXPECT_EQ(cursor, nullptr);
} }
#if BUILDFLAG(IS_CHROMEOS_LACROS)
TEST(BitmapCursorFactoryOzoneTest, LacrosUsesDefaultCursorsForCommonTypes) {
BitmapCursorFactoryOzone factory;
// Verify some common cursor types.
base::Optional<PlatformCursor> cursor =
factory.GetDefaultCursor(mojom::CursorType::kPointer);
ASSERT_TRUE(cursor.has_value());
EXPECT_NE(cursor, nullptr);
factory.UnrefImageCursor(cursor.value());
cursor = factory.GetDefaultCursor(mojom::CursorType::kHand);
ASSERT_TRUE(cursor.has_value());
EXPECT_NE(cursor, nullptr);
factory.UnrefImageCursor(cursor.value());
cursor = factory.GetDefaultCursor(mojom::CursorType::kIBeam);
ASSERT_TRUE(cursor.has_value());
EXPECT_NE(cursor, nullptr);
factory.UnrefImageCursor(cursor.value());
}
TEST(BitmapCursorFactoryOzoneTest, LacrosCustomCursor) {
BitmapCursorFactoryOzone factory;
base::Optional<PlatformCursor> cursor =
factory.GetDefaultCursor(mojom::CursorType::kCustom);
// Custom cursors don't have a default platform cursor.
EXPECT_FALSE(cursor.has_value());
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
} // namespace ui } // namespace ui
...@@ -159,7 +159,8 @@ base::Optional<PlatformCursor> X11CursorFactory::GetDefaultCursor( ...@@ -159,7 +159,8 @@ base::Optional<PlatformCursor> X11CursorFactory::GetDefaultCursor(
return ToPlatformCursor(cursor.get()); return ToPlatformCursor(cursor.get());
} }
PlatformCursor X11CursorFactory::CreateImageCursor(const SkBitmap& bitmap, PlatformCursor X11CursorFactory::CreateImageCursor(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) { const gfx::Point& hotspot) {
// There is a problem with custom cursors that have no custom data. The // There is a problem with custom cursors that have no custom data. The
// resulting SkBitmap is empty and X crashes when creating a zero size cursor // resulting SkBitmap is empty and X crashes when creating a zero size cursor
...@@ -180,6 +181,7 @@ PlatformCursor X11CursorFactory::CreateImageCursor(const SkBitmap& bitmap, ...@@ -180,6 +181,7 @@ PlatformCursor X11CursorFactory::CreateImageCursor(const SkBitmap& bitmap,
} }
PlatformCursor X11CursorFactory::CreateAnimatedCursor( PlatformCursor X11CursorFactory::CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps, const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot, const gfx::Point& hotspot,
int frame_delay_ms) { int frame_delay_ms) {
......
...@@ -34,9 +34,11 @@ class COMPONENT_EXPORT(UI_BASE_X) X11CursorFactory ...@@ -34,9 +34,11 @@ class COMPONENT_EXPORT(UI_BASE_X) X11CursorFactory
// CursorFactoryOzone: // CursorFactoryOzone:
base::Optional<PlatformCursor> GetDefaultCursor( base::Optional<PlatformCursor> GetDefaultCursor(
mojom::CursorType type) override; mojom::CursorType type) override;
PlatformCursor CreateImageCursor(const SkBitmap& bitmap, PlatformCursor CreateImageCursor(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) override; const gfx::Point& hotspot) override;
PlatformCursor CreateAnimatedCursor(const std::vector<SkBitmap>& bitmaps, PlatformCursor CreateAnimatedCursor(mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot, const gfx::Point& hotspot,
int frame_delay_ms) override; int frame_delay_ms) override;
void RefImageCursor(PlatformCursor cursor) override; void RefImageCursor(PlatformCursor cursor) override;
......
...@@ -19,7 +19,7 @@ TEST(X11CursorFactoryTest, InvisibleRefcount) { ...@@ -19,7 +19,7 @@ TEST(X11CursorFactoryTest, InvisibleRefcount) {
// than a single reference since the factory should hold a reference and // than a single reference since the factory should hold a reference and
// CreateImageCursor should return an incremented refcount. // CreateImageCursor should return an incremented refcount.
auto* invisible_cursor = static_cast<X11Cursor*>( auto* invisible_cursor = static_cast<X11Cursor*>(
factory.CreateImageCursor(SkBitmap(), gfx::Point())); factory.CreateImageCursor({}, SkBitmap(), gfx::Point()));
ASSERT_FALSE(invisible_cursor->HasOneRef()); ASSERT_FALSE(invisible_cursor->HasOneRef());
// Release our refcount on the cursor // Release our refcount on the cursor
......
...@@ -182,6 +182,7 @@ source_set("wayland") { ...@@ -182,6 +182,7 @@ source_set("wayland") {
"//ui/base:buildflags", "//ui/base:buildflags",
"//ui/base/cursor", "//ui/base/cursor",
"//ui/base/cursor:cursor_base", "//ui/base/cursor:cursor_base",
"//ui/base/cursor/mojom:cursor_type",
"//ui/base/ime/linux", "//ui/base/ime/linux",
"//ui/events", "//ui/events",
"//ui/events:dom_keycode_converter", "//ui/events:dom_keycode_converter",
...@@ -270,6 +271,7 @@ source_set("test_support") { ...@@ -270,6 +271,7 @@ source_set("test_support") {
testonly = true testonly = true
sources = [ sources = [
"host/wayland_connection_test_api.h",
"test/global_object.cc", "test/global_object.cc",
"test/global_object.h", "test/global_object.h",
"test/mock_buffer.cc", "test/mock_buffer.cc",
...@@ -333,6 +335,7 @@ source_set("test_support") { ...@@ -333,6 +335,7 @@ source_set("test_support") {
] ]
deps = [ deps = [
":wayland",
"//base:base", "//base:base",
"//ui/ozone:platform", "//ui/ozone:platform",
] ]
...@@ -377,6 +380,7 @@ source_set("wayland_unittests") { ...@@ -377,6 +380,7 @@ source_set("wayland_unittests") {
"//testing/gmock", "//testing/gmock",
"//testing/gtest", "//testing/gtest",
"//third_party/wayland:wayland_server", "//third_party/wayland:wayland_server",
"//third_party/wayland-protocols:cursor_shapes_protocol",
"//third_party/wayland-protocols:keyboard_extension_protocol", "//third_party/wayland-protocols:keyboard_extension_protocol",
"//third_party/wayland-protocols:linux_dmabuf_protocol", "//third_party/wayland-protocols:linux_dmabuf_protocol",
"//third_party/wayland-protocols:text_input_protocol", "//third_party/wayland-protocols:text_input_protocol",
......
...@@ -168,6 +168,8 @@ class WaylandConnection { ...@@ -168,6 +168,8 @@ class WaylandConnection {
wl::Object<wl_surface> CreateSurface(); wl::Object<wl_surface> CreateSurface();
private: private:
friend class WaylandConnectionTestApi;
void Flush(); void Flush();
void UpdateInputDevices(wl_seat* seat, uint32_t capabilities); void UpdateInputDevices(wl_seat* seat, uint32_t capabilities);
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_CONNECTION_TEST_API_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_CONNECTION_TEST_API_H_
#include <memory>
#include <utility>
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
namespace ui {
class WaylandConnection;
// Allows tests to override private data in a WaylandConnection.
class WaylandConnectionTestApi {
public:
explicit WaylandConnectionTestApi(WaylandConnection* impl) : impl_(impl) {}
WaylandConnectionTestApi(const WaylandConnectionTestApi&) = delete;
WaylandConnectionTestApi& operator=(const WaylandConnectionTestApi&) = delete;
~WaylandConnectionTestApi() = default;
void SetZcrCursorShapes(std::unique_ptr<WaylandZcrCursorShapes> obj) {
impl_->zcr_cursor_shapes_ = std::move(obj);
}
private:
WaylandConnection* const impl_;
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_CONNECTION_TEST_API_H_
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h" #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/ozone/platform/wayland/host/wayland_cursor.h" #include "ui/ozone/platform/wayland/host/wayland_cursor.h"
...@@ -267,8 +268,8 @@ TEST_P(WaylandPointerTest, SetBitmapOnPointerFocus) { ...@@ -267,8 +268,8 @@ TEST_P(WaylandPointerTest, SetBitmapOnPointerFocus) {
dummy_cursor.allocPixels(info, 10 * 4); dummy_cursor.allocPixels(info, 10 * 4);
BitmapCursorFactoryOzone cursor_factory; BitmapCursorFactoryOzone cursor_factory;
PlatformCursor cursor = PlatformCursor cursor = cursor_factory.CreateImageCursor(
cursor_factory.CreateImageCursor(dummy_cursor, gfx::Point(5, 8)); mojom::CursorType::kCustom, dummy_cursor, gfx::Point(5, 8));
scoped_refptr<BitmapCursorOzone> bitmap = scoped_refptr<BitmapCursorOzone> bitmap =
BitmapCursorFactoryOzone::GetBitmapCursor(cursor); BitmapCursorFactoryOzone::GetBitmapCursor(cursor);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "ui/ozone/platform/wayland/host/wayland_output_manager.h" #include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
#include "ui/ozone/platform/wayland/host/wayland_pointer.h" #include "ui/ozone/platform/wayland/host/wayland_pointer.h"
#include "ui/ozone/platform/wayland/host/wayland_subsurface.h" #include "ui/ozone/platform/wayland/host/wayland_subsurface.h"
#include "ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h"
#include "ui/ozone/public/mojom/wayland/wayland_overlay_config.mojom.h" #include "ui/ozone/public/mojom/wayland/wayland_overlay_config.mojom.h"
namespace { namespace {
...@@ -219,16 +220,30 @@ void WaylandWindow::SetCursor(PlatformCursor cursor) { ...@@ -219,16 +220,30 @@ void WaylandWindow::SetCursor(PlatformCursor cursor) {
bitmap_ = bitmap; bitmap_ = bitmap;
if (bitmap_) { if (!bitmap_) {
// Translate physical pixels to DIPs. // Hide the cursor.
gfx::Point hotspot_in_dips =
gfx::ScaleToRoundedPoint(bitmap_->hotspot(), 1.0f / ui_scale_);
connection_->SetCursorBitmap(bitmap_->bitmaps(), hotspot_in_dips,
buffer_scale());
} else {
connection_->SetCursorBitmap(std::vector<SkBitmap>(), gfx::Point(), connection_->SetCursorBitmap(std::vector<SkBitmap>(), gfx::Point(),
buffer_scale()); buffer_scale());
return;
}
// Check for Wayland server-side cursor support (e.g. exo for lacros).
if (connection_->zcr_cursor_shapes()) {
base::Optional<int32_t> shape =
WaylandZcrCursorShapes::ShapeFromType(bitmap->type());
// If the server supports this cursor type, use a server-side cursor.
if (shape.has_value()) {
// We should not have loaded image assets for this cursor.
DCHECK(bitmap_->bitmaps().empty());
connection_->zcr_cursor_shapes()->SetCursorShape(shape.value());
return;
}
// Fall through to client-side bitmap cursors.
} }
// Translate physical pixels to DIPs.
gfx::Point hotspot_in_dips =
gfx::ScaleToRoundedPoint(bitmap_->hotspot(), 1.0f / ui_scale_);
connection_->SetCursorBitmap(bitmap_->bitmaps(), hotspot_in_dips,
buffer_scale());
} }
void WaylandWindow::MoveCursorTo(const gfx::Point& location) { void WaylandWindow::MoveCursorTo(const gfx::Point& location) {
......
...@@ -7,16 +7,20 @@ ...@@ -7,16 +7,20 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <cursor-shapes-unstable-v1-client-protocol.h>
#include <linux/input.h> #include <linux/input.h>
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <xdg-shell-server-protocol.h> #include <xdg-shell-server-protocol.h>
#include <xdg-shell-unstable-v6-server-protocol.h> #include <xdg-shell-unstable-v6-server-protocol.h>
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/base/hit_test.h" #include "ui/base/hit_test.h"
#include "ui/events/base_event_utils.h" #include "ui/events/base_event_utils.h"
#include "ui/events/event.h" #include "ui/events/event.h"
...@@ -24,7 +28,9 @@ ...@@ -24,7 +28,9 @@
#include "ui/gfx/overlay_transform.h" #include "ui/gfx/overlay_transform.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h" #include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h" #include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h"
#include "ui/ozone/platform/wayland/host/wayland_connection_test_api.h"
#include "ui/ozone/platform/wayland/host/wayland_subsurface.h" #include "ui/ozone/platform/wayland/host/wayland_subsurface.h"
#include "ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h"
#include "ui/ozone/platform/wayland/test/mock_pointer.h" #include "ui/ozone/platform/wayland/test/mock_pointer.h"
#include "ui/ozone/platform/wayland/test/mock_surface.h" #include "ui/ozone/platform/wayland/test/mock_surface.h"
#include "ui/ozone/platform/wayland/test/test_keyboard.h" #include "ui/ozone/platform/wayland/test/test_keyboard.h"
...@@ -33,6 +39,7 @@ ...@@ -33,6 +39,7 @@
#include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h" #include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h"
#include "ui/ozone/platform/wayland/test/wayland_test.h" #include "ui/ozone/platform/wayland/test/wayland_test.h"
#include "ui/ozone/test/mock_platform_window_delegate.h" #include "ui/ozone/test/mock_platform_window_delegate.h"
#include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_init_properties.h" #include "ui/platform_window/platform_window_init_properties.h"
#include "ui/platform_window/wm/wm_move_resize_handler.h" #include "ui/platform_window/wm/wm_move_resize_handler.h"
...@@ -92,6 +99,16 @@ base::ScopedFD MakeFD() { ...@@ -92,6 +99,16 @@ base::ScopedFD MakeFD() {
return base::ScopedFD(file.TakePlatformFile()); return base::ScopedFD(file.TakePlatformFile());
} }
class MockZcrCursorShapes : public WaylandZcrCursorShapes {
public:
MockZcrCursorShapes() : WaylandZcrCursorShapes(nullptr, nullptr) {}
MockZcrCursorShapes(const MockZcrCursorShapes&) = delete;
MockZcrCursorShapes& operator=(const MockZcrCursorShapes&) = delete;
~MockZcrCursorShapes() override = default;
MOCK_METHOD(void, SetCursorShape, (int32_t), (override));
};
} // namespace } // namespace
class WaylandWindowTest : public WaylandTest { class WaylandWindowTest : public WaylandTest {
...@@ -173,6 +190,14 @@ class WaylandWindowTest : public WaylandTest { ...@@ -173,6 +190,14 @@ class WaylandWindowTest : public WaylandTest {
hit_tests->push_back(static_cast<int>(HTTOPRIGHT)); hit_tests->push_back(static_cast<int>(HTTOPRIGHT));
} }
MockZcrCursorShapes* InstallMockZcrCursorShapes() {
auto zcr_cursor_shapes = std::make_unique<MockZcrCursorShapes>();
MockZcrCursorShapes* mock_cursor_shapes = zcr_cursor_shapes.get();
WaylandConnectionTestApi test_api(connection_.get());
test_api.SetZcrCursorShapes(std::move(zcr_cursor_shapes));
return mock_cursor_shapes;
}
void VerifyAndClearExpectations() { void VerifyAndClearExpectations() {
Mock::VerifyAndClearExpectations(xdg_surface_); Mock::VerifyAndClearExpectations(xdg_surface_);
Mock::VerifyAndClearExpectations(&delegate_); Mock::VerifyAndClearExpectations(&delegate_);
...@@ -802,6 +827,56 @@ TEST_P(WaylandWindowTest, CanDispatchMouseEventUnfocus) { ...@@ -802,6 +827,56 @@ TEST_P(WaylandWindowTest, CanDispatchMouseEventUnfocus) {
EXPECT_FALSE(window_->CanDispatchEvent(&test_mouse_event_)); EXPECT_FALSE(window_->CanDispatchEvent(&test_mouse_event_));
} }
TEST_P(WaylandWindowTest, SetCursorUsesZcrCursorShapesForCommonTypes) {
MockZcrCursorShapes* mock_cursor_shapes = InstallMockZcrCursorShapes();
// Verify some commonly-used cursors.
EXPECT_CALL(*mock_cursor_shapes,
SetCursorShape(ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_POINTER));
auto pointer_cursor =
base::MakeRefCounted<BitmapCursorOzone>(mojom::CursorType::kPointer);
window_->SetCursor(pointer_cursor.get());
EXPECT_CALL(*mock_cursor_shapes,
SetCursorShape(ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_HAND));
auto hand_cursor =
base::MakeRefCounted<BitmapCursorOzone>(mojom::CursorType::kHand);
window_->SetCursor(hand_cursor.get());
EXPECT_CALL(*mock_cursor_shapes,
SetCursorShape(ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_IBEAM));
auto ibeam_cursor =
base::MakeRefCounted<BitmapCursorOzone>(mojom::CursorType::kIBeam);
window_->SetCursor(ibeam_cursor.get());
}
TEST_P(WaylandWindowTest, SetCursorCallsZcrCursorShapesOncePerCursor) {
MockZcrCursorShapes* mock_cursor_shapes = InstallMockZcrCursorShapes();
auto hand_cursor =
base::MakeRefCounted<BitmapCursorOzone>(mojom::CursorType::kHand);
// Setting the same cursor twice on the client only calls the server once.
EXPECT_CALL(*mock_cursor_shapes, SetCursorShape(_)).Times(1);
window_->SetCursor(hand_cursor.get());
window_->SetCursor(hand_cursor.get());
}
TEST_P(WaylandWindowTest, SetCursorDoesNotUseZcrCursorShapesForNoneCursor) {
MockZcrCursorShapes* mock_cursor_shapes = InstallMockZcrCursorShapes();
EXPECT_CALL(*mock_cursor_shapes, SetCursorShape(_)).Times(0);
// The "none" cursor is represented by nullptr.
window_->SetCursor(nullptr);
}
TEST_P(WaylandWindowTest, SetCursorDoesNotUseZcrCursorShapesForCustomCursors) {
MockZcrCursorShapes* mock_cursor_shapes = InstallMockZcrCursorShapes();
// Custom cursors require bitmaps, so they do not use server-side cursors.
EXPECT_CALL(*mock_cursor_shapes, SetCursorShape(_)).Times(0);
auto custom_cursor = base::MakeRefCounted<BitmapCursorOzone>(
mojom::CursorType::kCustom, SkBitmap(), gfx::Point());
window_->SetCursor(custom_cursor.get());
}
ACTION_P(CloneEvent, ptr) { ACTION_P(CloneEvent, ptr) {
*ptr = Event::Clone(*arg0); *ptr = Event::Clone(*arg0);
} }
......
...@@ -4,18 +4,145 @@ ...@@ -4,18 +4,145 @@
#include "ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h" #include "ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h"
#include <cursor-shapes-unstable-v1-client-protocol.h>
#include "base/check.h" #include "base/check.h"
#include "base/optional.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_pointer.h"
namespace ui { namespace ui {
using mojom::CursorType;
WaylandZcrCursorShapes::WaylandZcrCursorShapes( WaylandZcrCursorShapes::WaylandZcrCursorShapes(
zcr_cursor_shapes_v1* zcr_cursor_shapes, zcr_cursor_shapes_v1* zcr_cursor_shapes,
WaylandConnection* connection) WaylandConnection* connection)
: zcr_cursor_shapes_v1_(zcr_cursor_shapes), connection_(connection) { : zcr_cursor_shapes_v1_(zcr_cursor_shapes), connection_(connection) {
DCHECK(zcr_cursor_shapes_v1_); // |zcr_cursor_shapes_v1_| and |connection_| may be null in tests.
DCHECK(connection_);
} }
WaylandZcrCursorShapes::~WaylandZcrCursorShapes() = default; WaylandZcrCursorShapes::~WaylandZcrCursorShapes() = default;
// static
base::Optional<int32_t> WaylandZcrCursorShapes::ShapeFromType(CursorType type) {
switch (type) {
case CursorType::kNull:
// kNull is an alias for kPointer. Fall through.
case CursorType::kPointer:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_POINTER;
case CursorType::kCross:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_CROSS;
case CursorType::kHand:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_HAND;
case CursorType::kIBeam:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_IBEAM;
case CursorType::kWait:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_WAIT;
case CursorType::kHelp:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_HELP;
case CursorType::kEastResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_EAST_RESIZE;
case CursorType::kNorthResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_NORTH_RESIZE;
case CursorType::kNorthEastResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_NORTH_EAST_RESIZE;
case CursorType::kNorthWestResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_NORTH_WEST_RESIZE;
case CursorType::kSouthResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_SOUTH_RESIZE;
case CursorType::kSouthEastResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_SOUTH_EAST_RESIZE;
case CursorType::kSouthWestResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_SOUTH_WEST_RESIZE;
case CursorType::kWestResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_WEST_RESIZE;
case CursorType::kNorthSouthResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_NORTH_SOUTH_RESIZE;
case CursorType::kEastWestResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_EAST_WEST_RESIZE;
case CursorType::kNorthEastSouthWestResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_NORTH_EAST_SOUTH_WEST_RESIZE;
case CursorType::kNorthWestSouthEastResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_NORTH_WEST_SOUTH_EAST_RESIZE;
case CursorType::kColumnResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_COLUMN_RESIZE;
case CursorType::kRowResize:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_ROW_RESIZE;
case CursorType::kMiddlePanning:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_MIDDLE_PANNING;
case CursorType::kEastPanning:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_EAST_PANNING;
case CursorType::kNorthPanning:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_NORTH_PANNING;
case CursorType::kNorthEastPanning:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_NORTH_EAST_PANNING;
case CursorType::kNorthWestPanning:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_NORTH_WEST_PANNING;
case CursorType::kSouthPanning:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_SOUTH_PANNING;
case CursorType::kSouthEastPanning:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_SOUTH_EAST_PANNING;
case CursorType::kSouthWestPanning:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_SOUTH_WEST_PANNING;
case CursorType::kWestPanning:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_WEST_PANNING;
case CursorType::kMove:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_MOVE;
case CursorType::kVerticalText:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_VERTICAL_TEXT;
case CursorType::kCell:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_CELL;
case CursorType::kContextMenu:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_CONTEXT_MENU;
case CursorType::kAlias:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_ALIAS;
case CursorType::kProgress:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_PROGRESS;
case CursorType::kNoDrop:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_NO_DROP;
case CursorType::kCopy:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_COPY;
case CursorType::kNone:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_NONE;
case CursorType::kNotAllowed:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_NOT_ALLOWED;
case CursorType::kZoomIn:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_ZOOM_IN;
case CursorType::kZoomOut:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_ZOOM_OUT;
case CursorType::kGrab:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_GRAB;
case CursorType::kGrabbing:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_GRABBING;
case CursorType::kMiddlePanningVertical:
case CursorType::kMiddlePanningHorizontal:
// Not supported by this API.
return base::nullopt;
case CursorType::kCustom:
// Custom means a bitmap cursor, which can't use the shape API.
return base::nullopt;
case CursorType::kDndNone:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_DND_NONE;
case CursorType::kDndMove:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_DND_MOVE;
case CursorType::kDndCopy:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_DND_COPY;
case CursorType::kDndLink:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_DND_LINK;
// NOTE: If you add a new cursor shape, please also update
// UseDefaultCursorForType() in bitmap_cursor_factory_ozone.cc.
}
}
void WaylandZcrCursorShapes::SetCursorShape(int32_t shape) {
// Nothing to do if there's no pointer (mouse) connected.
if (!connection_->pointer())
return;
zcr_cursor_shapes_v1_set_cursor_shape(
zcr_cursor_shapes_v1_.get(), connection_->pointer()->wl_object(), shape);
}
} // namespace ui } // namespace ui
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZCR_CURSOR_SHAPES_H_ #ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZCR_CURSOR_SHAPES_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZCR_CURSOR_SHAPES_H_ #define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZCR_CURSOR_SHAPES_H_
#include "base/optional.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h" #include "ui/ozone/platform/wayland/common/wayland_object.h"
namespace ui { namespace ui {
...@@ -20,7 +22,15 @@ class WaylandZcrCursorShapes { ...@@ -20,7 +22,15 @@ class WaylandZcrCursorShapes {
WaylandConnection* connection); WaylandConnection* connection);
WaylandZcrCursorShapes(const WaylandZcrCursorShapes&) = delete; WaylandZcrCursorShapes(const WaylandZcrCursorShapes&) = delete;
WaylandZcrCursorShapes& operator=(const WaylandZcrCursorShapes&) = delete; WaylandZcrCursorShapes& operator=(const WaylandZcrCursorShapes&) = delete;
~WaylandZcrCursorShapes(); virtual ~WaylandZcrCursorShapes();
// Returns the cursor shape value for a cursor |type|, or nullopt if the
// type isn't supported by the cursor API.
static base::Optional<int32_t> ShapeFromType(mojom::CursorType type);
// Calls zcr_cursor_shapes_v1_set_cursor_shape(). See interface description
// for values for |shape|. Virtual for testing.
virtual void SetCursorShape(int32_t shape);
private: private:
wl::Object<zcr_cursor_shapes_v1> zcr_cursor_shapes_v1_; wl::Object<zcr_cursor_shapes_v1> zcr_cursor_shapes_v1_;
......
...@@ -14,14 +14,8 @@ ...@@ -14,14 +14,8 @@
namespace views { namespace views {
DesktopNativeCursorManager::DesktopNativeCursorManager() { DesktopNativeCursorManager::DesktopNativeCursorManager()
#if BUILDFLAG(IS_LACROS) : cursor_loader_(ui::CursorLoader::Create()) {}
const bool use_platform_cursors = false;
#else
const bool use_platform_cursors = true;
#endif
cursor_loader_ = ui::CursorLoader::Create(use_platform_cursors);
}
DesktopNativeCursorManager::~DesktopNativeCursorManager() = default; DesktopNativeCursorManager::~DesktopNativeCursorManager() = default;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment