From 20d5f5e8da0888ecb46c0497b398f9f54f5a4965 Mon Sep 17 00:00:00 2001 From: Joel Selvaraj Date: Mon, 11 Mar 2024 10:38:52 -0500 Subject: [PATCH] linux: wayland cursor fixes (#9047) Release Notes: - Fixed wayland cursor style handling In upcoming Gnome 46, cursor icon names are considerably changing. For example: this commit https://gitlab.gnome.org/GNOME/adwaita-icon-theme/-/commit/74e9b79471236320d2af4925d6c5bb7df22380ce removed/modified a lot of cursor names. Then some of the names were reintroduced in this commit https://gitlab.gnome.org/GNOME/adwaita-icon-theme/-/commit/6f64dc55dcaae24a14564494e24564a120cb4f33. I also tried upcoming KDE Plasma 6. Some of the cursor names are not used commonly between Gnome and KDE. From my analysis, these set of cursor names should be more widely available in both previous and upcoming release of Gnome and KDE. Also, If a cursor style is not available, let's fallback to default cursor style. This avoids scenarios where we get stuck with special cursor styles like IBeam/Resize* because the current cursor style is not available. This will lead to an unpleasant/broken experience. Falling back to default cursor seems to be more acceptable. --- .../gpui/src/platform/linux/wayland/client.rs | 42 ++++++++++--------- .../gpui/src/platform/linux/wayland/cursor.rs | 27 ++++++++---- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/crates/gpui/src/platform/linux/wayland/client.rs b/crates/gpui/src/platform/linux/wayland/client.rs index f97766af79..05da84481d 100644 --- a/crates/gpui/src/platform/linux/wayland/client.rs +++ b/crates/gpui/src/platform/linux/wayland/client.rs @@ -268,26 +268,30 @@ impl Client for WaylandClient { } fn set_cursor_style(&self, style: CursorStyle) { + // Based on cursor names from https://gitlab.gnome.org/GNOME/adwaita-icon-theme (GNOME) + // and https://github.com/KDE/breeze (KDE). Both of them seem to be also derived from + // Web CSS cursor names: https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#values let cursor_icon_name = match style { - CursorStyle::Arrow => "arrow".to_string(), - CursorStyle::IBeam => "text".to_string(), - CursorStyle::Crosshair => "crosshair".to_string(), - CursorStyle::ClosedHand => "grabbing".to_string(), - CursorStyle::OpenHand => "openhand".to_string(), - CursorStyle::PointingHand => "hand".to_string(), - CursorStyle::ResizeLeft => "w-resize".to_string(), - CursorStyle::ResizeRight => "e-resize".to_string(), - CursorStyle::ResizeLeftRight => "ew-resize".to_string(), - CursorStyle::ResizeUp => "n-resize".to_string(), - CursorStyle::ResizeDown => "s-resize".to_string(), - CursorStyle::ResizeUpDown => "ns-resize".to_string(), - CursorStyle::DisappearingItem => "grabbing".to_string(), // todo(linux) - couldn't find equivalent icon in linux - CursorStyle::IBeamCursorForVerticalLayout => "vertical-text".to_string(), - CursorStyle::OperationNotAllowed => "not-allowed".to_string(), - CursorStyle::DragLink => "dnd-link".to_string(), - CursorStyle::DragCopy => "dnd-copy".to_string(), - CursorStyle::ContextualMenu => "context-menu".to_string(), - }; + CursorStyle::Arrow => "arrow", + CursorStyle::IBeam => "text", + CursorStyle::Crosshair => "crosshair", + CursorStyle::ClosedHand => "grabbing", + CursorStyle::OpenHand => "grab", + CursorStyle::PointingHand => "pointer", + CursorStyle::ResizeLeft => "w-resize", + CursorStyle::ResizeRight => "e-resize", + CursorStyle::ResizeLeftRight => "ew-resize", + CursorStyle::ResizeUp => "n-resize", + CursorStyle::ResizeDown => "s-resize", + CursorStyle::ResizeUpDown => "ns-resize", + CursorStyle::DisappearingItem => "grabbing", // todo(linux) - couldn't find equivalent icon in linux + CursorStyle::IBeamCursorForVerticalLayout => "vertical-text", + CursorStyle::OperationNotAllowed => "not-allowed", + CursorStyle::DragLink => "alias", + CursorStyle::DragCopy => "copy", + CursorStyle::ContextualMenu => "context-menu", + } + .to_string(); let mut cursor_state = self.state.cursor_state.borrow_mut(); cursor_state.cursor_icon_name = cursor_icon_name; diff --git a/crates/gpui/src/platform/linux/wayland/cursor.rs b/crates/gpui/src/platform/linux/wayland/cursor.rs index 8b641972e3..8ea66168c8 100644 --- a/crates/gpui/src/platform/linux/wayland/cursor.rs +++ b/crates/gpui/src/platform/linux/wayland/cursor.rs @@ -35,10 +35,26 @@ impl Cursor { } pub fn set_icon(&mut self, wl_pointer: &WlPointer, cursor_icon_name: String) { + let mut cursor_icon_name = cursor_icon_name.clone(); if self.current_icon_name != cursor_icon_name { - if self.theme.is_ok() { - if let Some(cursor) = self.theme.as_mut().unwrap().get_cursor(&cursor_icon_name) { - let buffer: &CursorImageBuffer = &cursor[0]; + if let Ok(theme) = &mut self.theme { + let mut buffer: Option<&CursorImageBuffer>; + + if let Some(cursor) = theme.get_cursor(&cursor_icon_name) { + buffer = Some(&cursor[0]); + } else if let Some(cursor) = theme.get_cursor("default") { + buffer = Some(&cursor[0]); + cursor_icon_name = "default".to_string(); + log::warn!( + "Linux: Wayland: Unable to get cursor icon: {}. Using default cursor icon", + cursor_icon_name + ); + } else { + buffer = None; + log::warn!("Linux: Wayland: Unable to get default cursor too!"); + } + + if let Some(buffer) = &mut buffer { let (width, height) = buffer.dimensions(); let (hot_x, hot_y) = buffer.hotspot(); @@ -53,11 +69,6 @@ impl Cursor { self.surface.commit(); self.current_icon_name = cursor_icon_name; - } else { - log::warn!( - "Linux: Wayland: Unable to get cursor icon: {}", - cursor_icon_name - ); } } else { log::warn!("Linux: Wayland: Unable to load cursor themes");