@@ -496,7 +496,7 @@ impl WaylandClient {
XDPEvent::CursorTheme(theme) => {
if let Some(client) = client.0.upgrade() {
let mut client = client.borrow_mut();
- client.cursor.set_theme(theme.as_str(), None);
+ client.cursor.set_theme(theme.as_str());
}
}
XDPEvent::CursorSize(size) => {
@@ -649,15 +649,16 @@ impl LinuxClient for WaylandClient {
if let Some(cursor_shape_device) = &state.cursor_shape_device {
cursor_shape_device.set_shape(serial, style.to_shape());
- } else if state.mouse_focused_window.is_some() {
+ } else if let Some(focused_window) = &state.mouse_focused_window {
// cursor-shape-v1 isn't supported, set the cursor using a surface.
let wl_pointer = state
.wl_pointer
.clone()
.expect("window is focused by pointer");
+ let scale = focused_window.primary_output_scale();
state
.cursor
- .set_icon(&wl_pointer, serial, &style.to_icon_name());
+ .set_icon(&wl_pointer, serial, &style.to_icon_name(), scale);
}
}
}
@@ -1439,9 +1440,13 @@ impl Dispatch<wl_pointer::WlPointer, ()> for WaylandClientStatePtr {
if let Some(cursor_shape_device) = &state.cursor_shape_device {
cursor_shape_device.set_shape(serial, style.to_shape());
} else {
- state
- .cursor
- .set_icon(&wl_pointer, serial, &style.to_icon_name());
+ let scale = window.primary_output_scale();
+ state.cursor.set_icon(
+ &wl_pointer,
+ serial,
+ &style.to_icon_name(),
+ scale,
+ );
}
}
drop(state);
@@ -9,6 +9,7 @@ use wayland_cursor::{CursorImageBuffer, CursorTheme};
pub(crate) struct Cursor {
theme: Option<CursorTheme>,
theme_name: Option<String>,
+ theme_size: u32,
surface: WlSurface,
size: u32,
shm: WlShm,
@@ -27,6 +28,7 @@ impl Cursor {
Self {
theme: CursorTheme::load(&connection, globals.shm.clone(), size).log_err(),
theme_name: None,
+ theme_size: size,
surface: globals.compositor.create_surface(&globals.qh, ()),
shm: globals.shm.clone(),
connection: connection.clone(),
@@ -34,26 +36,26 @@ impl Cursor {
}
}
- pub fn set_theme(&mut self, theme_name: &str, size: Option<u32>) {
- if let Some(size) = size {
- self.size = size;
- }
- if let Some(theme) =
- CursorTheme::load_from_name(&self.connection, self.shm.clone(), theme_name, self.size)
- .log_err()
+ pub fn set_theme(&mut self, theme_name: &str) {
+ if let Some(theme) = CursorTheme::load_from_name(
+ &self.connection,
+ self.shm.clone(),
+ theme_name,
+ self.theme_size,
+ )
+ .log_err()
{
self.theme = Some(theme);
self.theme_name = Some(theme_name.to_string());
} else if let Some(theme) =
- CursorTheme::load(&self.connection, self.shm.clone(), self.size).log_err()
+ CursorTheme::load(&self.connection, self.shm.clone(), self.theme_size).log_err()
{
self.theme = Some(theme);
self.theme_name = None;
}
}
- pub fn set_size(&mut self, size: u32) {
- self.size = size;
+ fn set_theme_size(&mut self, theme_size: u32) {
self.theme = self
.theme_name
.as_ref()
@@ -62,14 +64,29 @@ impl Cursor {
&self.connection,
self.shm.clone(),
name.as_str(),
- self.size,
+ theme_size,
)
.log_err()
})
- .or_else(|| CursorTheme::load(&self.connection, self.shm.clone(), self.size).log_err());
+ .or_else(|| {
+ CursorTheme::load(&self.connection, self.shm.clone(), theme_size).log_err()
+ });
+ }
+
+ pub fn set_size(&mut self, size: u32) {
+ self.size = size;
+ self.set_theme_size(size);
}
- pub fn set_icon(&mut self, wl_pointer: &WlPointer, serial_id: u32, mut cursor_icon_name: &str) {
+ pub fn set_icon(
+ &mut self,
+ wl_pointer: &WlPointer,
+ serial_id: u32,
+ mut cursor_icon_name: &str,
+ scale: i32,
+ ) {
+ self.set_theme_size(self.size * scale as u32);
+
if let Some(theme) = &mut self.theme {
let mut buffer: Option<&CursorImageBuffer>;
@@ -91,7 +108,15 @@ impl Cursor {
let (width, height) = buffer.dimensions();
let (hot_x, hot_y) = buffer.hotspot();
- wl_pointer.set_cursor(serial_id, Some(&self.surface), hot_x as i32, hot_y as i32);
+ self.surface.set_buffer_scale(scale);
+
+ wl_pointer.set_cursor(
+ serial_id,
+ Some(&self.surface),
+ hot_x as i32 / scale,
+ hot_y as i32 / scale,
+ );
+
self.surface.attach(Some(&buffer), 0, 0);
self.surface.damage(0, 0, width as i32, height as i32);
self.surface.commit();
@@ -194,6 +194,23 @@ impl WaylandWindowState {
self.decorations == WindowDecorations::Client
|| self.background_appearance != WindowBackgroundAppearance::Opaque
}
+
+ pub fn primary_output_scale(&mut self) -> i32 {
+ let mut scale = 1;
+ let mut current_output = self.display.take();
+ for (id, output) in self.outputs.iter() {
+ if let Some((_, output_data)) = ¤t_output {
+ if output.scale > output_data.scale {
+ current_output = Some((id.clone(), output.clone()));
+ }
+ } else {
+ current_output = Some((id.clone(), output.clone()));
+ }
+ scale = scale.max(output.scale);
+ }
+ self.display = current_output;
+ scale
+ }
}
pub(crate) struct WaylandWindow(pub WaylandWindowStatePtr);
@@ -560,7 +577,7 @@ impl WaylandWindowStatePtr {
state.outputs.insert(id, output.clone());
- let scale = primary_output_scale(&mut state);
+ let scale = state.primary_output_scale();
// We use `PreferredBufferScale` instead to set the scale if it's available
if state.surface.version() < wl_surface::EVT_PREFERRED_BUFFER_SCALE_SINCE {
@@ -572,7 +589,7 @@ impl WaylandWindowStatePtr {
wl_surface::Event::Leave { output } => {
state.outputs.remove(&output.id());
- let scale = primary_output_scale(&mut state);
+ let scale = state.primary_output_scale();
// We use `PreferredBufferScale` instead to set the scale if it's available
if state.surface.version() < wl_surface::EVT_PREFERRED_BUFFER_SCALE_SINCE {
@@ -719,6 +736,10 @@ impl WaylandWindowStatePtr {
(fun)()
}
}
+
+ pub fn primary_output_scale(&self) -> i32 {
+ self.state.borrow_mut().primary_output_scale()
+ }
}
fn extract_states<'a, S: TryFrom<u32> + 'a>(states: &'a [u8]) -> impl Iterator<Item = S> + 'a
@@ -732,23 +753,6 @@ where
.flat_map(S::try_from)
}
-fn primary_output_scale(state: &mut RefMut<WaylandWindowState>) -> i32 {
- let mut scale = 1;
- let mut current_output = state.display.take();
- for (id, output) in state.outputs.iter() {
- if let Some((_, output_data)) = ¤t_output {
- if output.scale > output_data.scale {
- current_output = Some((id.clone(), output.clone()));
- }
- } else {
- current_output = Some((id.clone(), output.clone()));
- }
- scale = scale.max(output.scale);
- }
- state.display = current_output;
- scale
-}
-
impl rwh::HasWindowHandle for WaylandWindow {
fn window_handle(&self) -> Result<rwh::WindowHandle<'_>, rwh::HandleError> {
unimplemented!()
@@ -42,11 +42,13 @@ impl XDPEventSource {
{
sender.send(Event::CursorTheme(initial_theme))?;
}
+
+ // If u32 is used here, it throws invalid type error
if let Ok(initial_size) = settings
- .read::<u32>("org.gnome.desktop.interface", "cursor-size")
+ .read::<i32>("org.gnome.desktop.interface", "cursor-size")
.await
{
- sender.send(Event::CursorSize(initial_size))?;
+ sender.send(Event::CursorSize(initial_size as u32))?;
}
if let Ok(mut cursor_theme_changed) = settings
@@ -69,7 +71,7 @@ impl XDPEventSource {
}
if let Ok(mut cursor_size_changed) = settings
- .receive_setting_changed_with_args::<u32>(
+ .receive_setting_changed_with_args::<i32>(
"org.gnome.desktop.interface",
"cursor-size",
)
@@ -80,7 +82,7 @@ impl XDPEventSource {
.spawn(async move {
while let Some(size) = cursor_size_changed.next().await {
let size = size?;
- sender.send(Event::CursorSize(size))?;
+ sender.send(Event::CursorSize(size as u32))?;
}
anyhow::Ok(())
})