0

Use scoped_refptr for platform cursors

Platform cursors will be automatically ref-counted by migrating them to
use scoped_refptr.

Originally, the custom platform cursors were ref-counted manually in
several places: after using a custom cursor created by
CursorFactory::CreateImageCursor() and in ui::Cursor and
content::WebCursor, when custom cursors were stored
(Cursor::SetPlatformCursor()) and copied (copy constructors/operators).

By moving to a ref-counted type, many types of bugs that happened in the
past regarding WebCursor and PlatformCursor lifetimes will be prevented
(e.g. removing WebCursor::operator=, and thus leaking the custom cursor
resources on each assignment).

Bug: 1149906
Change-Id: If0f8c8570e6bcb47b203086dc90f49b8e7253fd0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2255605
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Bret Sepulveda <bsep@chromium.org>
Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
Commit-Queue: Henrique Ferreiro <hferreiro@igalia.com>
Cr-Commit-Position: refs/heads/master@{#874510}
This commit is contained in:
Henrique Ferreiro
2021-04-21 00:52:11 +00:00
committed by Chromium LUCI CQ
parent 3c38617171
commit 070fa848c1
56 changed files with 384 additions and 453 deletions

@ -251,12 +251,10 @@ ui::Cursor GetCursorForFullscreenOrWindowCapture(bool capture_image) {
ui::ScaleAndRotateCursorBitmapAndHotpoint(
device_scale_factor, display.panel_rotation(), &bitmap, &hotspot);
auto* cursor_factory = ui::CursorFactory::GetInstance();
ui::PlatformCursor platform_cursor =
cursor_factory->CreateImageCursor(cursor.type(), bitmap, hotspot);
cursor.SetPlatformCursor(platform_cursor);
cursor.SetPlatformCursor(
cursor_factory->CreateImageCursor(cursor.type(), bitmap, hotspot));
cursor.set_custom_bitmap(bitmap);
cursor.set_custom_hotspot(hotspot);
cursor_factory->UnrefImageCursor(platform_cursor);
return cursor;
}

@ -766,16 +766,14 @@ void Pointer::UpdateCursor() {
ui::ScaleAndRotateCursorBitmapAndHotpoint(scale, display.panel_rotation(),
&bitmap, &hotspot);
ui::PlatformCursor platform_cursor;
// TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers
// and use that here instead of the current bitmap API.
// https://crbug.com/686600
platform_cursor = ui::CursorFactory::GetInstance()->CreateImageCursor(
cursor_.type(), bitmap, hotspot);
cursor_.SetPlatformCursor(platform_cursor);
cursor_.SetPlatformCursor(
ui::CursorFactory::GetInstance()->CreateImageCursor(cursor_.type(),
bitmap, hotspot));
cursor_.set_custom_bitmap(bitmap);
cursor_.set_custom_hotspot(hotspot);
ui::CursorFactory::GetInstance()->UnrefImageCursor(platform_cursor);
}
// If there is a focused surface, update its widget as the views framework

@ -13,9 +13,7 @@ namespace content {
WebCursor::WebCursor() = default;
WebCursor::~WebCursor() {
CleanupPlatformData();
}
WebCursor::~WebCursor() = default;
WebCursor::WebCursor(const ui::Cursor& cursor) {
SetCursor(cursor);

@ -17,7 +17,6 @@
#if defined(USE_AURA)
#include "base/optional.h"
#include "ui/base/cursor/cursor.h"
#endif
@ -75,7 +74,6 @@ class CONTENT_EXPORT WebCursor {
#if defined(USE_AURA) || defined(USE_OZONE)
// Only used for custom cursors.
ui::PlatformCursor platform_cursor_ = nullptr;
float device_scale_factor_ = 1.f;
display::Display::Rotation rotation_ = display::Display::ROTATE_0;
#endif

@ -23,11 +23,9 @@ gfx::NativeCursor WebCursor::GetNativeCursor() {
custom_cursor_->set_custom_bitmap(bitmap);
custom_cursor_->set_custom_hotspot(hotspot);
custom_cursor_->set_image_scale_factor(scale);
DCHECK(!platform_cursor_);
platform_cursor_ = ui::CursorFactory::GetInstance()->CreateImageCursor(
ui::mojom::CursorType::kCustom, bitmap, hotspot);
custom_cursor_->SetPlatformCursor(platform_cursor_);
custom_cursor_->SetPlatformCursor(
ui::CursorFactory::GetInstance()->CreateImageCursor(
ui::mojom::CursorType::kCustom, bitmap, hotspot));
}
return *custom_cursor_;
}
@ -64,12 +62,6 @@ float WebCursor::GetCursorScaleFactor(SkBitmap* bitmap) {
void WebCursor::CopyPlatformData(const WebCursor& other) {
custom_cursor_ = other.custom_cursor_;
if (platform_cursor_)
ui::CursorFactory::GetInstance()->UnrefImageCursor(platform_cursor_);
platform_cursor_ = other.platform_cursor_;
if (platform_cursor_)
ui::CursorFactory::GetInstance()->RefImageCursor(platform_cursor_);
device_scale_factor_ = other.device_scale_factor_;
#if defined(USE_OZONE)
maximum_cursor_size_ = other.maximum_cursor_size_;
@ -77,10 +69,6 @@ void WebCursor::CopyPlatformData(const WebCursor& other) {
}
void WebCursor::CleanupPlatformData() {
if (platform_cursor_) {
ui::CursorFactory::GetInstance()->UnrefImageCursor(platform_cursor_);
platform_cursor_ = nullptr;
}
custom_cursor_.reset();
}

@ -30,8 +30,6 @@ void WebCursor::SetDisplayInfo(const display::Display& display) {
if (maximum_cursor_size_.width() == 0 || maximum_cursor_size_.height() == 0)
maximum_cursor_size_ = gfx::Size(kDefaultMaxSize, kDefaultMaxSize);
CleanupPlatformData();
// It is not necessary to recreate platform_cursor_ yet, since it will be
// recreated on demand when GetNativeCursor is called.
}
float WebCursor::GetCursorScaleFactor(SkBitmap* bitmap) {

@ -211,7 +211,7 @@ void ScaleCursor(float scale, int hotspot_x, int hotspot_y) {
webcursor.SetDisplayInfo(display);
HCURSOR windows_cursor_handle =
static_cast<ui::WinCursor*>(webcursor.GetNativeCursor().platform())
ui::WinCursor::FromPlatformCursor(webcursor.GetNativeCursor().platform())
->hcursor();
EXPECT_NE(nullptr, windows_cursor_handle);
ICONINFO windows_icon_info;

@ -14,6 +14,7 @@ component("cursor_base") {
"cursor_factory.cc",
"cursor_factory.h",
"cursor_size.h",
"platform_cursor.h",
]
defines = [ "IS_UI_BASE_CURSOR_BASE_IMPL" ]
public_deps = [
@ -23,10 +24,6 @@ component("cursor_base") {
"//ui/gfx/geometry",
]
deps = [ "//ui/gfx:geometry_skia" ]
if (use_aura) {
sources += [ "cursor_aura.cc" ]
}
}
component("theme_manager") {

@ -13,39 +13,14 @@ Cursor::Cursor() = default;
Cursor::Cursor(mojom::CursorType type) : type_(type) {}
Cursor::Cursor(const Cursor& cursor)
: type_(cursor.type_),
platform_cursor_(cursor.platform_cursor_),
image_scale_factor_(cursor.image_scale_factor_) {
if (type_ == mojom::CursorType::kCustom) {
custom_hotspot_ = cursor.custom_hotspot_;
custom_bitmap_ = cursor.custom_bitmap_;
RefCustomCursor();
}
}
Cursor::Cursor(const Cursor& cursor) = default;
Cursor::~Cursor() {
if (type_ == mojom::CursorType::kCustom)
UnrefCustomCursor();
}
Cursor::~Cursor() = default;
void Cursor::SetPlatformCursor(const PlatformCursor& platform) {
if (type_ == mojom::CursorType::kCustom)
UnrefCustomCursor();
platform_cursor_ = platform;
if (type_ == mojom::CursorType::kCustom)
RefCustomCursor();
void Cursor::SetPlatformCursor(scoped_refptr<PlatformCursor> platform_cursor) {
platform_cursor_ = platform_cursor;
}
#if !defined(USE_AURA)
void Cursor::RefCustomCursor() {
NOTIMPLEMENTED();
}
void Cursor::UnrefCustomCursor() {
NOTIMPLEMENTED();
}
#endif
bool Cursor::operator==(const Cursor& cursor) const {
return type_ == cursor.type_ && platform_cursor_ == cursor.platform_cursor_ &&
image_scale_factor_ == cursor.image_scale_factor_ &&
@ -54,19 +29,4 @@ bool Cursor::operator==(const Cursor& cursor) const {
gfx::BitmapsAreEqual(custom_bitmap_, cursor.custom_bitmap_)));
}
void Cursor::operator=(const Cursor& cursor) {
if (*this == cursor)
return;
if (type_ == mojom::CursorType::kCustom)
UnrefCustomCursor();
type_ = cursor.type_;
platform_cursor_ = cursor.platform_cursor_;
if (type_ == mojom::CursorType::kCustom) {
RefCustomCursor();
custom_hotspot_ = cursor.custom_hotspot_;
custom_bitmap_ = cursor.custom_bitmap_;
}
image_scale_factor_ = cursor.image_scale_factor_;
}
} // namespace ui

@ -6,42 +6,26 @@
#define UI_BASE_CURSOR_CURSOR_H_
#include "base/component_export.h"
#include "build/build_config.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/gfx/geometry/point.h"
#if defined(OS_WIN)
#include "base/win/windows_types.h"
#endif
namespace ui {
// NOTE: On Ozone platforms, the type is chosen at runtime, and is either
// X11Cursor* or BitmapCursorOzone*.
// On Windows, it's WinCursor*.
using PlatformCursor = void*;
// Ref-counted cursor that supports both default and custom cursors.
class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) Cursor {
public:
Cursor();
// Implicit constructor.
Cursor(mojom::CursorType type);
// Allow copy.
Cursor(const Cursor& cursor);
~Cursor();
void SetPlatformCursor(const PlatformCursor& platform);
void RefCustomCursor();
void UnrefCustomCursor();
void SetPlatformCursor(scoped_refptr<PlatformCursor> platform_cursor);
mojom::CursorType type() const { return type_; }
PlatformCursor platform() const { return platform_cursor_; }
scoped_refptr<PlatformCursor> platform() const { return platform_cursor_; }
float image_scale_factor() const { return image_scale_factor_; }
void set_image_scale_factor(float scale) { image_scale_factor_ = scale; }
@ -60,14 +44,12 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) Cursor {
bool operator==(mojom::CursorType type) const { return type_ == type; }
bool operator!=(mojom::CursorType type) const { return type_ != type; }
void operator=(const Cursor& cursor);
private:
// The basic cursor type.
mojom::CursorType type_ = mojom::CursorType::kNull;
// The native platform cursor.
PlatformCursor platform_cursor_ = 0;
scoped_refptr<PlatformCursor> platform_cursor_;
// The scale factor for the cursor bitmap.
float image_scale_factor_ = 1.0f;

@ -1,21 +0,0 @@
// Copyright 2014 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.
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/cursor_factory.h"
namespace ui {
void Cursor::RefCustomCursor() {
if (platform_cursor_)
CursorFactory::GetInstance()->RefImageCursor(platform_cursor_);
}
void Cursor::UnrefCustomCursor() {
if (platform_cursor_)
CursorFactory::GetInstance()->UnrefImageCursor(platform_cursor_);
}
} // namespace ui

@ -8,8 +8,10 @@
#include "base/check.h"
#include "base/check_op.h"
#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/cursor/platform_cursor.h"
namespace ui {
@ -34,33 +36,27 @@ CursorFactory* CursorFactory::GetInstance() {
return g_instance;
}
PlatformCursor CursorFactory::GetDefaultCursor(mojom::CursorType type) {
scoped_refptr<PlatformCursor> CursorFactory::GetDefaultCursor(
mojom::CursorType type) {
NOTIMPLEMENTED();
return nullptr;
}
PlatformCursor CursorFactory::CreateImageCursor(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) {
scoped_refptr<PlatformCursor> CursorFactory::CreateImageCursor(
mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) {
NOTIMPLEMENTED();
return 0;
return nullptr;
}
PlatformCursor CursorFactory::CreateAnimatedCursor(
scoped_refptr<PlatformCursor> CursorFactory::CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot,
base::TimeDelta frame_delay) {
NOTIMPLEMENTED();
return 0;
}
void CursorFactory::RefImageCursor(PlatformCursor cursor) {
NOTIMPLEMENTED();
}
void CursorFactory::UnrefImageCursor(PlatformCursor cursor) {
NOTIMPLEMENTED();
return nullptr;
}
void CursorFactory::ObserveThemeChanges() {

@ -14,6 +14,9 @@
class SkBitmap;
template <class T>
class scoped_refptr;
namespace base {
class TimeDelta;
}
@ -23,7 +26,7 @@ class Point;
}
namespace ui {
using PlatformCursor = void*;
class PlatformCursor;
class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactory {
public:
@ -33,37 +36,26 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactory {
// Returns the thread-local instance.
static CursorFactory* GetInstance();
// Return the default cursor of the specified type. The types are listed in
// ui/base/cursor/cursor.h. Default cursors are managed by the implementation
// and must live indefinitely; there's no way to know when to free them.
// When a default cursor is not available, nullptr is returned.
virtual PlatformCursor GetDefaultCursor(mojom::CursorType type);
// Return the default cursor of the specified type. When a default cursor is
// not available, nullptr is returned.
virtual scoped_refptr<PlatformCursor> GetDefaultCursor(
mojom::CursorType type);
// Return an image cursor for the specified |type| with a |bitmap| and
// |hotspot|. Image cursors are referenced counted and have an initial
// refcount of 1. Therefore, each CreateImageCursor call must be matched with
// a call to UnrefImageCursor.
virtual PlatformCursor CreateImageCursor(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot);
// Return an image cursor for the specified `type` with a `bitmap` and
// `hotspot`.
virtual scoped_refptr<PlatformCursor> CreateImageCursor(
mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot);
// Return a animated cursor from the specified image & hotspot. Animated
// cursors are referenced counted and have an initial refcount of 1.
// Therefore, each CreateAnimatedCursor call must be matched with a call to
// UnrefImageCursor.
// |frame_delay| is the delay between frames.
virtual PlatformCursor CreateAnimatedCursor(
// Return a animated cursor from the specified `bitmaps` and `hotspot`.
// `frame_delay` is the delay between frames.
virtual scoped_refptr<PlatformCursor> CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot,
base::TimeDelta frame_delay);
// Increment platform image cursor refcount.
virtual void RefImageCursor(PlatformCursor cursor);
// Decrement platform image cursor refcount.
virtual void UnrefImageCursor(PlatformCursor cursor);
// Called after CursorThemeManager is initialized, to be able to track
// cursor theme and size changes.
virtual void ObserveThemeChanges();

@ -8,6 +8,7 @@
#include <vector>
#include "base/check.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/cursor_factory.h"
@ -15,6 +16,7 @@
#include "ui/base/cursor/cursor_util.h"
#include "ui/base/cursor/cursors_aura.h"
#include "ui/base/cursor/mojom/cursor_type.mojom.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/gfx/geometry/point.h"
namespace ui {
@ -38,8 +40,6 @@ CursorLoader::~CursorLoader() {
}
void CursorLoader::UnloadCursors() {
for (const auto& image_cursor : image_cursors_)
factory_->UnrefImageCursor(image_cursor.second);
image_cursors_.clear();
}
@ -91,7 +91,8 @@ void CursorLoader::LoadImageCursor(mojom::CursorType type,
}
}
PlatformCursor CursorLoader::CursorFromType(mojom::CursorType type) {
scoped_refptr<PlatformCursor> CursorLoader::CursorFromType(
mojom::CursorType type) {
// An image cursor is loaded for this type.
if (image_cursors_.count(type))
return image_cursors_[type];
@ -99,7 +100,7 @@ PlatformCursor CursorLoader::CursorFromType(mojom::CursorType type) {
// Check if there's a default platform cursor available.
// For the none cursor, we also need to use the platform factory to take
// into account the different ways of creating an invisible cursor.
PlatformCursor cursor;
scoped_refptr<PlatformCursor> cursor;
if (use_platform_cursors_ || type == mojom::CursorType::kNone) {
cursor = factory_->GetDefaultCursor(type);
if (cursor)
@ -112,14 +113,14 @@ PlatformCursor CursorLoader::CursorFromType(mojom::CursorType type) {
cursor = LoadCursorFromAsset(type);
if (!cursor && type != mojom::CursorType::kPointer) {
cursor = CursorFromType(mojom::CursorType::kPointer);
factory_->RefImageCursor(cursor);
image_cursors_[type] = cursor;
}
DCHECK(cursor) << "Failed to load a bitmap for the pointer cursor.";
return cursor;
}
PlatformCursor CursorLoader::LoadCursorFromAsset(mojom::CursorType type) {
scoped_refptr<PlatformCursor> CursorLoader::LoadCursorFromAsset(
mojom::CursorType type) {
int resource_id;
gfx::Point hotspot;
if (GetCursorDataFor(size(), type, scale(), &resource_id, &hotspot)) {

@ -9,6 +9,7 @@
#include <memory>
#include "base/component_export.h"
#include "base/memory/scoped_refptr.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/cursor_size.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
@ -20,6 +21,7 @@ class Point;
namespace ui {
class CursorFactory;
class PlatformCursor;
class COMPONENT_EXPORT(UI_BASE_CURSOR) CursorLoader {
public:
@ -51,15 +53,15 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) CursorLoader {
void LoadImageCursor(mojom::CursorType id,
int resource_id,
const gfx::Point& hot);
PlatformCursor CursorFromType(mojom::CursorType type);
PlatformCursor LoadCursorFromAsset(mojom::CursorType type);
scoped_refptr<PlatformCursor> CursorFromType(mojom::CursorType type);
scoped_refptr<PlatformCursor> LoadCursorFromAsset(mojom::CursorType type);
// Whether to use cursors provided by the underlying platform (e.g. X11
// cursors). If false or in the case of a failure, Chromium assets will be
// used instead.
const bool use_platform_cursors_;
std::map<mojom::CursorType, PlatformCursor> image_cursors_;
std::map<mojom::CursorType, scoped_refptr<PlatformCursor>> image_cursors_;
CursorFactory* factory_ = nullptr;
// The current scale of the mouse cursor icon.

@ -4,10 +4,12 @@
#include "ui/base/cursor/cursor_loader.h"
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/cursor/platform_cursor.h"
#if defined(OS_WIN)
#include "ui/base/cursor/win/win_cursor.h"
@ -25,12 +27,13 @@
#endif
namespace ui {
namespace {
PlatformCursor LoadInvisibleCursor() {
using mojom::CursorType;
scoped_refptr<PlatformCursor> LoadInvisibleCursor() {
CursorLoader cursor_loader;
Cursor cursor(mojom::CursorType::kNone);
Cursor cursor(CursorType::kNone);
cursor_loader.SetPlatformCursor(&cursor);
return cursor.platform();
}
@ -40,19 +43,20 @@ PlatformCursor LoadInvisibleCursor() {
#if defined(OS_WIN)
TEST(CursorLoaderTest, InvisibleCursor) {
WinCursorFactory cursor_factory;
auto* invisible_cursor = static_cast<WinCursor*>(LoadInvisibleCursor());
auto invisible_cursor = LoadInvisibleCursor();
ASSERT_NE(invisible_cursor, nullptr);
EXPECT_EQ(invisible_cursor->hcursor(), nullptr);
EXPECT_EQ(WinCursor::FromPlatformCursor(invisible_cursor)->hcursor(),
nullptr);
}
#endif
#if defined(USE_OZONE) && !defined(USE_X11)
TEST(CursorLoaderTest, InvisibleCursor) {
BitmapCursorFactoryOzone cursor_factory;
auto* invisible_cursor =
static_cast<BitmapCursorOzone*>(LoadInvisibleCursor());
auto invisible_cursor = LoadInvisibleCursor();
ASSERT_NE(invisible_cursor, nullptr);
EXPECT_EQ(invisible_cursor->type(), mojom::CursorType::kNone);
EXPECT_EQ(BitmapCursorOzone::FromPlatformCursor(invisible_cursor)->type(),
CursorType::kNone);
}
#endif
@ -61,13 +65,10 @@ TEST(CursorLoaderTest, InvisibleCursor) {
X11CursorFactory cursor_factory;
// Building an image cursor with an invalid SkBitmap should return the
// invisible cursor in X11.
auto* invisible_cursor =
auto invisible_cursor =
cursor_factory.CreateImageCursor({}, SkBitmap(), gfx::Point());
ASSERT_NE(invisible_cursor, nullptr);
EXPECT_EQ(invisible_cursor, LoadInvisibleCursor());
// Release our refcount on the cursor
cursor_factory.UnrefImageCursor(invisible_cursor);
}
#endif

@ -333,7 +333,7 @@ SkBitmap GetDefaultBitmap(const Cursor& cursor) {
CursorLoader cursor_loader;
cursor_loader.SetPlatformCursor(&cursor_copy);
return IconUtil::CreateSkBitmapFromHICON(
static_cast<WinCursor*>(cursor_copy.platform())->hcursor());
WinCursor::FromPlatformCursor(cursor_copy.platform())->hcursor());
#else
int resource_id;
gfx::Point hotspot;
@ -354,7 +354,7 @@ gfx::Point GetDefaultHotspot(const Cursor& cursor) {
CursorLoader cursor_loader;
cursor_loader.SetPlatformCursor(&cursor_copy);
return IconUtil::GetHotSpotFromHICON(
static_cast<WinCursor*>(cursor_copy.platform())->hcursor());
WinCursor::FromPlatformCursor(cursor_copy.platform())->hcursor());
#else
int resource_id;
gfx::Point hotspot;

@ -85,16 +85,15 @@ bool UseDefaultCursorForType(mojom::CursorType type) {
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
BitmapCursorOzone* ToBitmapCursorOzone(PlatformCursor cursor) {
return static_cast<BitmapCursorOzone*>(cursor);
}
PlatformCursor ToPlatformCursor(BitmapCursorOzone* cursor) {
return static_cast<PlatformCursor>(cursor);
}
} // namespace
// static
scoped_refptr<BitmapCursorOzone> BitmapCursorOzone::FromPlatformCursor(
scoped_refptr<PlatformCursor> platform_cursor) {
return base::WrapRefCounted(
static_cast<BitmapCursorOzone*>(platform_cursor.get()));
}
BitmapCursorOzone::BitmapCursorOzone(mojom::CursorType type) : type_(type) {}
BitmapCursorOzone::BitmapCursorOzone(mojom::CursorType type,
@ -148,13 +147,7 @@ BitmapCursorFactoryOzone::BitmapCursorFactoryOzone() {}
BitmapCursorFactoryOzone::~BitmapCursorFactoryOzone() {}
// static
scoped_refptr<BitmapCursorOzone> BitmapCursorFactoryOzone::GetBitmapCursor(
PlatformCursor platform_cursor) {
return base::WrapRefCounted(ToBitmapCursorOzone(platform_cursor));
}
PlatformCursor BitmapCursorFactoryOzone::GetDefaultCursor(
scoped_refptr<PlatformCursor> BitmapCursorFactoryOzone::GetDefaultCursor(
mojom::CursorType type) {
if (!default_cursors_.count(type)) {
if (type == mojom::CursorType::kNone
@ -171,37 +164,24 @@ PlatformCursor BitmapCursorFactoryOzone::GetDefaultCursor(
}
}
// Returns owned default cursor for this type.
return default_cursors_[type].get();
return default_cursors_[type];
}
PlatformCursor BitmapCursorFactoryOzone::CreateImageCursor(
scoped_refptr<PlatformCursor> BitmapCursorFactoryOzone::CreateImageCursor(
mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) {
BitmapCursorOzone* cursor = new BitmapCursorOzone(type, bitmap, hotspot);
cursor->AddRef(); // Balanced by UnrefImageCursor.
return ToPlatformCursor(cursor);
return base::MakeRefCounted<BitmapCursorOzone>(type, bitmap, hotspot);
}
PlatformCursor BitmapCursorFactoryOzone::CreateAnimatedCursor(
scoped_refptr<PlatformCursor> BitmapCursorFactoryOzone::CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot,
base::TimeDelta frame_delay) {
DCHECK_LT(0U, bitmaps.size());
auto cursor = base::MakeRefCounted<BitmapCursorOzone>(type, bitmaps, hotspot,
frame_delay);
cursor->AddRef(); // Balanced by UnrefImageCursor.
return ToPlatformCursor(cursor.get());
}
void BitmapCursorFactoryOzone::RefImageCursor(PlatformCursor cursor) {
ToBitmapCursorOzone(cursor)->AddRef();
}
void BitmapCursorFactoryOzone::UnrefImageCursor(PlatformCursor cursor) {
ToBitmapCursorOzone(cursor)->Release();
return base::MakeRefCounted<BitmapCursorOzone>(type, bitmaps, hotspot,
frame_delay);
}
} // namespace ui

@ -10,21 +10,24 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/cursor_factory.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/gfx/geometry/point.h"
namespace ui {
// A cursor that is an SkBitmap combined with a gfx::Point hotspot.
class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorOzone
: public base::RefCounted<BitmapCursorOzone> {
: public PlatformCursor {
public:
static scoped_refptr<BitmapCursorOzone> FromPlatformCursor(
scoped_refptr<PlatformCursor> platform_cursor);
// Creates a cursor that doesn't need backing bitmaps (for example, a
// server-side cursor for Lacros).
explicit BitmapCursorOzone(mojom::CursorType type);
@ -55,8 +58,8 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorOzone
void* platform_data() { return platform_data_; }
private:
friend class base::RefCounted<BitmapCursorOzone>;
~BitmapCursorOzone();
friend class base::RefCounted<PlatformCursor>;
~BitmapCursorOzone() override;
const mojom::CursorType type_;
std::vector<SkBitmap> bitmaps_;
@ -80,21 +83,18 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorFactoryOzone
BitmapCursorFactoryOzone();
~BitmapCursorFactoryOzone() override;
// Convert PlatformCursor to BitmapCursorOzone.
static scoped_refptr<BitmapCursorOzone> GetBitmapCursor(
PlatformCursor platform_cursor);
// CursorFactory:
PlatformCursor GetDefaultCursor(mojom::CursorType type) override;
PlatformCursor CreateImageCursor(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) override;
PlatformCursor CreateAnimatedCursor(mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot,
base::TimeDelta frame_delay) override;
void RefImageCursor(PlatformCursor cursor) override;
void UnrefImageCursor(PlatformCursor cursor) override;
scoped_refptr<PlatformCursor> GetDefaultCursor(
mojom::CursorType type) override;
scoped_refptr<PlatformCursor> CreateImageCursor(
mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) override;
scoped_refptr<PlatformCursor> CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot,
base::TimeDelta frame_delay) override;
private:
std::map<mojom::CursorType, scoped_refptr<BitmapCursorOzone>>

@ -6,8 +6,8 @@
#include "build/chromeos_buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/cursor/platform_cursor.h"
namespace ui {
@ -16,11 +16,12 @@ using mojom::CursorType;
TEST(BitmapCursorFactoryOzoneTest, InvisibleCursor) {
BitmapCursorFactoryOzone cursor_factory;
PlatformCursor cursor = cursor_factory.GetDefaultCursor(CursorType::kNone);
auto cursor = cursor_factory.GetDefaultCursor(CursorType::kNone);
// The invisible cursor should be a BitmapCursorOzone of type kNone, not
// nullptr.
ASSERT_NE(cursor, nullptr);
EXPECT_EQ(static_cast<BitmapCursorOzone*>(cursor)->type(), CursorType::kNone);
EXPECT_EQ(BitmapCursorOzone::FromPlatformCursor(cursor)->type(),
CursorType::kNone);
}
#if BUILDFLAG(IS_CHROMEOS_LACROS)
@ -28,24 +29,25 @@ TEST(BitmapCursorFactoryOzoneTest, LacrosUsesDefaultCursorsForCommonTypes) {
BitmapCursorFactoryOzone factory;
// Verify some common cursor types.
PlatformCursor cursor = factory.GetDefaultCursor(CursorType::kPointer);
auto cursor = factory.GetDefaultCursor(CursorType::kPointer);
EXPECT_NE(cursor, nullptr);
EXPECT_EQ(static_cast<BitmapCursorOzone*>(cursor)->type(),
EXPECT_EQ(BitmapCursorOzone::FromPlatformCursor(cursor)->type(),
CursorType::kPointer);
cursor = factory.GetDefaultCursor(CursorType::kHand);
EXPECT_NE(cursor, nullptr);
EXPECT_EQ(static_cast<BitmapCursorOzone*>(cursor)->type(), CursorType::kHand);
EXPECT_EQ(BitmapCursorOzone::FromPlatformCursor(cursor)->type(),
CursorType::kHand);
cursor = factory.GetDefaultCursor(CursorType::kIBeam);
EXPECT_NE(cursor, nullptr);
EXPECT_EQ(static_cast<BitmapCursorOzone*>(cursor)->type(),
EXPECT_EQ(BitmapCursorOzone::FromPlatformCursor(cursor)->type(),
CursorType::kIBeam);
}
TEST(BitmapCursorFactoryOzoneTest, LacrosCustomCursor) {
BitmapCursorFactoryOzone factory;
PlatformCursor cursor = factory.GetDefaultCursor(CursorType::kCustom);
auto cursor = factory.GetDefaultCursor(CursorType::kCustom);
// Custom cursors don't have a default platform cursor.
EXPECT_EQ(cursor, nullptr);
}

@ -0,0 +1,36 @@
// Copyright 2021 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_BASE_CURSOR_PLATFORM_CURSOR_H_
#define UI_BASE_CURSOR_PLATFORM_CURSOR_H_
#include "base/component_export.h"
#include "base/memory/ref_counted.h"
namespace ui {
// Ref-counted base class for platform-specific cursors.
//
// Sub-classes of PlatformCursor are expected to wrap platform-specific cursor
// resources (e.g. HCURSOR on Windows). Those resources also have
// platform-specific deletion methods that must only be called once the last
// cursor is destroyed, thus requiring a ref-counted type.
// While default cursors (all other than kCustom in
// ui/base/cursor/cursor_type.mojom) are used often during any Chrome session
// and could perhaps be kept alive for the duration of the program, custom
// cursors might incur in high memory usage. Because of this, all types of
// cursors are expected to be ref-counted.
class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) PlatformCursor
: public base::RefCounted<PlatformCursor> {
public:
REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
protected:
friend class base::RefCounted<PlatformCursor>;
virtual ~PlatformCursor() = default;
};
} // namespace ui
#endif // UI_BASE_CURSOR_PLATFORM_CURSOR_H_

@ -6,14 +6,24 @@
#include <windows.h>
#include "base/memory/scoped_refptr.h"
namespace ui {
WinCursor::WinCursor(HCURSOR hcursor) {
hcursor_ = hcursor;
// static
scoped_refptr<WinCursor> WinCursor::FromPlatformCursor(
scoped_refptr<PlatformCursor> platform_cursor) {
return base::WrapRefCounted(static_cast<WinCursor*>(platform_cursor.get()));
}
WinCursor::WinCursor(HCURSOR hcursor, bool should_destroy)
: should_destroy_(should_destroy), hcursor_(hcursor) {}
WinCursor::~WinCursor() {
DestroyIcon(hcursor_);
// DestroyIcon shouldn't be used to destroy a shared icon:
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-destroyicon#remarks
if (should_destroy_)
DestroyIcon(hcursor_);
}
} // namespace ui

@ -6,17 +6,22 @@
#define UI_BASE_CURSOR_WIN_WIN_CURSOR_H_
#include "base/component_export.h"
#include "base/memory/ref_counted.h"
#include "base/win/windows_types.h"
#include "ui/base/cursor/platform_cursor.h"
template <class T>
class scoped_refptr;
namespace ui {
// Ref counted class to hold a Windows cursor, i.e. an HCURSOR. Clears the
// Ref counted class to hold a Windows cursor, i.e. an HCURSOR. Clears the
// resources on destruction.
class COMPONENT_EXPORT(UI_BASE_CURSOR) WinCursor
: public base::RefCounted<WinCursor> {
class COMPONENT_EXPORT(UI_BASE_CURSOR) WinCursor : public PlatformCursor {
public:
explicit WinCursor(HCURSOR hcursor = nullptr);
static scoped_refptr<WinCursor> FromPlatformCursor(
scoped_refptr<PlatformCursor> platform_cursor);
explicit WinCursor(HCURSOR hcursor = nullptr, bool should_destroy = false);
WinCursor(const WinCursor&) = delete;
WinCursor& operator=(const WinCursor&) = delete;
@ -24,9 +29,10 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) WinCursor
private:
friend class base::RefCounted<WinCursor>;
~WinCursor() override;
~WinCursor();
// Release the cursor on deletion. To be used by custom image cursors.
bool should_destroy_;
HCURSOR hcursor_;
};

@ -12,8 +12,8 @@
#include "base/notreached.h"
#include "base/win/scoped_gdi_object.h"
#include "base/win/windows_types.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/resource/resource_bundle_win.h"
#include "ui/gfx/icon_util.h"
#include "ui/resources/grit/ui_unscaled_resources.h"
@ -21,14 +21,6 @@
namespace ui {
namespace {
WinCursor* ToWinCursor(PlatformCursor cursor) {
return static_cast<WinCursor*>(cursor);
}
PlatformCursor ToPlatformCursor(WinCursor* cursor) {
return static_cast<PlatformCursor>(cursor);
}
const wchar_t* GetCursorId(mojom::CursorType type) {
switch (type) {
case mojom::CursorType::kNull:
@ -135,7 +127,8 @@ WinCursorFactory::WinCursorFactory() = default;
WinCursorFactory::~WinCursorFactory() = default;
PlatformCursor WinCursorFactory::GetDefaultCursor(mojom::CursorType type) {
scoped_refptr<PlatformCursor> WinCursorFactory::GetDefaultCursor(
mojom::CursorType type) {
if (!default_cursors_.count(type)) {
// Using a dark 1x1 bit bmp for the kNone cursor may still cause DWM to do
// composition work unnecessarily. Better to totally remove it from the
@ -153,25 +146,16 @@ PlatformCursor WinCursorFactory::GetDefaultCursor(mojom::CursorType type) {
default_cursors_[type] = base::MakeRefCounted<WinCursor>(hcursor);
}
auto cursor = default_cursors_[type];
return ToPlatformCursor(cursor.get());
return default_cursors_[type];
}
PlatformCursor WinCursorFactory::CreateImageCursor(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) {
auto cursor = base::MakeRefCounted<WinCursor>(
IconUtil::CreateCursorFromSkBitmap(bitmap, hotspot).release());
cursor->AddRef();
return ToPlatformCursor(cursor.get());
}
void WinCursorFactory::RefImageCursor(PlatformCursor cursor) {
ToWinCursor(cursor)->AddRef();
}
void WinCursorFactory::UnrefImageCursor(PlatformCursor cursor) {
ToWinCursor(cursor)->Release();
scoped_refptr<PlatformCursor> WinCursorFactory::CreateImageCursor(
mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) {
return base::MakeRefCounted<WinCursor>(
IconUtil::CreateCursorFromSkBitmap(bitmap, hotspot).release(),
/*should_destroy=*/true);
}
} // namespace ui

@ -29,12 +29,12 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) WinCursorFactory : public CursorFactory {
~WinCursorFactory() override;
// CursorFactory:
PlatformCursor GetDefaultCursor(mojom::CursorType type) override;
PlatformCursor CreateImageCursor(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) override;
void RefImageCursor(PlatformCursor cursor) override;
void UnrefImageCursor(PlatformCursor cursor) override;
scoped_refptr<PlatformCursor> GetDefaultCursor(
mojom::CursorType type) override;
scoped_refptr<PlatformCursor> CreateImageCursor(
mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) override;
private:
std::map<mojom::CursorType, scoped_refptr<WinCursor>> default_cursors_;

@ -68,7 +68,7 @@ component("x") {
defines = [ "IS_UI_BASE_X_IMPL" ]
public_deps = []
public_deps = [ "//ui/base/cursor:cursor_base" ]
deps = [
"//base",
"//base:i18n",
@ -79,7 +79,6 @@ component("x") {
"//ui/base:features",
"//ui/base/clipboard:clipboard_types",
"//ui/base/clipboard:file_info",
"//ui/base/cursor:cursor_base",
"//ui/base/cursor:theme_manager",
"//ui/base/cursor/mojom:cursor_type",
"//ui/display/util",

@ -4,6 +4,7 @@
#include "ui/base/x/x11_cursor.h"
#include "base/memory/scoped_refptr.h"
#include "ui/base/x/x11_cursor_loader.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/future.h"
@ -11,6 +12,12 @@
namespace ui {
// static
scoped_refptr<X11Cursor> X11Cursor::FromPlatformCursor(
scoped_refptr<PlatformCursor> platform_cursor) {
return base::WrapRefCounted(static_cast<X11Cursor*>(platform_cursor.get()));
}
X11Cursor::X11Cursor() = default;
X11Cursor::X11Cursor(x11::Cursor cursor) : loaded_(true), xcursor_(cursor) {}

@ -9,20 +9,23 @@
#include "base/callback.h"
#include "base/component_export.h"
#include "base/memory/ref_counted.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/gfx/x/xproto.h"
template <class T>
class scoped_refptr;
namespace ui {
// Ref counted class to hold an X11 cursor resource. Clears the X11 resources
// on destruction
class COMPONENT_EXPORT(UI_BASE_X) X11Cursor
: public base::RefCounted<X11Cursor> {
class COMPONENT_EXPORT(UI_BASE_X) X11Cursor : public PlatformCursor {
public:
REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
using Callback = base::OnceCallback<void(x11::Cursor)>;
static scoped_refptr<X11Cursor> FromPlatformCursor(
scoped_refptr<PlatformCursor> platform_cursor);
X11Cursor();
explicit X11Cursor(x11::Cursor cursor);
@ -35,16 +38,16 @@ class COMPONENT_EXPORT(UI_BASE_X) X11Cursor
x11::Cursor xcursor() const { return xcursor_; }
private:
friend class base::RefCounted<X11Cursor>;
friend class base::RefCounted<PlatformCursor>;
friend class XCursorLoader;
~X11Cursor() override;
void SetCursor(x11::Cursor cursor);
// This cannot be named Release() since it conflicts with base::RefCounted.
x11::Cursor ReleaseCursor();
~X11Cursor();
bool loaded_ = false;
x11::Cursor xcursor_ = x11::Cursor::None;

@ -6,6 +6,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/x/x11_cursor.h"
#include "ui/base/x/x11_cursor_loader.h"
#include "ui/base/x/x11_util.h"
@ -16,14 +17,6 @@ namespace ui {
namespace {
X11Cursor* ToX11Cursor(PlatformCursor cursor) {
return static_cast<X11Cursor*>(cursor);
}
PlatformCursor ToPlatformCursor(X11Cursor* cursor) {
return static_cast<PlatformCursor>(cursor);
}
scoped_refptr<X11Cursor> CreateInvisibleCursor(XCursorLoader* cursor_loader) {
SkBitmap bitmap;
bitmap.allocN32Pixels(1, 1);
@ -37,28 +30,20 @@ X11CursorFactory::X11CursorFactory()
X11CursorFactory::~X11CursorFactory() = default;
PlatformCursor X11CursorFactory::CreateImageCursor(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) {
scoped_refptr<PlatformCursor> X11CursorFactory::CreateImageCursor(
mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) {
// 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
// image. Return invisible cursor here instead.
if (bitmap.drawsNothing()) {
// The result of `CreateImageCursor()` is owned by the caller, and will be
// Unref()ed by code far away. (Usually in web_cursor.cc in content, among
// others.) If we don't manually add another reference before we cast this
// to a void*, we can end up with the cursor being freed out from under us.
auto* invisible_cursor = GetDefaultCursor(mojom::CursorType::kNone);
RefImageCursor(invisible_cursor);
return invisible_cursor;
}
if (bitmap.drawsNothing())
return GetDefaultCursor(mojom::CursorType::kNone);
auto cursor = cursor_loader_->CreateCursor(bitmap, hotspot);
cursor->AddRef();
return ToPlatformCursor(cursor.get());
return cursor_loader_->CreateCursor(bitmap, hotspot);
}
PlatformCursor X11CursorFactory::CreateAnimatedCursor(
scoped_refptr<PlatformCursor> X11CursorFactory::CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot,
@ -67,17 +52,7 @@ PlatformCursor X11CursorFactory::CreateAnimatedCursor(
images.reserve(bitmaps.size());
for (const auto& bitmap : bitmaps)
images.push_back(XCursorLoader::Image{bitmap, hotspot, frame_delay});
auto cursor = cursor_loader_->CreateCursor(images);
cursor->AddRef();
return ToPlatformCursor(cursor.get());
}
void X11CursorFactory::RefImageCursor(PlatformCursor cursor) {
ToX11Cursor(cursor)->AddRef();
}
void X11CursorFactory::UnrefImageCursor(PlatformCursor cursor) {
ToX11Cursor(cursor)->Release();
return cursor_loader_->CreateCursor(images);
}
void X11CursorFactory::ObserveThemeChanges() {
@ -95,7 +70,8 @@ void X11CursorFactory::OnCursorThemeSizeChanged(int cursor_theme_size) {
ClearThemeCursors();
}
PlatformCursor X11CursorFactory::GetDefaultCursor(mojom::CursorType type) {
scoped_refptr<PlatformCursor> X11CursorFactory::GetDefaultCursor(
mojom::CursorType type) {
if (!default_cursors_.count(type)) {
// Try to load a predefined X11 cursor.
default_cursors_[type] =
@ -104,8 +80,7 @@ PlatformCursor X11CursorFactory::GetDefaultCursor(mojom::CursorType type) {
: cursor_loader_->LoadCursor(CursorNamesFromType(type));
}
// Returns owned default cursor for this type.
return default_cursors_[type].get();
return default_cursors_[type];
}
void X11CursorFactory::ClearThemeCursors() {

@ -21,7 +21,7 @@ namespace ui {
class X11Cursor;
class XCursorLoader;
// CursorFactoryOzone implementation for X11 cursors.
// CursorFactory implementation for X11 cursors.
class COMPONENT_EXPORT(UI_BASE_X) X11CursorFactory
: public CursorFactory,
public CursorThemeManagerObserver {
@ -32,16 +32,17 @@ class COMPONENT_EXPORT(UI_BASE_X) X11CursorFactory
~X11CursorFactory() override;
// CursorFactory:
PlatformCursor GetDefaultCursor(mojom::CursorType type) override;
PlatformCursor CreateImageCursor(mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) override;
PlatformCursor CreateAnimatedCursor(mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot,
base::TimeDelta frame_delay) override;
void RefImageCursor(PlatformCursor cursor) override;
void UnrefImageCursor(PlatformCursor cursor) override;
scoped_refptr<PlatformCursor> GetDefaultCursor(
mojom::CursorType type) override;
scoped_refptr<PlatformCursor> CreateImageCursor(
mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) override;
scoped_refptr<PlatformCursor> CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot,
base::TimeDelta frame_delay) override;
void ObserveThemeChanges() override;
private:

@ -6,28 +6,24 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/cursor/mojom/cursor_type.mojom.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/x/x11_cursor.h"
#include "ui/gfx/geometry/point.h"
namespace ui {
TEST(X11CursorFactoryTest, InvisibleRefcount) {
using mojom::CursorType;
TEST(X11CursorFactoryTest, InvisibleCursor) {
X11CursorFactory factory;
// Building an image cursor with an invalid SkBitmap should return the
// invisible cursor in X11. The invisible cursor instance should have more
// than a single reference since the factory should hold a reference and
// CreateImageCursor should return an incremented refcount.
auto* invisible_cursor = static_cast<X11Cursor*>(
factory.CreateImageCursor({}, SkBitmap(), gfx::Point()));
// invisible cursor in X11.
auto invisible_cursor =
factory.CreateImageCursor({}, SkBitmap(), gfx::Point());
ASSERT_NE(invisible_cursor, nullptr);
ASSERT_FALSE(invisible_cursor->HasOneRef());
// Release our refcount on the cursor
factory.UnrefImageCursor(invisible_cursor);
// The invisible cursor should still exist.
EXPECT_TRUE(invisible_cursor->HasOneRef());
EXPECT_EQ(invisible_cursor, factory.GetDefaultCursor(CursorType::kNone));
}
} // namespace ui

@ -12,6 +12,7 @@
#include "base/trace_event/trace_event.h"
#include "build/chromeos_buildflags.h"
#include "ui/base/cursor/mojom/cursor_type.mojom.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/ozone/platform/drm/host/drm_window_host.h"
#include "ui/ozone/platform/drm/host/drm_window_host_manager.h"
@ -75,21 +76,18 @@ gfx::Point DrmCursor::GetBitmapLocationLocked() {
}
void DrmCursor::SetCursor(gfx::AcceleratedWidget window,
PlatformCursor platform_cursor) {
scoped_refptr<BitmapCursorOzone> platform_cursor) {
TRACE_EVENT0("drmcursor", "DrmCursor::SetCursor");
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_NE(window, gfx::kNullAcceleratedWidget);
DCHECK(platform_cursor);
scoped_refptr<BitmapCursorOzone> bitmap =
BitmapCursorFactoryOzone::GetBitmapCursor(platform_cursor);
base::AutoLock lock(lock_);
if (window_ != window || bitmap_ == bitmap)
if (window_ != window || bitmap_ == platform_cursor)
return;
bitmap_ = bitmap;
bitmap_ = platform_cursor;
SendCursorShowLocked();
}

@ -8,9 +8,9 @@
#include <memory>
#include <vector>
#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
#include "ui/gfx/geometry/rect.h"
@ -53,8 +53,9 @@ class DrmCursor : public CursorDelegateEvdev {
void SetDrmCursorProxy(std::unique_ptr<DrmCursorProxy> proxy);
void ResetDrmCursorProxy();
// Change the cursor over the specifed window.
void SetCursor(gfx::AcceleratedWidget window, PlatformCursor platform_cursor);
// Change the cursor over the specified window.
void SetCursor(gfx::AcceleratedWidget window,
scoped_refptr<BitmapCursorOzone> platform_cursor);
// Handle window lifecycle.
void OnWindowAdded(gfx::AcceleratedWidget window,

@ -5,6 +5,9 @@
#include "ui/ozone/platform/drm/host/drm_window_host.h"
#include "base/bind.h"
#include "base/memory/scoped_refptr.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/display/display.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/events/event.h"
@ -125,8 +128,8 @@ bool DrmWindowHost::ShouldUseNativeFrame() const {
return false;
}
void DrmWindowHost::SetCursor(PlatformCursor cursor) {
cursor_->SetCursor(widget_, cursor);
void DrmWindowHost::SetCursor(scoped_refptr<PlatformCursor> cursor) {
cursor_->SetCursor(widget_, BitmapCursorOzone::FromPlatformCursor(cursor));
}
void DrmWindowHost::MoveCursorTo(const gfx::Point& location) {

@ -76,7 +76,7 @@ class DrmWindowHost : public PlatformWindow,
void Deactivate() override;
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
void SetCursor(PlatformCursor cursor) override;
void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
void MoveCursorTo(const gfx::Point& location) override;
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;

@ -14,6 +14,8 @@
#include "base/fuchsia/fuchsia_logging.h"
#include "base/fuchsia/process_context.h"
#include "base/memory/scoped_refptr.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
@ -195,7 +197,7 @@ bool ScenicWindow::ShouldUseNativeFrame() const {
return false;
}
void ScenicWindow::SetCursor(PlatformCursor cursor) {
void ScenicWindow::SetCursor(scoped_refptr<PlatformCursor> cursor) {
NOTIMPLEMENTED_LOG_ONCE();
}

@ -81,7 +81,7 @@ class COMPONENT_EXPORT(OZONE) ScenicWindow : public PlatformWindow,
void Deactivate() override;
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
void SetCursor(PlatformCursor cursor) override;
void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
void MoveCursorTo(const gfx::Point& location) override;
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;

@ -11,6 +11,7 @@
#include "base/task/thread_pool.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/task_runner_util.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_shm.h"
@ -48,7 +49,8 @@ void WaylandCursorFactory::ObserveThemeChanges() {
cursor_theme_observer_.Observe(cursor_theme_manager);
}
PlatformCursor WaylandCursorFactory::GetDefaultCursor(mojom::CursorType type) {
scoped_refptr<PlatformCursor> WaylandCursorFactory::GetDefaultCursor(
mojom::CursorType type) {
if (current_theme_->cache.count(type) == 0) {
for (const std::string& name : CursorNamesFromType(type)) {
wl_cursor* cursor = GetCursorFromTheme(name);
@ -68,7 +70,7 @@ PlatformCursor WaylandCursorFactory::GetDefaultCursor(mojom::CursorType type) {
if (current_theme_->cache[type].get() == nullptr)
return BitmapCursorFactoryOzone::GetDefaultCursor(type);
return static_cast<PlatformCursor>(current_theme_->cache[type].get());
return current_theme_->cache[type];
}
void WaylandCursorFactory::SetDeviceScaleFactor(float scale) {

@ -36,7 +36,8 @@ class WaylandCursorFactory : public BitmapCursorFactoryOzone,
void ObserveThemeChanges() override;
// CursorFactory:
PlatformCursor GetDefaultCursor(mojom::CursorType type) override;
scoped_refptr<PlatformCursor> GetDefaultCursor(
mojom::CursorType type) override;
void SetDeviceScaleFactor(float scale) override;
protected:

@ -8,6 +8,9 @@
#include "base/containers/flat_map.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_refptr.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/ozone/platform/wayland/test/wayland_test.h"
namespace ui {
@ -85,7 +88,7 @@ TEST_P(WaylandCursorFactoryTest, RetainOldThemeUntilNewBufferIsAttached) {
// that theme.
{
auto* const current_theme = cursor_factory_->current_theme_.get();
auto* const cursor =
auto const cursor =
cursor_factory_->GetDefaultCursor(mojom::CursorType::kPointer);
EXPECT_NE(cursor, nullptr);
EXPECT_GT(cursor_factory_->current_theme_->cache.size(), 0U);
@ -105,19 +108,19 @@ TEST_P(WaylandCursorFactoryTest, RetainOldThemeUntilNewBufferIsAttached) {
EXPECT_EQ(cursor_factory_->unloaded_theme_.get(), current_theme);
cursor_factory_->OnCursorBufferAttached(static_cast<wl_cursor*>(
static_cast<BitmapCursorOzone*>(cursor)->platform_data()));
BitmapCursorOzone::FromPlatformCursor(cursor)->platform_data()));
EXPECT_EQ(cursor_factory_->unloaded_theme_.get(), current_theme);
}
// Finally, tell the factory that we have attached a buffer from the current
// theme. This time the old theme held since a while ago should be freed.
{
auto* const cursor =
auto const cursor =
cursor_factory_->GetDefaultCursor(mojom::CursorType::kPointer);
EXPECT_NE(cursor, nullptr);
cursor_factory_->OnCursorBufferAttached(static_cast<wl_cursor*>(
static_cast<BitmapCursorOzone*>(cursor)->platform_data()));
BitmapCursorOzone::FromPlatformCursor(cursor)->platform_data()));
EXPECT_EQ(cursor_factory_->unloaded_theme_.get(), nullptr);
}

@ -8,10 +8,12 @@
#include <cmath>
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "testing/gmock/include/gmock/gmock.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/platform_cursor.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/events/event.h"
#include "ui/ozone/platform/wayland/host/wayland_cursor.h"
@ -275,10 +277,8 @@ TEST_P(WaylandPointerTest, SetBitmapOnPointerFocus) {
dummy_cursor.allocPixels(info, 10 * 4);
BitmapCursorFactoryOzone cursor_factory;
PlatformCursor cursor = cursor_factory.CreateImageCursor(
auto cursor = cursor_factory.CreateImageCursor(
mojom::CursorType::kCustom, dummy_cursor, gfx::Point(5, 8));
scoped_refptr<BitmapCursorOzone> bitmap =
BitmapCursorFactoryOzone::GetBitmapCursor(cursor);
EXPECT_CALL(*pointer_, SetCursor(Ne(nullptr), 5, 8));
window_->SetCursor(cursor);

@ -14,6 +14,7 @@
#include "build/chromeos_buildflags.h"
#include "ui/base/cursor/mojom/cursor_type.mojom.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/events/event.h"
@ -316,49 +317,41 @@ bool WaylandWindow::ShouldUseNativeFrame() const {
return false;
}
void WaylandWindow::SetCursor(PlatformCursor cursor) {
DCHECK(cursor);
void WaylandWindow::SetCursor(scoped_refptr<PlatformCursor> platform_cursor) {
DCHECK(platform_cursor);
scoped_refptr<BitmapCursorOzone> bitmap =
BitmapCursorFactoryOzone::GetBitmapCursor(cursor);
if (bitmap_ == bitmap)
if (bitmap_ == platform_cursor)
return;
bitmap_ = bitmap;
if (bitmap_->type() == CursorType::kNone) {
// Hide the cursor.
auto cursor = BitmapCursorOzone::FromPlatformCursor(platform_cursor);
base::Optional<int32_t> shape =
WaylandZcrCursorShapes::ShapeFromType(cursor->type());
if (cursor->type() == CursorType::kNone) { // Hide the cursor.
connection_->SetCursorBitmap(std::vector<SkBitmap>(), gfx::Point(),
buffer_scale());
return;
}
// Check for theme-provided cursor.
if (bitmap_->platform_data()) {
} else if (cursor->platform_data()) { // Check for theme-provided cursor.
connection_->SetPlatformCursor(
reinterpret_cast<wl_cursor*>(bitmap_->platform_data()), 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()) {
reinterpret_cast<wl_cursor*>(cursor->platform_data()), buffer_scale());
} else if (connection_->zcr_cursor_shapes() &&
shape.has_value()) { // Check for Wayland server-side cursor
// support (e.g. exo for lacros).
#if BUILDFLAG(IS_CHROMEOS_LACROS)
// Lacros should not load image assets for default cursors. See
// BitmapCursorFactoryOzone::GetDefaultCursor().
DCHECK(bitmap_->bitmaps().empty());
// Lacros should not load image assets for default cursors. See
// BitmapCursorFactoryOzone::GetDefaultCursor().
DCHECK(cursor->bitmaps().empty());
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
connection_->zcr_cursor_shapes()->SetCursorShape(shape.value());
return;
}
// Fall through to client-side bitmap cursors.
connection_->zcr_cursor_shapes()->SetCursorShape(shape.value());
} else { // Use client-side bitmap cursors as fallback.
// Translate physical pixels to DIPs.
gfx::Point hotspot_in_dips =
gfx::ScaleToRoundedPoint(cursor->hotspot(), 1.0f / ui_scale_);
connection_->SetCursorBitmap(cursor->bitmaps(), hotspot_in_dips,
buffer_scale());
}
// 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());
// The new cursor needs to be stored last to avoid deleting the old cursor
// while it's still in use.
bitmap_ = cursor;
}
void WaylandWindow::MoveCursorTo(const gfx::Point& location) {

@ -155,7 +155,7 @@ class WaylandWindow : public PlatformWindow,
void Deactivate() override;
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
void SetCursor(PlatformCursor cursor) override;
void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
void MoveCursorTo(const gfx::Point& location) override;
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;

@ -14,6 +14,9 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/platform_window/platform_window_delegate.h"
template <class T>
class scoped_refptr;
namespace gfx {
class ImageSkia;
class Point;
@ -23,7 +26,7 @@ class Transform;
} // namespace gfx
namespace ui {
using PlatformCursor = void*;
class PlatformCursor;
// Generic PlatformWindow interface.
class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindow
@ -73,7 +76,12 @@ class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindow
virtual void SetUseNativeFrame(bool use_native_frame) = 0;
virtual bool ShouldUseNativeFrame() const = 0;
virtual void SetCursor(PlatformCursor cursor) = 0;
// This method sets the current cursor to `cursor`. Note that the platform
// window should keep a copy of `cursor` and also avoid replacing it until the
// new value has been set if any kind of platform-specific resources are
// managed by the platform cursor, e.g. HCURSOR on Windows, which are
// destroyed once the last copy of the platform cursor goes out of scope.
virtual void SetCursor(scoped_refptr<PlatformCursor> cursor) = 0;
// Moves the cursor to |location|. Location is in platform window coordinates.
virtual void MoveCursorTo(const gfx::Point& location) = 0;

@ -4,7 +4,9 @@
#include "ui/platform_window/stub/stub_window.h"
#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/platform_window/platform_window_delegate.h"
namespace ui {
@ -84,7 +86,7 @@ bool StubWindow::ShouldUseNativeFrame() const {
return false;
}
void StubWindow::SetCursor(PlatformCursor cursor) {}
void StubWindow::SetCursor(scoped_refptr<PlatformCursor> cursor) {}
void StubWindow::MoveCursorTo(const gfx::Point& location) {}

@ -48,7 +48,7 @@ class STUB_WINDOW_EXPORT StubWindow : public PlatformWindow {
void Deactivate() override;
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
void SetCursor(PlatformCursor cursor) override;
void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
void MoveCursorTo(const gfx::Point& location) override;
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;

@ -4,20 +4,22 @@
#include "ui/platform_window/win/win_window.h"
#include <windows.h>
#include <algorithm>
#include <memory>
#include <string>
#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
#include "base/strings/string_util_win.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/cursor/win/win_cursor.h"
#include "ui/base/win/shell.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/gfx/win/msg_util.h"
#include <windows.h>
namespace ui {
namespace {
@ -147,9 +149,15 @@ bool WinWindow::ShouldUseNativeFrame() const {
return false;
}
void WinWindow::SetCursor(PlatformCursor cursor) {
DCHECK(cursor);
::SetCursor(static_cast<WinCursor*>(cursor)->hcursor());
void WinWindow::SetCursor(scoped_refptr<PlatformCursor> platform_cursor) {
DCHECK(platform_cursor);
auto cursor = WinCursor::FromPlatformCursor(platform_cursor);
::SetCursor(cursor->hcursor());
// The new cursor needs to be stored last to avoid deleting the old cursor
// while it's still in use.
cursor_ = cursor;
}
void WinWindow::MoveCursorTo(const gfx::Point& location) {

@ -7,6 +7,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "ui/gfx/win/msg_util.h"
#include "ui/gfx/win/window_impl.h"
@ -17,6 +18,7 @@
#include <windows.h>
namespace ui {
class WinCursor;
class WIN_WINDOW_EXPORT WinWindow : public PlatformWindow,
public gfx::WindowImpl {
@ -48,7 +50,7 @@ class WIN_WINDOW_EXPORT WinWindow : public PlatformWindow,
void Deactivate() override;
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
void SetCursor(PlatformCursor cursor) override;
void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
void MoveCursorTo(const gfx::Point& location) override;
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;
@ -105,6 +107,10 @@ class WIN_WINDOW_EXPORT WinWindow : public PlatformWindow,
PlatformWindowDelegate* delegate_;
// Keep a reference to the current cursor to make sure the wrapped HCURSOR
// isn't destroyed after the call to SetCursor().
scoped_refptr<WinCursor> cursor_;
CR_MSG_MAP_CLASS_DECLARATIONS(WinWindow)
DISALLOW_COPY_AND_ASSIGN(WinWindow);

@ -4,6 +4,7 @@
#include "ui/platform_window/x11/x11_window.h"
#include "base/memory/scoped_refptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
@ -12,6 +13,7 @@
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/base/buildflags.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/dragdrop/os_exchange_data.h"
@ -760,10 +762,10 @@ bool X11Window::ShouldUseNativeFrame() const {
return use_native_frame_;
}
void X11Window::SetCursor(PlatformCursor cursor) {
void X11Window::SetCursor(scoped_refptr<PlatformCursor> cursor) {
DCHECK(cursor);
last_cursor_ = static_cast<X11Cursor*>(cursor);
last_cursor_ = X11Cursor::FromPlatformCursor(cursor);
on_cursor_loaded_.Reset(base::BindOnce(DefineCursor, xwindow_));
last_cursor_->OnCursorLoaded(on_cursor_loaded_.callback());
}

@ -90,7 +90,7 @@ class X11_WINDOW_EXPORT X11Window
void Deactivate() override;
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
void SetCursor(PlatformCursor cursor) override;
void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
void MoveCursorTo(const gfx::Point& location) override;
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;

@ -1362,7 +1362,10 @@ test("views_unittests") {
"widget/desktop_aura/desktop_screen_x11_unittest.cc",
"widget/desktop_aura/x11_drag_drop_client_unittest.cc",
]
deps += [ "//ui/base/x:test_support" ]
deps += [
"//ui/base/x",
"//ui/base/x:test_support",
]
}
if (is_linux || is_chromeos || is_fuchsia) {
sources += [

@ -9,12 +9,14 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
@ -60,7 +62,7 @@ class FakePlatformWindow : public ui::PlatformWindow, public ui::WmDragHandler {
}
void Activate() override {}
void Deactivate() override {}
void SetCursor(ui::PlatformCursor cursor) override {}
void SetCursor(scoped_refptr<ui::PlatformCursor> cursor) override {}
void MoveCursorTo(const gfx::Point& location) override {}
void ConfineCursorToBounds(const gfx::Rect& bounds) override {}
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override {}

@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/containers/flat_set.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
#include "base/win/win_util.h"
@ -22,6 +23,8 @@
#include "ui/aura/client/focus_client.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/class_property.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/cursor/win/win_cursor.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ui_base_features.h"
@ -633,10 +636,8 @@ void DesktopWindowTreeHostWin::SetCursorNative(gfx::NativeCursor cursor) {
TRACE_EVENT1("ui,input", "DesktopWindowTreeHostWin::SetCursorNative",
"cursor", cursor.type());
ui::WinCursor* platform_cursor =
static_cast<ui::WinCursor*>(cursor.platform());
DCHECK(platform_cursor);
message_handler_->SetCursor(platform_cursor->hcursor());
message_handler_->SetCursor(
ui::WinCursor::FromPlatformCursor(cursor.platform()));
}
void DesktopWindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) {

@ -13,6 +13,7 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
@ -22,9 +23,9 @@
#include "ui/aura/test/test_screen.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/cursor_loader.h"
#include "ui/base/cursor/mojom/cursor_type.mojom.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
#include "ui/base/dragdrop/os_exchange_data.h"
@ -323,10 +324,10 @@ DragOperation SimpleTestDragDropClient::StartDragAndDrop(
ui::CursorLoader cursor_loader;
ui::Cursor grabbing = ui::mojom::CursorType::kGrabbing;
cursor_loader.SetPlatformCursor(&grabbing);
auto* last_cursor = static_cast<ui::X11Cursor*>(
source_window->GetHost()->last_cursor().platform());
loop_->RunMoveLoop(!source_window->HasCapture(), last_cursor,
static_cast<ui::X11Cursor*>(grabbing.platform()));
auto last_cursor = source_window->GetHost()->last_cursor();
loop_->RunMoveLoop(!source_window->HasCapture(),
ui::X11Cursor::FromPlatformCursor(last_cursor.platform()),
ui::X11Cursor::FromPlatformCursor(grabbing.platform()));
auto resulting_operation = negotiated_operation();
CleanupDrag();

@ -35,6 +35,7 @@
#include "ui/accessibility/platform/ax_fragment_root_win.h"
#include "ui/accessibility/platform/ax_platform_node_win.h"
#include "ui/accessibility/platform/ax_system_caret_win.h"
#include "ui/base/cursor/win/win_cursor.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/base/ui_base_features.h"
@ -402,7 +403,7 @@ HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate,
waiting_for_close_now_(false),
use_system_default_icon_(false),
restored_enabled_(false),
current_cursor_(nullptr),
current_cursor_(base::MakeRefCounted<ui::WinCursor>()),
dpi_(0),
called_enable_non_client_dpi_scaling_(false),
active_mouse_tracking_flags_(0),
@ -863,10 +864,12 @@ bool HWNDMessageHandler::SetTitle(const std::u16string& title) {
return true;
}
void HWNDMessageHandler::SetCursor(HCURSOR cursor) {
void HWNDMessageHandler::SetCursor(scoped_refptr<ui::WinCursor> cursor) {
DCHECK(cursor);
TRACE_EVENT1("ui,input", "HWNDMessageHandler::SetCursor", "cursor",
static_cast<const void*>(cursor));
::SetCursor(cursor);
static_cast<const void*>(cursor->hcursor()));
::SetCursor(cursor->hcursor());
current_cursor_ = cursor;
}
@ -2486,12 +2489,15 @@ LRESULT HWNDMessageHandler::OnSetCursor(UINT message,
if (is_pen_active_in_client_area_)
return 1;
// current_cursor_ must be a ui::WinCursor, so that custom image cursors are
// properly ref-counted. cursor below is only used for system cursors and
// doesn't replace the current cursor so an HCURSOR can be used directly.
wchar_t* cursor = IDC_ARROW;
// Reimplement the necessary default behavior here. Calling DefWindowProc can
// trigger weird non-client painting for non-glass windows with custom frames.
// Using a ScopedRedrawLock to prevent caption rendering artifacts may allow
// content behind this window to incorrectly paint in front of this window.
// Invalidating the window to paint over either set of artifacts is not ideal.
wchar_t* cursor = IDC_ARROW;
switch (LOWORD(l_param)) {
case HTSIZE:
cursor = IDC_SIZENWSE;

@ -17,6 +17,7 @@
#include "base/compiler_specific.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/win/scoped_gdi_object.h"
@ -43,9 +44,10 @@ class Insets;
namespace ui {
class AXFragmentRootWin;
class AXSystemCaretWin;
class SessionChangeObserver;
class TextInputClient;
class ViewProp;
class SessionChangeObserver;
class WinCursor;
} // namespace ui
namespace views {
@ -159,7 +161,7 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
// Returns true if the title changed.
bool SetTitle(const std::u16string& title);
void SetCursor(HCURSOR cursor);
void SetCursor(scoped_refptr<ui::WinCursor> cursor);
void FrameTypeChanged();
@ -624,7 +626,7 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
bool restored_enabled_;
// The current cursor.
HCURSOR current_cursor_;
scoped_refptr<ui::WinCursor> current_cursor_;
// The icon created from the bitmap image of the window icon.
base::win::ScopedHICON window_icon_;