mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 13:51:30 +11:00
Use cursor-icon
crate for CursorIcon
This crate is aimed to simplify handling of cursor icon across various crates and be used in the public API.
This commit is contained in:
parent
596c0edf0f
commit
bd9cc2a9da
|
@ -8,6 +8,9 @@ And please only add new entries to the top of this list, right below the `# Unre
|
|||
|
||||
# Unreleased
|
||||
|
||||
- **Breaking:** `CursorIcon` is now used from the `cursor-icon` crate.
|
||||
- **Breaking:** `CursorIcon::Hand` is now named `CursorIcon::Pointer`.
|
||||
- **Breaking:** `CursorIcon::Arrow` was removed.
|
||||
- On macOS, fixed memory leak when getting monitor handle.
|
||||
- On Wayland, fix maximized startup not taking full size on GNOME.
|
||||
- On Wayland, fix initial window size not restored for maximized/fullscreened on startup window.
|
||||
|
|
|
@ -44,12 +44,14 @@ wayland-csd-adwaita-crossfont = ["sctk-adwaita", "sctk-adwaita/crossfont"]
|
|||
wayland-csd-adwaita-notitle = ["sctk-adwaita"]
|
||||
android-native-activity = ["android-activity/native-activity"]
|
||||
android-game-activity = ["android-activity/game-activity"]
|
||||
serde = ["dep:serde", "cursor-icon/serde"]
|
||||
|
||||
[build-dependencies]
|
||||
cfg_aliases = "0.1.1"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1"
|
||||
cursor-icon = "1.0.0"
|
||||
instant = { version = "0.1", features = ["wasm-bindgen"] }
|
||||
log = "0.4"
|
||||
mint = { version = "0.5.6", optional = true }
|
||||
|
|
|
@ -54,8 +54,7 @@ fn main() {
|
|||
const CURSORS: &[CursorIcon] = &[
|
||||
CursorIcon::Default,
|
||||
CursorIcon::Crosshair,
|
||||
CursorIcon::Hand,
|
||||
CursorIcon::Arrow,
|
||||
CursorIcon::Pointer,
|
||||
CursorIcon::Move,
|
||||
CursorIcon::Text,
|
||||
CursorIcon::Wait,
|
||||
|
|
|
@ -547,63 +547,22 @@ impl WindowState {
|
|||
return;
|
||||
}
|
||||
|
||||
let cursors: &[&str] = match cursor_icon {
|
||||
CursorIcon::Alias => &["link"],
|
||||
CursorIcon::Arrow => &["arrow"],
|
||||
CursorIcon::Cell => &["plus"],
|
||||
CursorIcon::Copy => &["copy"],
|
||||
CursorIcon::Crosshair => &["crosshair"],
|
||||
CursorIcon::Default => &["left_ptr"],
|
||||
CursorIcon::Hand => &["hand2", "hand1"],
|
||||
CursorIcon::Help => &["question_arrow"],
|
||||
CursorIcon::Move => &["move"],
|
||||
CursorIcon::Grab => &["openhand", "grab"],
|
||||
CursorIcon::Grabbing => &["closedhand", "grabbing"],
|
||||
CursorIcon::Progress => &["progress"],
|
||||
CursorIcon::AllScroll => &["all-scroll"],
|
||||
CursorIcon::ContextMenu => &["context-menu"],
|
||||
|
||||
CursorIcon::NoDrop => &["no-drop", "circle"],
|
||||
CursorIcon::NotAllowed => &["crossed_circle"],
|
||||
|
||||
// Resize cursors
|
||||
CursorIcon::EResize => &["right_side"],
|
||||
CursorIcon::NResize => &["top_side"],
|
||||
CursorIcon::NeResize => &["top_right_corner"],
|
||||
CursorIcon::NwResize => &["top_left_corner"],
|
||||
CursorIcon::SResize => &["bottom_side"],
|
||||
CursorIcon::SeResize => &["bottom_right_corner"],
|
||||
CursorIcon::SwResize => &["bottom_left_corner"],
|
||||
CursorIcon::WResize => &["left_side"],
|
||||
CursorIcon::EwResize => &["h_double_arrow"],
|
||||
CursorIcon::NsResize => &["v_double_arrow"],
|
||||
CursorIcon::NwseResize => &["bd_double_arrow", "size_fdiag"],
|
||||
CursorIcon::NeswResize => &["fd_double_arrow", "size_bdiag"],
|
||||
CursorIcon::ColResize => &["split_h", "h_double_arrow"],
|
||||
CursorIcon::RowResize => &["split_v", "v_double_arrow"],
|
||||
CursorIcon::Text => &["text", "xterm"],
|
||||
CursorIcon::VerticalText => &["vertical-text"],
|
||||
|
||||
CursorIcon::Wait => &["watch"],
|
||||
|
||||
CursorIcon::ZoomIn => &["zoom-in"],
|
||||
CursorIcon::ZoomOut => &["zoom-out"],
|
||||
};
|
||||
|
||||
self.apply_on_poiner(|pointer, data| {
|
||||
let surface = data.cursor_surface();
|
||||
let scale_factor = surface.data::<SurfaceData>().unwrap().scale_factor();
|
||||
|
||||
for cursor in cursors {
|
||||
if pointer
|
||||
.set_cursor(&self.connection, cursor, &self.shm, surface, scale_factor)
|
||||
.is_ok()
|
||||
{
|
||||
return;
|
||||
}
|
||||
if pointer
|
||||
.set_cursor(
|
||||
&self.connection,
|
||||
cursor_icon.name(),
|
||||
&self.shm,
|
||||
surface,
|
||||
scale_factor,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
warn!("Failed to set cursor to {:?}", cursor_icon);
|
||||
}
|
||||
|
||||
warn!("Failed to set cursor to {:?}", cursor_icon);
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::ffi::CString;
|
||||
|
||||
use crate::window::CursorIcon;
|
||||
|
||||
use super::*;
|
||||
|
@ -45,78 +47,15 @@ impl XConnection {
|
|||
}
|
||||
}
|
||||
|
||||
fn load_cursor(&self, name: &[u8]) -> ffi::Cursor {
|
||||
unsafe {
|
||||
(self.xcursor.XcursorLibraryLoadCursor)(self.display, name.as_ptr() as *const c_char)
|
||||
}
|
||||
}
|
||||
|
||||
fn load_first_existing_cursor(&self, names: &[&[u8]]) -> ffi::Cursor {
|
||||
for name in names.iter() {
|
||||
let xcursor = self.load_cursor(name);
|
||||
if xcursor != 0 {
|
||||
return xcursor;
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
fn get_cursor(&self, cursor: Option<CursorIcon>) -> ffi::Cursor {
|
||||
let cursor = match cursor {
|
||||
Some(cursor) => cursor,
|
||||
None => return self.create_empty_cursor(),
|
||||
};
|
||||
|
||||
let load = |name: &[u8]| self.load_cursor(name);
|
||||
|
||||
let loadn = |names: &[&[u8]]| self.load_first_existing_cursor(names);
|
||||
|
||||
// Try multiple names in some cases where the name
|
||||
// differs on the desktop environments or themes.
|
||||
//
|
||||
// Try the better looking (or more suiting) names first.
|
||||
match cursor {
|
||||
CursorIcon::Alias => load(b"link\0"),
|
||||
CursorIcon::Arrow => load(b"arrow\0"),
|
||||
CursorIcon::Cell => load(b"plus\0"),
|
||||
CursorIcon::Copy => load(b"copy\0"),
|
||||
CursorIcon::Crosshair => load(b"crosshair\0"),
|
||||
CursorIcon::Default => load(b"left_ptr\0"),
|
||||
CursorIcon::Hand => loadn(&[b"hand2\0", b"hand1\0"]),
|
||||
CursorIcon::Help => load(b"question_arrow\0"),
|
||||
CursorIcon::Move => load(b"move\0"),
|
||||
CursorIcon::Grab => loadn(&[b"openhand\0", b"grab\0"]),
|
||||
CursorIcon::Grabbing => loadn(&[b"closedhand\0", b"grabbing\0"]),
|
||||
CursorIcon::Progress => load(b"left_ptr_watch\0"),
|
||||
CursorIcon::AllScroll => load(b"all-scroll\0"),
|
||||
CursorIcon::ContextMenu => load(b"context-menu\0"),
|
||||
|
||||
CursorIcon::NoDrop => loadn(&[b"no-drop\0", b"circle\0"]),
|
||||
CursorIcon::NotAllowed => load(b"crossed_circle\0"),
|
||||
|
||||
// Resize cursors
|
||||
CursorIcon::EResize => load(b"right_side\0"),
|
||||
CursorIcon::NResize => load(b"top_side\0"),
|
||||
CursorIcon::NeResize => load(b"top_right_corner\0"),
|
||||
CursorIcon::NwResize => load(b"top_left_corner\0"),
|
||||
CursorIcon::SResize => load(b"bottom_side\0"),
|
||||
CursorIcon::SeResize => load(b"bottom_right_corner\0"),
|
||||
CursorIcon::SwResize => load(b"bottom_left_corner\0"),
|
||||
CursorIcon::WResize => load(b"left_side\0"),
|
||||
CursorIcon::EwResize => load(b"h_double_arrow\0"),
|
||||
CursorIcon::NsResize => load(b"v_double_arrow\0"),
|
||||
CursorIcon::NwseResize => loadn(&[b"bd_double_arrow\0", b"size_fdiag\0"]),
|
||||
CursorIcon::NeswResize => loadn(&[b"fd_double_arrow\0", b"size_bdiag\0"]),
|
||||
CursorIcon::ColResize => loadn(&[b"split_h\0", b"h_double_arrow\0"]),
|
||||
CursorIcon::RowResize => loadn(&[b"split_v\0", b"v_double_arrow\0"]),
|
||||
|
||||
CursorIcon::Text => loadn(&[b"text\0", b"xterm\0"]),
|
||||
CursorIcon::VerticalText => load(b"vertical-text\0"),
|
||||
|
||||
CursorIcon::Wait => load(b"watch\0"),
|
||||
|
||||
CursorIcon::ZoomIn => load(b"zoom-in\0"),
|
||||
CursorIcon::ZoomOut => load(b"zoom-out\0"),
|
||||
let name = CString::new(cursor.name()).unwrap();
|
||||
unsafe {
|
||||
(self.xcursor.XcursorLibraryLoadCursor)(self.display, name.as_ptr() as *const c_char)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -197,8 +197,7 @@ impl NSCursor {
|
|||
pub fn from_icon(icon: CursorIcon) -> Id<Self, Shared> {
|
||||
match icon {
|
||||
CursorIcon::Default => Default::default(),
|
||||
CursorIcon::Arrow => Self::arrowCursor(),
|
||||
CursorIcon::Hand => Self::pointingHandCursor(),
|
||||
CursorIcon::Pointer => Self::pointingHandCursor(),
|
||||
CursorIcon::Grab => Self::openHandCursor(),
|
||||
CursorIcon::Grabbing => Self::closedHandCursor(),
|
||||
CursorIcon::Text => Self::IBeamCursor(),
|
||||
|
@ -228,6 +227,7 @@ impl NSCursor {
|
|||
CursorIcon::Wait | CursorIcon::Progress => Self::busyButClickableCursor(),
|
||||
CursorIcon::Move | CursorIcon::AllScroll => Self::moveCursor(),
|
||||
CursorIcon::Cell => Self::cellCursor(),
|
||||
_ => Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -192,47 +192,8 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn set_cursor_icon(&self, cursor: CursorIcon) {
|
||||
let text = match cursor {
|
||||
CursorIcon::Default => "auto",
|
||||
CursorIcon::Crosshair => "crosshair",
|
||||
CursorIcon::Hand => "pointer",
|
||||
CursorIcon::Arrow => "default",
|
||||
CursorIcon::Move => "move",
|
||||
CursorIcon::Text => "text",
|
||||
CursorIcon::Wait => "wait",
|
||||
CursorIcon::Help => "help",
|
||||
CursorIcon::Progress => "progress",
|
||||
|
||||
CursorIcon::NotAllowed => "not-allowed",
|
||||
CursorIcon::ContextMenu => "context-menu",
|
||||
CursorIcon::Cell => "cell",
|
||||
CursorIcon::VerticalText => "vertical-text",
|
||||
CursorIcon::Alias => "alias",
|
||||
CursorIcon::Copy => "copy",
|
||||
CursorIcon::NoDrop => "no-drop",
|
||||
CursorIcon::Grab => "grab",
|
||||
CursorIcon::Grabbing => "grabbing",
|
||||
CursorIcon::AllScroll => "all-scroll",
|
||||
CursorIcon::ZoomIn => "zoom-in",
|
||||
CursorIcon::ZoomOut => "zoom-out",
|
||||
|
||||
CursorIcon::EResize => "e-resize",
|
||||
CursorIcon::NResize => "n-resize",
|
||||
CursorIcon::NeResize => "ne-resize",
|
||||
CursorIcon::NwResize => "nw-resize",
|
||||
CursorIcon::SResize => "s-resize",
|
||||
CursorIcon::SeResize => "se-resize",
|
||||
CursorIcon::SwResize => "sw-resize",
|
||||
CursorIcon::WResize => "w-resize",
|
||||
CursorIcon::EwResize => "ew-resize",
|
||||
CursorIcon::NsResize => "ns-resize",
|
||||
CursorIcon::NeswResize => "nesw-resize",
|
||||
CursorIcon::NwseResize => "nwse-resize",
|
||||
CursorIcon::ColResize => "col-resize",
|
||||
CursorIcon::RowResize => "row-resize",
|
||||
};
|
||||
*self.previous_pointer.borrow_mut() = text;
|
||||
backend::set_canvas_style_property(self.canvas.borrow().raw(), "cursor", text);
|
||||
*self.previous_pointer.borrow_mut() = cursor.name();
|
||||
backend::set_canvas_style_property(self.canvas.borrow().raw(), "cursor", cursor.name());
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -2026,7 +2026,7 @@ unsafe fn public_window_callback_inner<T: 'static>(
|
|||
|
||||
match set_cursor_to {
|
||||
Some(cursor) => {
|
||||
let cursor = LoadCursorW(0, cursor.to_windows_cursor());
|
||||
let cursor = LoadCursorW(0, util::to_windows_cursor(cursor));
|
||||
SetCursor(cursor);
|
||||
0
|
||||
}
|
||||
|
|
|
@ -164,32 +164,30 @@ pub fn get_instance_handle() -> HINSTANCE {
|
|||
unsafe { &__ImageBase as *const _ as _ }
|
||||
}
|
||||
|
||||
impl CursorIcon {
|
||||
pub(crate) fn to_windows_cursor(self) -> PCWSTR {
|
||||
match self {
|
||||
CursorIcon::Arrow | CursorIcon::Default => IDC_ARROW,
|
||||
CursorIcon::Hand => IDC_HAND,
|
||||
CursorIcon::Crosshair => IDC_CROSS,
|
||||
CursorIcon::Text | CursorIcon::VerticalText => IDC_IBEAM,
|
||||
CursorIcon::NotAllowed | CursorIcon::NoDrop => IDC_NO,
|
||||
CursorIcon::Grab | CursorIcon::Grabbing | CursorIcon::Move | CursorIcon::AllScroll => {
|
||||
IDC_SIZEALL
|
||||
}
|
||||
CursorIcon::EResize
|
||||
| CursorIcon::WResize
|
||||
| CursorIcon::EwResize
|
||||
| CursorIcon::ColResize => IDC_SIZEWE,
|
||||
CursorIcon::NResize
|
||||
| CursorIcon::SResize
|
||||
| CursorIcon::NsResize
|
||||
| CursorIcon::RowResize => IDC_SIZENS,
|
||||
CursorIcon::NeResize | CursorIcon::SwResize | CursorIcon::NeswResize => IDC_SIZENESW,
|
||||
CursorIcon::NwResize | CursorIcon::SeResize | CursorIcon::NwseResize => IDC_SIZENWSE,
|
||||
CursorIcon::Wait => IDC_WAIT,
|
||||
CursorIcon::Progress => IDC_APPSTARTING,
|
||||
CursorIcon::Help => IDC_HELP,
|
||||
_ => IDC_ARROW, // use arrow for the missing cases.
|
||||
pub(crate) fn to_windows_cursor(cursor: CursorIcon) -> PCWSTR {
|
||||
match cursor {
|
||||
CursorIcon::Default => IDC_ARROW,
|
||||
CursorIcon::Pointer => IDC_HAND,
|
||||
CursorIcon::Crosshair => IDC_CROSS,
|
||||
CursorIcon::Text | CursorIcon::VerticalText => IDC_IBEAM,
|
||||
CursorIcon::NotAllowed | CursorIcon::NoDrop => IDC_NO,
|
||||
CursorIcon::Grab | CursorIcon::Grabbing | CursorIcon::Move | CursorIcon::AllScroll => {
|
||||
IDC_SIZEALL
|
||||
}
|
||||
CursorIcon::EResize
|
||||
| CursorIcon::WResize
|
||||
| CursorIcon::EwResize
|
||||
| CursorIcon::ColResize => IDC_SIZEWE,
|
||||
CursorIcon::NResize
|
||||
| CursorIcon::SResize
|
||||
| CursorIcon::NsResize
|
||||
| CursorIcon::RowResize => IDC_SIZENS,
|
||||
CursorIcon::NeResize | CursorIcon::SwResize | CursorIcon::NeswResize => IDC_SIZENESW,
|
||||
CursorIcon::NwResize | CursorIcon::SeResize | CursorIcon::NwseResize => IDC_SIZENWSE,
|
||||
CursorIcon::Wait => IDC_WAIT,
|
||||
CursorIcon::Progress => IDC_APPSTARTING,
|
||||
CursorIcon::Help => IDC_HELP,
|
||||
_ => IDC_ARROW, // use arrow for the missing cases.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -333,7 +333,7 @@ impl Window {
|
|||
pub fn set_cursor_icon(&self, cursor: CursorIcon) {
|
||||
self.window_state_lock().mouse.cursor = cursor;
|
||||
self.thread_executor.execute_in_thread(move || unsafe {
|
||||
let cursor = LoadCursorW(0, cursor.to_windows_cursor());
|
||||
let cursor = LoadCursorW(0, util::to_windows_cursor(cursor));
|
||||
SetCursor(cursor);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@ use crate::{
|
|||
|
||||
pub use crate::icon::{BadIcon, Icon};
|
||||
|
||||
#[doc(inline)]
|
||||
pub use cursor_icon::{CursorIcon, ParseError as CursorIconParseError};
|
||||
|
||||
/// Represents a window.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -1388,66 +1391,6 @@ pub enum CursorGrabMode {
|
|||
Locked,
|
||||
}
|
||||
|
||||
/// Describes the appearance of the mouse cursor.
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum CursorIcon {
|
||||
/// The platform-dependent default cursor.
|
||||
#[default]
|
||||
Default,
|
||||
/// A simple crosshair.
|
||||
Crosshair,
|
||||
/// A hand (often used to indicate links in web browsers).
|
||||
Hand,
|
||||
/// Self explanatory.
|
||||
Arrow,
|
||||
/// Indicates something is to be moved.
|
||||
Move,
|
||||
/// Indicates text that may be selected or edited.
|
||||
Text,
|
||||
/// Program busy indicator.
|
||||
Wait,
|
||||
/// Help indicator (often rendered as a "?")
|
||||
Help,
|
||||
/// Progress indicator. Shows that processing is being done. But in contrast
|
||||
/// with "Wait" the user may still interact with the program. Often rendered
|
||||
/// as a spinning beach ball, or an arrow with a watch or hourglass.
|
||||
Progress,
|
||||
|
||||
/// Cursor showing that something cannot be done.
|
||||
NotAllowed,
|
||||
ContextMenu,
|
||||
Cell,
|
||||
VerticalText,
|
||||
Alias,
|
||||
Copy,
|
||||
NoDrop,
|
||||
/// Indicates something can be grabbed.
|
||||
Grab,
|
||||
/// Indicates something is grabbed.
|
||||
Grabbing,
|
||||
AllScroll,
|
||||
ZoomIn,
|
||||
ZoomOut,
|
||||
|
||||
/// Indicate that some edge is to be moved. For example, the 'SeResize' cursor
|
||||
/// is used when the movement starts from the south-east corner of the box.
|
||||
EResize,
|
||||
NResize,
|
||||
NeResize,
|
||||
NwResize,
|
||||
SResize,
|
||||
SeResize,
|
||||
SwResize,
|
||||
WResize,
|
||||
EwResize,
|
||||
NsResize,
|
||||
NeswResize,
|
||||
NwseResize,
|
||||
ColResize,
|
||||
RowResize,
|
||||
}
|
||||
|
||||
/// Defines the orientation that a window resize will be performed.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum ResizeDirection {
|
||||
|
|
Loading…
Reference in a new issue