Skip to content

Commit bfb616a

Browse files
authored
Add support for HighDPI cursor themes (sony#304)
Signed-off-by: Valentin Hăloiu <[email protected]>
1 parent 3cdde96 commit bfb616a

File tree

2 files changed

+66
-28
lines changed

2 files changed

+66
-28
lines changed

src/flutter/shell/platform/linux_embedded/window/elinux_window_wayland.cc

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,6 @@ ELinuxWindowWayland::ELinuxWindowWayland(
819819
wl_data_device_(nullptr),
820820
wl_data_offer_(nullptr),
821821
wl_data_source_(nullptr),
822-
wl_cursor_theme_(nullptr),
823822
serial_(0),
824823
zwp_text_input_manager_v1_(nullptr),
825824
zwp_text_input_manager_v3_(nullptr),
@@ -834,6 +833,13 @@ ELinuxWindowWayland::ELinuxWindowWayland(
834833
view_properties.force_scale_factor ? view_properties.scale_factor : 1.0;
835834
SetRotation(view_properties_.view_rotation);
836835

836+
auto xcursor_size_string = std::getenv(kXcursorSizeEnvironmentKey);
837+
cursor_size_ =
838+
xcursor_size_string ? atoi(xcursor_size_string) : kDefaultPointerSize;
839+
if (cursor_size_ <= 0) {
840+
cursor_size_ = kDefaultPointerSize;
841+
}
842+
837843
wl_display_ = wl_display_connect(nullptr);
838844
if (!wl_display_) {
839845
ELINUX_LOG(ERROR) << "Failed to connect to the Wayland display.";
@@ -889,10 +895,10 @@ ELinuxWindowWayland::~ELinuxWindowWayland() {
889895
display_valid_ = false;
890896
running_ = false;
891897

892-
if (wl_cursor_theme_) {
893-
wl_cursor_theme_destroy(wl_cursor_theme_);
894-
wl_cursor_theme_ = nullptr;
898+
for (auto theme : wl_cursor_themes_) {
899+
wl_cursor_theme_destroy(theme.second);
895900
}
901+
wl_cursor_themes_.clear();
896902

897903
{
898904
if (zwp_text_input_v1_) {
@@ -1201,7 +1207,7 @@ void ELinuxWindowWayland::UpdateFlutterCursor(const std::string& cursor_name) {
12011207
return;
12021208
}
12031209

1204-
auto wl_cursor = GetWlCursor(cursor_name);
1210+
auto wl_cursor = GetWlCursor(cursor_name, cursor_size_ * current_scale_);
12051211
if (!wl_cursor) {
12061212
return;
12071213
}
@@ -1213,6 +1219,7 @@ void ELinuxWindowWayland::UpdateFlutterCursor(const std::string& cursor_name) {
12131219
image->hotspot_y);
12141220
wl_surface_attach(wl_cursor_surface_, buffer, 0, 0);
12151221
wl_surface_damage(wl_cursor_surface_, 0, 0, image->width, image->height);
1222+
wl_surface_set_buffer_scale(wl_cursor_surface_, current_scale_);
12161223
wl_surface_commit(wl_cursor_surface_);
12171224
}
12181225
}
@@ -1321,12 +1328,6 @@ void ELinuxWindowWayland::WlRegistryHandler(wl_registry* wl_registry,
13211328
constexpr uint32_t kMaxVersion = 1;
13221329
wl_shm_ = static_cast<decltype(wl_shm_)>(
13231330
wl_registry_bind(wl_registry, name, &wl_shm_interface, kMaxVersion));
1324-
wl_cursor_theme_ = wl_cursor_theme_load(nullptr, 32, wl_shm_);
1325-
if (!wl_cursor_theme_) {
1326-
ELINUX_LOG(ERROR) << "Failed to load cursor theme.";
1327-
return;
1328-
}
1329-
CreateSupportedWlCursorList();
13301331
}
13311332
return;
13321333
}
@@ -1378,8 +1379,22 @@ void ELinuxWindowWayland::WlRegistryHandler(wl_registry* wl_registry,
13781379
void ELinuxWindowWayland::WlUnRegistryHandler(wl_registry* wl_registry,
13791380
uint32_t name) {}
13801381

1381-
void ELinuxWindowWayland::CreateSupportedWlCursorList() {
1382-
std::vector<std::string> wl_cursor_themes{
1382+
bool ELinuxWindowWayland::LoadCursorTheme(uint32_t size) {
1383+
if (!wl_shm_) {
1384+
ELINUX_LOG(ERROR) << "Failed to load cursor theme because shared memory "
1385+
"buffers are not available.";
1386+
return false;
1387+
}
1388+
1389+
auto theme = wl_cursor_theme_load(nullptr, size, wl_shm_);
1390+
if (!theme) {
1391+
ELINUX_LOG(ERROR) << "Failed to load cursor theme for size: " << size;
1392+
return false;
1393+
}
1394+
1395+
wl_cursor_themes_[size] = theme;
1396+
1397+
std::vector<std::string> wl_cursor_names{
13831398
kWlCursorThemeLeftPtr,
13841399
kWlCursorThemeBottomLeftCorner,
13851400
kWlCursorThemeBottomRightCorner,
@@ -1395,18 +1410,24 @@ void ELinuxWindowWayland::CreateSupportedWlCursorList() {
13951410
kWlCursorThemeWatch,
13961411
};
13971412

1398-
for (const auto& theme : wl_cursor_themes) {
1399-
auto wl_cursor =
1400-
wl_cursor_theme_get_cursor(wl_cursor_theme_, theme.c_str());
1413+
std::unordered_map<std::string, wl_cursor*> cursor_list;
1414+
1415+
for (const auto& cursor_name : wl_cursor_names) {
1416+
auto wl_cursor = wl_cursor_theme_get_cursor(theme, cursor_name.c_str());
14011417
if (!wl_cursor) {
1402-
ELINUX_LOG(ERROR) << "Unsupported cursor theme: " << theme.c_str();
1418+
ELINUX_LOG(ERROR) << "Unsupported cursor theme: " << cursor_name.c_str();
14031419
continue;
14041420
}
1405-
supported_wl_cursor_list_[theme] = wl_cursor;
1421+
cursor_list[cursor_name] = wl_cursor;
14061422
}
1423+
1424+
supported_wl_cursor_list_.insert(std::make_pair(size, cursor_list));
1425+
1426+
return true;
14071427
}
14081428

1409-
wl_cursor* ELinuxWindowWayland::GetWlCursor(const std::string& cursor_name) {
1429+
wl_cursor* ELinuxWindowWayland::GetWlCursor(const std::string& cursor_name,
1430+
uint32_t size) {
14101431
// Convert the cursor theme name from Flutter's cursor value to Wayland's one.
14111432
// However, Wayland has not all cursor themes corresponding to Flutter.
14121433
// If there is no Wayland's cursor theme corresponding to the Flutter's cursor
@@ -1450,17 +1471,24 @@ wl_cursor* ELinuxWindowWayland::GetWlCursor(const std::string& cursor_name) {
14501471
{"zoomOut", ""},
14511472
};
14521473

1474+
if (supported_wl_cursor_list_.find(size) == supported_wl_cursor_list_.end()) {
1475+
if (!LoadCursorTheme(size)) {
1476+
return nullptr;
1477+
}
1478+
}
1479+
1480+
auto cursor_list = supported_wl_cursor_list_.at(size);
1481+
14531482
if (flutter_to_wayland_cursor_map.find(cursor_name) !=
14541483
flutter_to_wayland_cursor_map.end()) {
14551484
auto theme = flutter_to_wayland_cursor_map.at(cursor_name);
1456-
if (!theme.empty() && supported_wl_cursor_list_.find(theme) !=
1457-
supported_wl_cursor_list_.end()) {
1458-
return supported_wl_cursor_list_[theme];
1485+
if (!theme.empty() && cursor_list.find(theme) != cursor_list.end()) {
1486+
return cursor_list[theme];
14591487
}
14601488
}
14611489

14621490
ELINUX_LOG(ERROR) << "Unsupported cursor: " << cursor_name.c_str();
1463-
return supported_wl_cursor_list_[kWlCursorThemeLeftPtr];
1491+
return cursor_list[kWlCursorThemeLeftPtr];
14641492
}
14651493

14661494
void ELinuxWindowWayland::ShowVirtualKeyboard() {

src/flutter/shell/platform/linux_embedded/window/elinux_window_wayland.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ extern "C" {
2929

3030
namespace flutter {
3131

32+
namespace {
33+
constexpr char kXcursorSizeEnvironmentKey[] = "XCURSOR_SIZE";
34+
} // namespace
35+
3236
class ELinuxWindowWayland : public ELinuxWindow, public WindowBindingHandler {
3337
public:
3438
ELinuxWindowWayland(FlutterDesktopViewProperties view_properties);
@@ -90,9 +94,9 @@ class ELinuxWindowWayland : public ELinuxWindow, public WindowBindingHandler {
9094

9195
void WlUnRegistryHandler(wl_registry* wl_registry, uint32_t name);
9296

93-
void CreateSupportedWlCursorList();
97+
bool LoadCursorTheme(uint32_t size);
9498

95-
wl_cursor* GetWlCursor(const std::string& cursor_name);
99+
wl_cursor* GetWlCursor(const std::string& cursor_name, uint32_t size);
96100

97101
void ShowVirtualKeyboard();
98102

@@ -115,6 +119,7 @@ class ELinuxWindowWayland : public ELinuxWindow, public WindowBindingHandler {
115119
static const wp_presentation_listener kWpPresentationListener;
116120
static const wp_presentation_feedback_listener
117121
kWpPresentationFeedbackListener;
122+
static constexpr size_t kDefaultPointerSize = 24;
118123

119124
// A pointer to a FlutterWindowsView that can be used to update engine
120125
// windowing and input state.
@@ -149,7 +154,6 @@ class ELinuxWindowWayland : public ELinuxWindow, public WindowBindingHandler {
149154
wl_touch* wl_touch_;
150155
wl_keyboard* wl_keyboard_;
151156
wl_surface* wl_cursor_surface_;
152-
wl_cursor_theme* wl_cursor_theme_;
153157
xdg_wm_base* xdg_wm_base_;
154158
xdg_surface* xdg_surface_;
155159
xdg_toplevel* xdg_toplevel_;
@@ -167,9 +171,15 @@ class ELinuxWindowWayland : public ELinuxWindow, public WindowBindingHandler {
167171
int32_t frame_rate_;
168172

169173
CursorInfo cursor_info_;
174+
size_t cursor_size_;
175+
176+
// List of cursor name and wl_cursor supported by Wayland keyed by their
177+
// (scaled) size.
178+
std::unordered_map<uint32_t, std::unordered_map<std::string, wl_cursor*>>
179+
supported_wl_cursor_list_;
170180

171-
// List of cursor name and wl_cursor supported by Wayland.
172-
std::unordered_map<std::string, wl_cursor*> supported_wl_cursor_list_;
181+
// List of loaded Wayland cursor themes keyed by their (scaled) size.
182+
std::unordered_map<uint32_t, wl_cursor_theme*> wl_cursor_themes_;
173183

174184
wl_data_device_manager* wl_data_device_manager_;
175185
wl_data_device* wl_data_device_;

0 commit comments

Comments
 (0)