Skip to content

Commit

Permalink
feat: load cursor from data
Browse files Browse the repository at this point in the history
I want to add a function to load cursor from data
  • Loading branch information
Decodetalkers committed Dec 9, 2023
1 parent fdd88c4 commit 610e93a
Showing 1 changed file with 74 additions and 0 deletions.
74 changes: 74 additions & 0 deletions wayland-cursor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
//! # }
//! ```

use std::borrow::Cow;
use std::env;
use std::fs::File;
use std::io::{Error as IoError, Read, Result as IoResult, Seek, SeekFrom, Write};
Expand Down Expand Up @@ -83,6 +84,22 @@ pub struct CursorTheme {
backend: WeakBackend,
}

/// An error that occurs when a binding a global fails.
#[derive(Debug)]
pub enum CursorLoadError {
/// When give a icon name, but XCursorTheme cannot find a path
IconPathNotFound(String),

/// When the path finded before, but it cannot be opened
IconFileCannotOpen(std::io::Error),

/// When the file is opened, but cannot get the data
IconFileNotReadable(std::io::Error),

/// When the data of icon is get, but xparser cannot parse it
IconFileNotParsable,
}

impl CursorTheme {
/// Load a cursor theme from system defaults.
///
Expand Down Expand Up @@ -177,6 +194,63 @@ impl CursorTheme {
}
}

/// try to load data from theme, else, it will try to load from fallback data
///
/// This method returns [`None`] if this cursor is not provided either by the theme, or by one of its parents,
/// and the data by fallback function cannot parse it
/// fallback function will receive a enum which discribe the error, you can print some messages
/// or do some other things before return the finally fallback data
pub fn get_cursor_with_default_data<F>(&mut self, name: &str, fallback: F) -> Option<&Cursor>
where
F: Fn(CursorLoadError) -> Cow<'static, [u8]>,
{
match self.cursors.iter().position(|cursor| cursor.name == name) {
Some(i) => Some(&self.cursors[i]),

Check warning on line 208 in wayland-cursor/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

wayland-cursor/src/lib.rs#L203-L208

Added lines #L203 - L208 were not covered by tests
None => {
let cursor = self.load_cursor_with_default_data(name, self.size, fallback)?;
self.cursors.push(cursor);
self.cursors.iter().last()

Check warning on line 212 in wayland-cursor/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

wayland-cursor/src/lib.rs#L210-L212

Added lines #L210 - L212 were not covered by tests
}
}
}

Check warning on line 215 in wayland-cursor/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

wayland-cursor/src/lib.rs#L215

Added line #L215 was not covered by tests

fn load_cursor_with_default_data<F>(
&mut self,
name: &str,
size: u32,
fallback: F,
) -> Option<Cursor>
where
F: Fn(CursorLoadError) -> Cow<'static, [u8]>,
{
let conn = Connection::from_backend(self.backend.upgrade()?);
let err_reason = 'fallback: {
let Some(icon_path) = XCursorTheme::load(&self.name).load_icon(name) else {
break 'fallback CursorLoadError::IconPathNotFound(name.to_owned());

Check warning on line 229 in wayland-cursor/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

wayland-cursor/src/lib.rs#L217-L229

Added lines #L217 - L229 were not covered by tests
};
let mut icon_file = match File::open(icon_path) {
Ok(icon_file) => icon_file,
Err(e) => {
break 'fallback CursorLoadError::IconFileCannotOpen(e);

Check warning on line 234 in wayland-cursor/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

wayland-cursor/src/lib.rs#L231-L234

Added lines #L231 - L234 were not covered by tests
}
};
let mut buf = Vec::new();
let Some(images) = ({
if let Err(e) = icon_file.read_to_end(&mut buf) {
break 'fallback CursorLoadError::IconFileNotReadable(e);
}
xparser::parse_xcursor(&buf)

Check warning on line 242 in wayland-cursor/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

wayland-cursor/src/lib.rs#L237-L242

Added lines #L237 - L242 were not covered by tests
}) else {
break 'fallback CursorLoadError::IconFileNotParsable;

Check warning on line 244 in wayland-cursor/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

wayland-cursor/src/lib.rs#L244

Added line #L244 was not covered by tests
};

return Some(Cursor::new(&conn, name, self, &images, size));

Check warning on line 247 in wayland-cursor/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

wayland-cursor/src/lib.rs#L247

Added line #L247 was not covered by tests
};
let data = fallback(err_reason);
let images = xparser::parse_xcursor(data.as_ref())?;
Some(Cursor::new(&conn, name, self, &images, size))
}

Check warning on line 252 in wayland-cursor/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

wayland-cursor/src/lib.rs#L249-L252

Added lines #L249 - L252 were not covered by tests

/// This function loads a cursor, parses it and pushes the images onto the shm pool.
///
/// Keep in mind that if the cursor is already loaded, the function will make a duplicate.
Expand Down

0 comments on commit 610e93a

Please sign in to comment.