Commit a9458bb6 authored by Henrique Ferreiro's avatar Henrique Ferreiro Committed by Commit Bot

Wayland: Apply the correct buffer scale to the cursor bitmap

On Ozone/Wayland, the cursor bitmap as obtained by CursorLoader already
matches the device scale factor, after selecting the most appropriate
asset (100P, 200P, etc.). The Wayland surface needs to know about this
scale, so that it doesn't scale it further in some cases (e.g. HiDPI).

On Linux, this was previously working in HiDPI displays because of a bug
in mutter: https://gitlab.gnome.org/GNOME/mutter/-/issues/1215, where
cursor surfaces aren't scaled.

The issue was present on Lacros though, but resulted in cursors being
blurry instead of too big, because, when Chrome was launched, the
initial display configuration wasn't being passed to CursorLoader. This
meant that the 1.0 default scale was used, so that the 100P cursor image
assets were loaded and then scaled by the compositor.

A fix for the latter issue landed in https://crrev.com/c/2443610.

Bug: 1127962, 1141426
Change-Id: I1511fe9fc24f85db77e1bcc66ebbb720a8ce3375
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2470626
Commit-Queue: Henrique Ferreiro <hferreiro@igalia.com>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#821187}
parent 894fa45b
...@@ -159,10 +159,11 @@ void WaylandConnection::SetShutdownCb(base::OnceCallback<void()> shutdown_cb) { ...@@ -159,10 +159,11 @@ void WaylandConnection::SetShutdownCb(base::OnceCallback<void()> shutdown_cb) {
} }
void WaylandConnection::SetCursorBitmap(const std::vector<SkBitmap>& bitmaps, void WaylandConnection::SetCursorBitmap(const std::vector<SkBitmap>& bitmaps,
const gfx::Point& location) { const gfx::Point& hotspot_in_dips,
int buffer_scale) {
if (!cursor_) if (!cursor_)
return; return;
cursor_->UpdateBitmap(bitmaps, location, serial()); cursor_->UpdateBitmap(bitmaps, hotspot_in_dips, serial(), buffer_scale);
} }
bool WaylandConnection::IsDragInProgress() const { bool WaylandConnection::IsDragInProgress() const {
......
...@@ -94,7 +94,8 @@ class WaylandConnection { ...@@ -94,7 +94,8 @@ class WaylandConnection {
EventSerial event_serial() const { return serial_; } EventSerial event_serial() const { return serial_; }
void SetCursorBitmap(const std::vector<SkBitmap>& bitmaps, void SetCursorBitmap(const std::vector<SkBitmap>& bitmaps,
const gfx::Point& location); const gfx::Point& hotspot_in_dips,
int buffer_scale);
WaylandEventSource* event_source() const { return event_source_.get(); } WaylandEventSource* event_source() const { return event_source_.get(); }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/skia_util.h" #include "ui/gfx/skia_util.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h" #include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h"
...@@ -33,8 +34,9 @@ void WaylandCursor::OnBufferRelease(void* data, wl_buffer* buffer) { ...@@ -33,8 +34,9 @@ void WaylandCursor::OnBufferRelease(void* data, wl_buffer* buffer) {
} }
void WaylandCursor::UpdateBitmap(const std::vector<SkBitmap>& cursor_image, void WaylandCursor::UpdateBitmap(const std::vector<SkBitmap>& cursor_image,
const gfx::Point& hotspot, const gfx::Point& hotspot_in_dips,
uint32_t serial) { uint32_t serial,
int buffer_scale) {
DCHECK(connection_->shm()); DCHECK(connection_->shm());
if (!pointer_) if (!pointer_)
return; return;
...@@ -61,8 +63,10 @@ void WaylandCursor::UpdateBitmap(const std::vector<SkBitmap>& cursor_image, ...@@ -61,8 +63,10 @@ void WaylandCursor::UpdateBitmap(const std::vector<SkBitmap>& cursor_image,
wl::DrawBitmap(image, &buffer); wl::DrawBitmap(image, &buffer);
wl_surface_set_buffer_scale(pointer_surface_.get(), buffer_scale);
wl_pointer_set_cursor(pointer_->wl_object(), serial, pointer_surface_.get(), wl_pointer_set_cursor(pointer_->wl_object(), serial, pointer_surface_.get(),
hotspot.x(), hotspot.y()); hotspot_in_dips.x(), hotspot_in_dips.y());
wl_surface_damage(pointer_surface_.get(), 0, 0, image_size.width(), wl_surface_damage(pointer_surface_.get(), 0, 0, image_size.width(),
image_size.height()); image_size.height());
wl_surface_attach(pointer_surface_.get(), buffer.get(), 0, 0); wl_surface_attach(pointer_surface_.get(), buffer.get(), 0, 0);
......
...@@ -39,9 +39,14 @@ class WaylandCursor { ...@@ -39,9 +39,14 @@ class WaylandCursor {
// Updates wl_pointer's visual representation with the given bitmap // Updates wl_pointer's visual representation with the given bitmap
// image set and hotspot. // image set and hotspot.
// The cursor bitmap should already match the device scale factor.
// `buffer_scale` should match the scale of the window surface, so that we
// can pass this information to the compositor which will avoid scaling it
// again.
void UpdateBitmap(const std::vector<SkBitmap>& bitmaps, void UpdateBitmap(const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot, const gfx::Point& hotspot_in_dips,
uint32_t serial); uint32_t serial,
int buffer_scale);
private: private:
// wl_buffer_listener: // wl_buffer_listener:
......
...@@ -247,13 +247,13 @@ TEST_P(WaylandPointerTest, SetBitmap) { ...@@ -247,13 +247,13 @@ TEST_P(WaylandPointerTest, SetBitmap) {
SkImageInfo::Make(16, 16, kUnknown_SkColorType, kUnknown_SkAlphaType)); SkImageInfo::Make(16, 16, kUnknown_SkColorType, kUnknown_SkAlphaType));
EXPECT_CALL(*pointer_, SetCursor(nullptr, 0, 0)); EXPECT_CALL(*pointer_, SetCursor(nullptr, 0, 0));
connection_->SetCursorBitmap({}, {}); connection_->SetCursorBitmap({}, {}, 1.0);
connection_->ScheduleFlush(); connection_->ScheduleFlush();
Sync(); Sync();
Mock::VerifyAndClearExpectations(pointer_); Mock::VerifyAndClearExpectations(pointer_);
EXPECT_CALL(*pointer_, SetCursor(Ne(nullptr), 5, 8)); EXPECT_CALL(*pointer_, SetCursor(Ne(nullptr), 5, 8));
connection_->SetCursorBitmap({dummy_cursor}, gfx::Point(5, 8)); connection_->SetCursorBitmap({dummy_cursor}, gfx::Point(5, 8), 1.0);
connection_->ScheduleFlush(); connection_->ScheduleFlush();
Sync(); Sync();
Mock::VerifyAndClearExpectations(pointer_); Mock::VerifyAndClearExpectations(pointer_);
......
...@@ -112,8 +112,13 @@ void WaylandWindow::SetPointerFocus(bool focus) { ...@@ -112,8 +112,13 @@ void WaylandWindow::SetPointerFocus(bool focus) {
// Whenever the window gets the pointer focus back, we must reinitialize the // Whenever the window gets the pointer focus back, we must reinitialize the
// cursor. Otherwise, it is invalidated whenever the pointer leaves the // cursor. Otherwise, it is invalidated whenever the pointer leaves the
// surface and is not restored by the Wayland compositor. // surface and is not restored by the Wayland compositor.
if (has_pointer_focus_ && bitmap_) if (has_pointer_focus_ && bitmap_) {
connection_->SetCursorBitmap(bitmap_->bitmaps(), bitmap_->hotspot()); // Translate physical pixels to DIPs.
gfx::Point hotspot_in_dips =
gfx::ScaleToRoundedPoint(bitmap_->hotspot(), 1.0f / ui_scale_);
connection_->SetCursorBitmap(bitmap_->bitmaps(), hotspot_in_dips,
buffer_scale());
}
} }
void WaylandWindow::Show(bool inactive) { void WaylandWindow::Show(bool inactive) {
...@@ -214,9 +219,14 @@ void WaylandWindow::SetCursor(PlatformCursor cursor) { ...@@ -214,9 +219,14 @@ void WaylandWindow::SetCursor(PlatformCursor cursor) {
bitmap_ = bitmap; bitmap_ = bitmap;
if (bitmap_) { if (bitmap_) {
connection_->SetCursorBitmap(bitmap_->bitmaps(), bitmap_->hotspot()); // 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());
} else { } else {
connection_->SetCursorBitmap(std::vector<SkBitmap>(), gfx::Point()); connection_->SetCursorBitmap(std::vector<SkBitmap>(), gfx::Point(),
buffer_scale());
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment