mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-11 05:00:16 +00:00
x11: Cursor style support (#11237)
Adds cursor style support to X11 ![image](https://github.com/zed-industries/zed/assets/71973804/e5a2414f-4d80-4963-93d2-e4a15878a718) Release Notes: - N/A
This commit is contained in:
parent
bb1817ff31
commit
091e7cb395
2 changed files with 61 additions and 9 deletions
|
@ -120,6 +120,7 @@ x11rb = { version = "0.13.0", features = [
|
|||
"xkb",
|
||||
"randr",
|
||||
"xinput",
|
||||
"cursor",
|
||||
"resource_manager",
|
||||
] }
|
||||
xkbcommon = { version = "0.7", features = ["wayland", "x11"] }
|
||||
|
|
|
@ -3,19 +3,21 @@ use std::ops::Deref;
|
|||
use std::rc::{Rc, Weak};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use calloop::{EventLoop, LoopHandle};
|
||||
use calloop::generic::{FdWrapper, Generic};
|
||||
use calloop::{EventLoop, LoopHandle, RegistrationToken};
|
||||
use collections::HashMap;
|
||||
use copypasta::x11_clipboard::{Clipboard, Primary, X11ClipboardContext};
|
||||
use copypasta::ClipboardProvider;
|
||||
|
||||
use util::ResultExt;
|
||||
use x11rb::connection::{Connection, RequestConnection};
|
||||
use x11rb::cursor;
|
||||
use x11rb::errors::ConnectionError;
|
||||
use x11rb::protocol::randr::ConnectionExt as _;
|
||||
use x11rb::protocol::xinput::{ConnectionExt, ScrollClass};
|
||||
use x11rb::protocol::xkb::ConnectionExt as _;
|
||||
use x11rb::protocol::xproto::ConnectionExt as _;
|
||||
use x11rb::protocol::{randr, xinput, xkb, xproto, Event};
|
||||
use x11rb::protocol::xproto::{ChangeWindowAttributesAux, ConnectionExt as _};
|
||||
use x11rb::protocol::{randr, render, xinput, xkb, xproto, Event};
|
||||
use x11rb::resource_manager::Database;
|
||||
use x11rb::xcb_ffi::XCBConnection;
|
||||
use xkbc::x11::ffi::{XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION};
|
||||
|
@ -36,10 +38,6 @@ use super::{
|
|||
use super::{button_of_key, modifiers_from_state};
|
||||
use crate::platform::linux::is_within_click_distance;
|
||||
use crate::platform::linux::platform::DOUBLE_CLICK_INTERVAL;
|
||||
use calloop::{
|
||||
generic::{FdWrapper, Generic},
|
||||
RegistrationToken,
|
||||
};
|
||||
|
||||
pub(crate) struct WindowRef {
|
||||
window: X11WindowStatePtr,
|
||||
|
@ -72,6 +70,10 @@ pub struct X11ClientState {
|
|||
pub(crate) focused_window: Option<xproto::Window>,
|
||||
pub(crate) xkb: xkbc::State,
|
||||
|
||||
pub(crate) cursor_handle: cursor::Handle,
|
||||
pub(crate) cursor_styles: HashMap<xproto::Window, CursorStyle>,
|
||||
pub(crate) cursor_cache: HashMap<CursorStyle, xproto::Cursor>,
|
||||
|
||||
pub(crate) scroll_class_data: Vec<xinput::DeviceClassDataScroll>,
|
||||
pub(crate) scroll_x: Option<f32>,
|
||||
pub(crate) scroll_y: Option<f32>,
|
||||
|
@ -93,6 +95,8 @@ impl X11ClientStatePtr {
|
|||
state.loop_handle.remove(window_ref.refresh_event_token);
|
||||
}
|
||||
|
||||
state.cursor_styles.remove(&x_window);
|
||||
|
||||
if state.windows.is_empty() {
|
||||
state.common.signal.stop();
|
||||
}
|
||||
|
@ -123,6 +127,9 @@ impl X11Client {
|
|||
xcb_connection
|
||||
.prefetch_extension_information(randr::X11_EXTENSION_NAME)
|
||||
.unwrap();
|
||||
xcb_connection
|
||||
.prefetch_extension_information(render::X11_EXTENSION_NAME)
|
||||
.unwrap();
|
||||
xcb_connection
|
||||
.prefetch_extension_information(xinput::X11_EXTENSION_NAME)
|
||||
.unwrap();
|
||||
|
@ -210,6 +217,11 @@ impl X11Client {
|
|||
.map(|dpi: f32| dpi / 96.0)
|
||||
.unwrap_or(1.0);
|
||||
|
||||
let cursor_handle = cursor::Handle::new(&xcb_connection, x_root_index, &resource_database)
|
||||
.unwrap()
|
||||
.reply()
|
||||
.unwrap();
|
||||
|
||||
let clipboard = X11ClipboardContext::<Clipboard>::new().unwrap();
|
||||
let primary = X11ClipboardContext::<Primary>::new().unwrap();
|
||||
|
||||
|
@ -254,6 +266,10 @@ impl X11Client {
|
|||
focused_window: None,
|
||||
xkb: xkb_state,
|
||||
|
||||
cursor_handle,
|
||||
cursor_styles: HashMap::default(),
|
||||
cursor_cache: HashMap::default(),
|
||||
|
||||
scroll_class_data,
|
||||
scroll_x: None,
|
||||
scroll_y: None,
|
||||
|
@ -672,8 +688,43 @@ impl LinuxClient for X11Client {
|
|||
Box::new(window)
|
||||
}
|
||||
|
||||
//todo(linux)
|
||||
fn set_cursor_style(&self, _style: CursorStyle) {}
|
||||
fn set_cursor_style(&self, style: CursorStyle) {
|
||||
let mut state = self.0.borrow_mut();
|
||||
let Some(focused_window) = state.focused_window else {
|
||||
return;
|
||||
};
|
||||
let current_style = state
|
||||
.cursor_styles
|
||||
.get(&focused_window)
|
||||
.unwrap_or(&CursorStyle::Arrow);
|
||||
if *current_style == style {
|
||||
return;
|
||||
}
|
||||
|
||||
let cursor = match state.cursor_cache.get(&style) {
|
||||
Some(cursor) => *cursor,
|
||||
None => {
|
||||
let cursor = state
|
||||
.cursor_handle
|
||||
.load_cursor(&state.xcb_connection, &style.to_icon_name())
|
||||
.expect("failed to load cursor");
|
||||
state.cursor_cache.insert(style, cursor);
|
||||
cursor
|
||||
}
|
||||
};
|
||||
|
||||
state.cursor_styles.insert(focused_window, style);
|
||||
state
|
||||
.xcb_connection
|
||||
.change_window_attributes(
|
||||
focused_window,
|
||||
&ChangeWindowAttributesAux {
|
||||
cursor: Some(cursor),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.expect("failed to change window cursor");
|
||||
}
|
||||
|
||||
fn open_uri(&self, uri: &str) {
|
||||
open_uri_internal(uri, None);
|
||||
|
|
Loading…
Reference in a new issue