forked from pool/nodejs-electron
562 lines
25 KiB
Diff
562 lines
25 KiB
Diff
|
From 653716a6838676b6cf257e0d9756eccbf509fabb Mon Sep 17 00:00:00 2001
|
||
|
From: Ilya Bizyaev <ilyabiz@chromium.org>
|
||
|
Date: Fri, 19 Jan 2024 02:02:03 +0000
|
||
|
Subject: [PATCH] Implement cursor-shape-v1
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
This CL is largely based on the existing support for the custom
|
||
|
zcr-cursor-shapes-v1 protocol used by Lacros.
|
||
|
|
||
|
cursor-shape-v1 is the new upstream protocol for server-side cursor shapes
|
||
|
based on zcr-cursor-shapes-v1. Of compositors, it is currently
|
||
|
implemented in KDE's KWin (in Plasma 6.0) and Sway (not yet released).
|
||
|
|
||
|
The enum mapping is based on
|
||
|
https://source.chromium.org/chromium/chromium/src/+/main:ui/base/cursor/cursor_factory.cc;l=115;drc=67d90538f11c6b232dbfd716075db52aeb34fd15
|
||
|
— despite the seemingly fewer shapes in cursor-shape-v1's list, the
|
||
|
reduction is the same as in Chromium's own FreeDesktop cursor loading code,
|
||
|
so there's no downside in letting the compositor do the work for us
|
||
|
whenever it offers to. Since the compositor — and, by extension, the
|
||
|
desktop environment — are the source of truth for cursor display
|
||
|
settings, this simplifies complying with the user's preferences.
|
||
|
|
||
|
Unlike Lacros, we cannot be sure at compile time that the compositor has
|
||
|
support for this protocol, so the cursor loading code is changed to not
|
||
|
give up on a shape when is has no bitmap and instead let the update
|
||
|
code try the server-side approach.
|
||
|
|
||
|
Exo does not support cursor-shape-v1, so it will keep using the
|
||
|
zcr-cursor-shapes-v1 branch.
|
||
|
|
||
|
I have tested this CL in a Plasma 6 RC1 session with this CSS demo:
|
||
|
https://www.tutorialrepublic.com/codelab.php?topic=css&file=cursor-property
|
||
|
|
||
|
Low-Coverage-Reason: TRIVIAL_CHANGE Not tested are the enum conversion and getters/setters, which is boilerplate.
|
||
|
Bug: 1427111
|
||
|
Cq-Include-Trybots: luci.chromium.try:linux-lacros-rel,linux-wayland-rel
|
||
|
Change-Id: I50567021e6fd80a641bbc906370c517efe16ffb9
|
||
|
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5196950
|
||
|
Commit-Queue: Ilya Bizyaev <ilyabiz@chromium.org>
|
||
|
Reviewed-by: Henrique Ferreiro <hferreiro@igalia.com>
|
||
|
Reviewed-by: Kramer Ge <fangzhoug@chromium.org>
|
||
|
Cr-Commit-Position: refs/heads/main@{#1249191}
|
||
|
---
|
||
|
third_party/wayland-protocols/BUILD.gn | 4 +
|
||
|
ui/ozone/common/bitmap_cursor_factory.cc | 90 +-------
|
||
|
.../common/bitmap_cursor_factory_unittest.cc | 12 +-
|
||
|
ui/ozone/platform/wayland/BUILD.gn | 5 +
|
||
|
.../platform/wayland/common/wayland_object.cc | 3 +
|
||
|
.../platform/wayland/common/wayland_object.h | 2 +
|
||
|
.../wayland/host/wayland_connection.cc | 3 +
|
||
|
.../wayland/host/wayland_connection.h | 7 +
|
||
|
.../host/wayland_connection_test_api.h | 5 +
|
||
|
.../wayland/host/wayland_cursor_shape.cc | 194 ++++++++++++++++++
|
||
|
.../wayland/host/wayland_cursor_shape.h | 53 +++++
|
||
|
.../platform/wayland/host/wayland_window.cc | 18 +-
|
||
|
.../wayland/host/wayland_window_unittest.cc | 76 +++++++
|
||
|
.../wayland/host/wayland_zcr_cursor_shapes.cc | 2 -
|
||
|
14 files changed, 371 insertions(+), 103 deletions(-)
|
||
|
create mode 100644 ui/ozone/platform/wayland/host/wayland_cursor_shape.cc
|
||
|
create mode 100644 ui/ozone/platform/wayland/host/wayland_cursor_shape.h
|
||
|
|
||
|
diff --git a/third_party/wayland-protocols/BUILD.gn b/third_party/wayland-protocols/BUILD.gn
|
||
|
index b0c0082769055..db15b95e41dd4 100644
|
||
|
--- a/third_party/wayland-protocols/BUILD.gn
|
||
|
+++ b/third_party/wayland-protocols/BUILD.gn
|
||
|
@@ -15,6 +15,10 @@ wayland_protocol("content_type_protocol") {
|
||
|
sources = [ "unstable/content-type/content-type-v1.xml" ]
|
||
|
}
|
||
|
|
||
|
+wayland_protocol("cursor_shape_protocol") {
|
||
|
+ sources = [ "src/staging/cursor-shape/cursor-shape-v1.xml" ]
|
||
|
+}
|
||
|
+
|
||
|
wayland_protocol("cursor_shapes_protocol") {
|
||
|
sources = [ "unstable/cursor-shapes/cursor-shapes-unstable-v1.xml" ]
|
||
|
}
|
||
|
diff --git a/ui/ozone/common/bitmap_cursor_factory.cc b/ui/ozone/common/bitmap_cursor_factory.cc
|
||
|
index cf9bb8655a9cb..fd7274ccd28e4 100644
|
||
|
--- a/ui/ozone/common/bitmap_cursor_factory.cc
|
||
|
+++ b/ui/ozone/common/bitmap_cursor_factory.cc
|
||
|
@@ -8,84 +8,11 @@
|
||
|
|
||
|
#include "base/check_op.h"
|
||
|
#include "base/memory/scoped_refptr.h"
|
||
|
-#include "build/chromeos_buildflags.h"
|
||
|
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
|
||
|
#include "ui/ozone/common/bitmap_cursor.h"
|
||
|
|
||
|
namespace ui {
|
||
|
|
||
|
-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:
|
||
|
- case CursorType::kEastWestNoResize:
|
||
|
- case CursorType::kNorthEastSouthWestNoResize:
|
||
|
- case CursorType::kNorthSouthNoResize:
|
||
|
- case CursorType::kNorthWestSouthEastNoResize:
|
||
|
- return false;
|
||
|
- }
|
||
|
-}
|
||
|
-#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
|
||
|
-
|
||
|
-} // namespace
|
||
|
-
|
||
|
BitmapCursorFactory::BitmapCursorFactory() = default;
|
||
|
|
||
|
BitmapCursorFactory::~BitmapCursorFactory() = default;
|
||
|
@@ -93,18 +20,11 @@ BitmapCursorFactory::~BitmapCursorFactory() = default;
|
||
|
scoped_refptr<PlatformCursor> BitmapCursorFactory::GetDefaultCursor(
|
||
|
mojom::CursorType type) {
|
||
|
if (!default_cursors_.count(type)) {
|
||
|
- if (type == mojom::CursorType::kNone
|
||
|
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
|
||
|
- || UseDefaultCursorForType(type)
|
||
|
-#endif
|
||
|
- ) {
|
||
|
- // Lacros uses server-side cursors for most types. These cursors don't
|
||
|
- // need to load bitmap images on the client.
|
||
|
- // Similarly, the hidden cursor doesn't use any bitmap.
|
||
|
- default_cursors_[type] = base::MakeRefCounted<BitmapCursor>(type);
|
||
|
- } else {
|
||
|
- return nullptr;
|
||
|
- }
|
||
|
+ // Return a cursor not backed by a bitmap to preserve the type information.
|
||
|
+ // It can still be used to request the compositor to draw a server-side
|
||
|
+ // cursor for the given type.
|
||
|
+ // kNone is handled separately and does not need a bitmap.
|
||
|
+ default_cursors_[type] = base::MakeRefCounted<BitmapCursor>(type);
|
||
|
}
|
||
|
|
||
|
return default_cursors_[type];
|
||
|
diff --git a/ui/ozone/common/bitmap_cursor_factory_unittest.cc b/ui/ozone/common/bitmap_cursor_factory_unittest.cc
|
||
|
index 905b721d66193..6428821d90c6b 100644
|
||
|
--- a/ui/ozone/common/bitmap_cursor_factory_unittest.cc
|
||
|
+++ b/ui/ozone/common/bitmap_cursor_factory_unittest.cc
|
||
|
@@ -4,7 +4,6 @@
|
||
|
|
||
|
#include "ui/ozone/common/bitmap_cursor_factory.h"
|
||
|
|
||
|
-#include "build/chromeos_buildflags.h"
|
||
|
#include "testing/gtest/include/gtest/gtest.h"
|
||
|
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
|
||
|
#include "ui/base/cursor/platform_cursor.h"
|
||
|
@@ -24,8 +23,7 @@ TEST(BitmapCursorFactoryTest, InvisibleCursor) {
|
||
|
CursorType::kNone);
|
||
|
}
|
||
|
|
||
|
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
|
||
|
-TEST(BitmapCursorFactoryTest, LacrosUsesDefaultCursorsForCommonTypes) {
|
||
|
+TEST(BitmapCursorFactoryTest, DefaultCursorsHaveTypeInformation) {
|
||
|
BitmapCursorFactory factory;
|
||
|
|
||
|
// Verify some common cursor types.
|
||
|
@@ -45,12 +43,4 @@ TEST(BitmapCursorFactoryTest, LacrosUsesDefaultCursorsForCommonTypes) {
|
||
|
CursorType::kIBeam);
|
||
|
}
|
||
|
|
||
|
-TEST(BitmapCursorFactoryTest, LacrosCustomCursor) {
|
||
|
- BitmapCursorFactory factory;
|
||
|
- auto cursor = factory.GetDefaultCursor(CursorType::kCustom);
|
||
|
- // Custom cursors don't have a default platform cursor.
|
||
|
- EXPECT_EQ(cursor, nullptr);
|
||
|
-}
|
||
|
-#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
|
||
|
-
|
||
|
} // namespace ui
|
||
|
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn
|
||
|
index 8ebc966e1e1c3..d3dc3c736aa3c 100644
|
||
|
--- a/ui/ozone/platform/wayland/BUILD.gn
|
||
|
+++ b/ui/ozone/platform/wayland/BUILD.gn
|
||
|
@@ -103,6 +103,8 @@ source_set("wayland") {
|
||
|
"host/wayland_cursor.h",
|
||
|
"host/wayland_cursor_position.cc",
|
||
|
"host/wayland_cursor_position.h",
|
||
|
+ "host/wayland_cursor_shape.cc",
|
||
|
+ "host/wayland_cursor_shape.h",
|
||
|
"host/wayland_data_device.cc",
|
||
|
"host/wayland_data_device.h",
|
||
|
"host/wayland_data_device_base.cc",
|
||
|
@@ -256,6 +258,7 @@ source_set("wayland") {
|
||
|
"//third_party/wayland:wayland_util",
|
||
|
"//third_party/wayland-protocols:alpha_compositing_protocol",
|
||
|
"//third_party/wayland-protocols:content_type_protocol",
|
||
|
+ "//third_party/wayland-protocols:cursor_shape_protocol",
|
||
|
"//third_party/wayland-protocols:cursor_shapes_protocol",
|
||
|
"//third_party/wayland-protocols:extended_drag",
|
||
|
"//third_party/wayland-protocols:fractional_scale_protocol",
|
||
|
@@ -274,6 +277,7 @@ source_set("wayland") {
|
||
|
"//third_party/wayland-protocols:relative_pointer_protocol",
|
||
|
"//third_party/wayland-protocols:single_pixel_buffer",
|
||
|
"//third_party/wayland-protocols:stylus_protocol",
|
||
|
+ "//third_party/wayland-protocols:tablet_protocol",
|
||
|
"//third_party/wayland-protocols:text_input_extension_protocol",
|
||
|
"//third_party/wayland-protocols:text_input_protocol",
|
||
|
"//third_party/wayland-protocols:touchpad_haptics_protocol",
|
||
|
@@ -623,6 +627,7 @@ source_set("wayland_unittests") {
|
||
|
"//testing/gmock",
|
||
|
"//testing/gtest",
|
||
|
"//third_party/wayland:wayland_server",
|
||
|
+ "//third_party/wayland-protocols:cursor_shape_protocol",
|
||
|
"//third_party/wayland-protocols:cursor_shapes_protocol",
|
||
|
"//third_party/wayland-protocols:keyboard_extension_protocol",
|
||
|
"//third_party/wayland-protocols:linux_dmabuf_protocol",
|
||
|
diff --git a/ui/ozone/platform/wayland/common/wayland_object.cc b/ui/ozone/platform/wayland/common/wayland_object.cc
|
||
|
index bcc48aaeb186e..7f09a9f4f67dd 100644
|
||
|
--- a/ui/ozone/platform/wayland/common/wayland_object.cc
|
||
|
+++ b/ui/ozone/platform/wayland/common/wayland_object.cc
|
||
|
@@ -8,6 +8,7 @@
|
||
|
#include <aura-shell-client-protocol.h>
|
||
|
#include <chrome-color-management-client-protocol.h>
|
||
|
#include <content-type-v1-client-protocol.h>
|
||
|
+#include <cursor-shape-v1-client-protocol.h>
|
||
|
#include <cursor-shapes-unstable-v1-client-protocol.h>
|
||
|
#include <extended-drag-unstable-v1-client-protocol.h>
|
||
|
#include <fractional-scale-v1-client-protocol.h>
|
||
|
@@ -228,6 +229,8 @@ IMPLEMENT_WAYLAND_OBJECT_TRAITS(wp_viewport)
|
||
|
IMPLEMENT_WAYLAND_OBJECT_TRAITS(wp_viewporter)
|
||
|
IMPLEMENT_WAYLAND_OBJECT_TRAITS(wp_content_type_v1)
|
||
|
IMPLEMENT_WAYLAND_OBJECT_TRAITS(wp_content_type_manager_v1)
|
||
|
+IMPLEMENT_WAYLAND_OBJECT_TRAITS(wp_cursor_shape_device_v1)
|
||
|
+IMPLEMENT_WAYLAND_OBJECT_TRAITS(wp_cursor_shape_manager_v1)
|
||
|
IMPLEMENT_WAYLAND_OBJECT_TRAITS(wp_fractional_scale_manager_v1)
|
||
|
IMPLEMENT_WAYLAND_OBJECT_TRAITS(wp_fractional_scale_v1)
|
||
|
IMPLEMENT_WAYLAND_OBJECT_TRAITS(xdg_activation_v1)
|
||
|
diff --git a/ui/ozone/platform/wayland/common/wayland_object.h b/ui/ozone/platform/wayland/common/wayland_object.h
|
||
|
index c84c084841ea9..436e7ff5f3910 100644
|
||
|
--- a/ui/ozone/platform/wayland/common/wayland_object.h
|
||
|
+++ b/ui/ozone/platform/wayland/common/wayland_object.h
|
||
|
@@ -146,6 +146,8 @@ DECLARE_WAYLAND_OBJECT_TRAITS(wp_viewport)
|
||
|
DECLARE_WAYLAND_OBJECT_TRAITS(wp_viewporter)
|
||
|
DECLARE_WAYLAND_OBJECT_TRAITS(wp_content_type_manager_v1)
|
||
|
DECLARE_WAYLAND_OBJECT_TRAITS(wp_content_type_v1)
|
||
|
+DECLARE_WAYLAND_OBJECT_TRAITS(wp_cursor_shape_device_v1)
|
||
|
+DECLARE_WAYLAND_OBJECT_TRAITS(wp_cursor_shape_manager_v1)
|
||
|
DECLARE_WAYLAND_OBJECT_TRAITS(wp_fractional_scale_manager_v1)
|
||
|
DECLARE_WAYLAND_OBJECT_TRAITS(wp_fractional_scale_v1)
|
||
|
DECLARE_WAYLAND_OBJECT_TRAITS(xdg_activation_v1)
|
||
|
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc
|
||
|
index 5c62c0ead1497..944c9dd6904cd 100644
|
||
|
--- a/ui/ozone/platform/wayland/host/wayland_connection.cc
|
||
|
+++ b/ui/ozone/platform/wayland/host/wayland_connection.cc
|
||
|
@@ -41,6 +41,7 @@
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_cursor.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_cursor_position.h"
|
||
|
+#include "ui/ozone/platform/wayland/host/wayland_cursor_shape.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_data_device_manager.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_drm.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_event_source.h"
|
||
|
@@ -165,6 +166,8 @@ bool WaylandConnection::Initialize(bool use_threaded_polling) {
|
||
|
RegisterGlobalObjectFactory(WaylandZcrColorManager::kInterfaceName,
|
||
|
&WaylandZcrColorManager::Instantiate);
|
||
|
}
|
||
|
+ RegisterGlobalObjectFactory(WaylandCursorShape::kInterfaceName,
|
||
|
+ &WaylandCursorShape::Instantiate);
|
||
|
RegisterGlobalObjectFactory(WaylandZcrCursorShapes::kInterfaceName,
|
||
|
&WaylandZcrCursorShapes::Instantiate);
|
||
|
RegisterGlobalObjectFactory(WaylandZcrTouchpadHaptics::kInterfaceName,
|
||
|
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.h b/ui/ozone/platform/wayland/host/wayland_connection.h
|
||
|
index b0bb930a3de99..13be193482721 100644
|
||
|
--- a/ui/ozone/platform/wayland/host/wayland_connection.h
|
||
|
+++ b/ui/ozone/platform/wayland/host/wayland_connection.h
|
||
|
@@ -62,6 +62,7 @@ class WaylandZwpPointerGestures;
|
||
|
class WaylandZwpRelativePointerManager;
|
||
|
class WaylandDataDeviceManager;
|
||
|
class WaylandCursorPosition;
|
||
|
+class WaylandCursorShape;
|
||
|
class WaylandWindowDragController;
|
||
|
class GtkPrimarySelectionDeviceManager;
|
||
|
class GtkShell1;
|
||
|
@@ -209,6 +210,10 @@ class WaylandConnection {
|
||
|
return zcr_color_manager_.get();
|
||
|
}
|
||
|
|
||
|
+ WaylandCursorShape* wayland_cursor_shape() const {
|
||
|
+ return cursor_shape_.get();
|
||
|
+ }
|
||
|
+
|
||
|
WaylandZcrCursorShapes* zcr_cursor_shapes() const {
|
||
|
return zcr_cursor_shapes_.get();
|
||
|
}
|
||
|
@@ -383,6 +388,7 @@ class WaylandConnection {
|
||
|
friend class WaylandZwpPointerGestures;
|
||
|
friend class WaylandZwpRelativePointerManager;
|
||
|
friend class WaylandZcrColorManager;
|
||
|
+ friend class WaylandCursorShape;
|
||
|
friend class WaylandZcrCursorShapes;
|
||
|
friend class XdgActivation;
|
||
|
friend class XdgForeignWrapper;
|
||
|
@@ -483,6 +489,7 @@ class WaylandConnection {
|
||
|
std::unique_ptr<WaylandZAuraOutputManager> zaura_output_manager_;
|
||
|
std::unique_ptr<WaylandZAuraShell> zaura_shell_;
|
||
|
std::unique_ptr<WaylandZcrColorManager> zcr_color_manager_;
|
||
|
+ std::unique_ptr<WaylandCursorShape> cursor_shape_;
|
||
|
std::unique_ptr<WaylandZcrCursorShapes> zcr_cursor_shapes_;
|
||
|
std::unique_ptr<WaylandZcrTouchpadHaptics> zcr_touchpad_haptics_;
|
||
|
std::unique_ptr<WaylandZwpPointerConstraints> zwp_pointer_constraints_;
|
||
|
diff --git a/ui/ozone/platform/wayland/host/wayland_connection_test_api.h b/ui/ozone/platform/wayland/host/wayland_connection_test_api.h
|
||
|
index 31e61aff6010b..419801f0257a3 100644
|
||
|
--- a/ui/ozone/platform/wayland/host/wayland_connection_test_api.h
|
||
|
+++ b/ui/ozone/platform/wayland/host/wayland_connection_test_api.h
|
||
|
@@ -10,6 +10,7 @@
|
||
|
|
||
|
#include "base/memory/raw_ptr.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
|
||
|
+#include "ui/ozone/platform/wayland/host/wayland_cursor_shape.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h"
|
||
|
|
||
|
namespace ui {
|
||
|
@@ -22,6 +23,10 @@ class WaylandConnectionTestApi {
|
||
|
WaylandConnectionTestApi& operator=(const WaylandConnectionTestApi&) = delete;
|
||
|
~WaylandConnectionTestApi() = default;
|
||
|
|
||
|
+ void SetCursorShape(std::unique_ptr<WaylandCursorShape> obj) {
|
||
|
+ impl_->cursor_shape_ = std::move(obj);
|
||
|
+ }
|
||
|
+
|
||
|
void SetZcrCursorShapes(std::unique_ptr<WaylandZcrCursorShapes> obj) {
|
||
|
impl_->zcr_cursor_shapes_ = std::move(obj);
|
||
|
}
|
||
|
diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc
|
||
|
index 68f87776ef4f0..f5c36964ad36d 100644
|
||
|
--- a/ui/ozone/platform/wayland/host/wayland_window.cc
|
||
|
+++ b/ui/ozone/platform/wayland/host/wayland_window.cc
|
||
|
@@ -41,6 +41,7 @@
|
||
|
#include "ui/ozone/platform/wayland/common/wayland_overlay_config.h"
|
||
|
#include "ui/ozone/platform/wayland/host/dump_util.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
|
||
|
+#include "ui/ozone/platform/wayland/host/wayland_cursor_shape.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_data_drag_controller.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_event_source.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_frame_manager.h"
|
||
|
@@ -1110,7 +1111,9 @@ void WaylandWindow::UpdateCursorShape(scoped_refptr<BitmapCursor> cursor) {
|
||
|
base::IsValueInRangeForNumericType<int>(
|
||
|
cursor->cursor_image_scale_factor()));
|
||
|
|
||
|
- std::optional<int32_t> shape =
|
||
|
+ std::optional<uint32_t> shape =
|
||
|
+ WaylandCursorShape::ShapeFromType(cursor->type());
|
||
|
+ std::optional<int32_t> zcr_shape =
|
||
|
WaylandZcrCursorShapes::ShapeFromType(cursor->type());
|
||
|
|
||
|
// Round cursor scale factor to ceil as wl_surface.set_buffer_scale accepts
|
||
|
@@ -1118,20 +1121,25 @@ void WaylandWindow::UpdateCursorShape(scoped_refptr<BitmapCursor> cursor) {
|
||
|
if (cursor->type() == CursorType::kNone) { // Hide the cursor.
|
||
|
connection_->SetCursorBitmap(
|
||
|
{}, gfx::Point(), std::ceil(cursor->cursor_image_scale_factor()));
|
||
|
+ } else if (connection_->wayland_cursor_shape() && shape.has_value()) {
|
||
|
+ // Prefer Wayland server-side cursor support, as the compositor knows better
|
||
|
+ // how to draw the cursor.
|
||
|
+ connection_->wayland_cursor_shape()->SetCursorShape(shape.value());
|
||
|
} else if (cursor->platform_data()) { // Check for theme-provided cursor.
|
||
|
connection_->SetPlatformCursor(
|
||
|
reinterpret_cast<wl_cursor*>(cursor->platform_data()),
|
||
|
std::ceil(cursor->cursor_image_scale_factor()));
|
||
|
} else if (connection_->zcr_cursor_shapes() &&
|
||
|
- shape.has_value()) { // Check for Wayland server-side cursor
|
||
|
- // support (e.g. exo for lacros).
|
||
|
+ zcr_shape.has_value()) { // Check for Exo server-side cursor
|
||
|
+ // support.
|
||
|
#if BUILDFLAG(IS_CHROMEOS_LACROS)
|
||
|
// Lacros should not load image assets for default cursors. See
|
||
|
// `BitmapCursorFactory::GetDefaultCursor()`.
|
||
|
DCHECK(cursor->bitmaps().empty());
|
||
|
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
|
||
|
- connection_->zcr_cursor_shapes()->SetCursorShape(shape.value());
|
||
|
- } else { // Use client-side bitmap cursors as fallback.
|
||
|
+ connection_->zcr_cursor_shapes()->SetCursorShape(zcr_shape.value());
|
||
|
+ } else if (!cursor->bitmaps()
|
||
|
+ .empty()) { // Use client-side bitmap cursors as fallback.
|
||
|
// Translate physical pixels to DIPs.
|
||
|
gfx::Point hotspot_in_dips = gfx::ScaleToRoundedPoint(
|
||
|
cursor->hotspot(), 1.0f / cursor->cursor_image_scale_factor());
|
||
|
diff --git a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
|
||
|
index 49dcdfed360fe..7a1640bc6f045 100644
|
||
|
--- a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
|
||
|
+++ b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
|
||
|
@@ -11,6 +11,7 @@
|
||
|
#include <utility>
|
||
|
#include <vector>
|
||
|
|
||
|
+#include <cursor-shape-v1-client-protocol.h>
|
||
|
#include <cursor-shapes-unstable-v1-client-protocol.h>
|
||
|
#include <linux/input.h>
|
||
|
#include <wayland-server-core.h>
|
||
|
@@ -51,6 +52,7 @@
|
||
|
#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_connection_test_api.h"
|
||
|
+#include "ui/ozone/platform/wayland/host/wayland_cursor_shape.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_event_source.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_output.h"
|
||
|
#include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
|
||
|
@@ -146,6 +148,16 @@ wl::ScopedWlArray MakeStateArray(const std::vector<int32_t> states) {
|
||
|
return wl::ScopedWlArray(states);
|
||
|
}
|
||
|
|
||
|
+class MockCursorShape : public WaylandCursorShape {
|
||
|
+ public:
|
||
|
+ MockCursorShape() : WaylandCursorShape(nullptr, nullptr) {}
|
||
|
+ MockCursorShape(const MockCursorShape&) = delete;
|
||
|
+ MockCursorShape& operator=(const MockCursorShape&) = delete;
|
||
|
+ ~MockCursorShape() override = default;
|
||
|
+
|
||
|
+ MOCK_METHOD(void, SetCursorShape, (uint32_t), (override));
|
||
|
+};
|
||
|
+
|
||
|
class MockZcrCursorShapes : public WaylandZcrCursorShapes {
|
||
|
public:
|
||
|
MockZcrCursorShapes() : WaylandZcrCursorShapes(nullptr, nullptr) {}
|
||
|
@@ -264,6 +276,14 @@ class WaylandWindowTest : public WaylandTest {
|
||
|
hit_tests->push_back(static_cast<int>(HTTOPRIGHT));
|
||
|
}
|
||
|
|
||
|
+ MockCursorShape* InstallMockCursorShape() {
|
||
|
+ auto zcr_cursor_shapes = std::make_unique<MockCursorShape>();
|
||
|
+ MockCursorShape* mock_cursor_shapes = zcr_cursor_shapes.get();
|
||
|
+ WaylandConnectionTestApi test_api(connection_.get());
|
||
|
+ test_api.SetCursorShape(std::move(zcr_cursor_shapes));
|
||
|
+ return mock_cursor_shapes;
|
||
|
+ }
|
||
|
+
|
||
|
MockZcrCursorShapes* InstallMockZcrCursorShapes() {
|
||
|
auto zcr_cursor_shapes = std::make_unique<MockZcrCursorShapes>();
|
||
|
MockZcrCursorShapes* mock_cursor_shapes = zcr_cursor_shapes.get();
|
||
|
@@ -1692,6 +1712,62 @@ TEST_P(WaylandWindowTest, CanDispatchMouseEventFocus) {
|
||
|
EXPECT_TRUE(window_->CanDispatchEvent(&test_mouse_event_));
|
||
|
}
|
||
|
|
||
|
+TEST_P(WaylandWindowTest, SetCursorUsesCursorShapeForCommonTypes) {
|
||
|
+ SetPointerFocusedWindow(window_.get());
|
||
|
+ MockCursorShape* mock_cursor_shape = InstallMockCursorShape();
|
||
|
+
|
||
|
+ // Verify some commonly-used cursors.
|
||
|
+ EXPECT_CALL(*mock_cursor_shape,
|
||
|
+ SetCursorShape(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT));
|
||
|
+ auto pointer_cursor = AsPlatformCursor(
|
||
|
+ base::MakeRefCounted<BitmapCursor>(mojom::CursorType::kPointer));
|
||
|
+ window_->SetCursor(pointer_cursor.get());
|
||
|
+
|
||
|
+ EXPECT_CALL(*mock_cursor_shape,
|
||
|
+ SetCursorShape(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER));
|
||
|
+ auto hand_cursor = AsPlatformCursor(
|
||
|
+ base::MakeRefCounted<BitmapCursor>(mojom::CursorType::kHand));
|
||
|
+ window_->SetCursor(hand_cursor.get());
|
||
|
+
|
||
|
+ EXPECT_CALL(*mock_cursor_shape,
|
||
|
+ SetCursorShape(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT));
|
||
|
+ auto ibeam_cursor = AsPlatformCursor(
|
||
|
+ base::MakeRefCounted<BitmapCursor>(mojom::CursorType::kIBeam));
|
||
|
+ window_->SetCursor(ibeam_cursor.get());
|
||
|
+}
|
||
|
+
|
||
|
+TEST_P(WaylandWindowTest, SetCursorCallsCursorShapeOncePerCursor) {
|
||
|
+ SetPointerFocusedWindow(window_.get());
|
||
|
+ MockCursorShape* mock_cursor_shape = InstallMockCursorShape();
|
||
|
+ auto hand_cursor = AsPlatformCursor(
|
||
|
+ base::MakeRefCounted<BitmapCursor>(mojom::CursorType::kHand));
|
||
|
+ // Setting the same cursor twice on the client only calls the server once.
|
||
|
+ EXPECT_CALL(*mock_cursor_shape, SetCursorShape(_)).Times(1);
|
||
|
+ window_->SetCursor(hand_cursor.get());
|
||
|
+ window_->SetCursor(hand_cursor.get());
|
||
|
+}
|
||
|
+
|
||
|
+TEST_P(WaylandWindowTest, SetCursorDoesNotUseCursorShapeForNoneCursor) {
|
||
|
+ SetPointerFocusedWindow(window_.get());
|
||
|
+ MockCursorShape* mock_cursor_shape = InstallMockCursorShape();
|
||
|
+ EXPECT_CALL(*mock_cursor_shape, SetCursorShape(_)).Times(0);
|
||
|
+ auto none_cursor = AsPlatformCursor(
|
||
|
+ base::MakeRefCounted<BitmapCursor>(mojom::CursorType::kNone));
|
||
|
+ window_->SetCursor(none_cursor.get());
|
||
|
+}
|
||
|
+
|
||
|
+TEST_P(WaylandWindowTest, SetCursorDoesNotUseCursorShapeForCustomCursors) {
|
||
|
+ SetPointerFocusedWindow(window_.get());
|
||
|
+ MockCursorShape* mock_cursor_shape = InstallMockCursorShape();
|
||
|
+
|
||
|
+ // Custom cursors require bitmaps, so they do not use server-side cursors.
|
||
|
+ EXPECT_CALL(*mock_cursor_shape, SetCursorShape(_)).Times(0);
|
||
|
+ auto custom_cursor = AsPlatformCursor(
|
||
|
+ base::MakeRefCounted<BitmapCursor>(mojom::CursorType::kCustom, SkBitmap(),
|
||
|
+ gfx::Point(), kDefaultCursorScale));
|
||
|
+ window_->SetCursor(custom_cursor.get());
|
||
|
+}
|
||
|
+
|
||
|
TEST_P(WaylandWindowTest, SetCursorUsesZcrCursorShapesForCommonTypes) {
|
||
|
SetPointerFocusedWindow(window_.get());
|
||
|
MockZcrCursorShapes* mock_cursor_shapes = InstallMockZcrCursorShapes();
|
||
|
diff --git a/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.cc b/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.cc
|
||
|
index 9e3243dceea20..297c48e614087 100644
|
||
|
--- a/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.cc
|
||
|
+++ b/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.cc
|
||
|
@@ -168,8 +168,6 @@ absl::optional<int32_t> WaylandZcrCursorShapes::ShapeFromType(CursorType type) {
|
||
|
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.
|
||
|
}
|
||
|
}
|
||
|
|