Skip to content

Commit

Permalink
X11 shell cursors (#1755)
Browse files Browse the repository at this point in the history
  • Loading branch information
maan2003 authored May 3, 2021
1 parent 1fd8bc0 commit 20f05cc
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ You can find its changes [documented below](#070---2021-01-01).
- Fixed layout of scrollbar with very small viewports ([#1715] by [@andrewhickman])
- Fixed `WindowLevel::Tooltip` on Windows platform ([#1737] by [@djeedai])
- X11 backend now supports scaling([#1751] by [@Maan2003])
- X11 backend now supports changing cursors ([#1755] by [@Maan2003])

### Visual

Expand Down Expand Up @@ -706,6 +707,7 @@ Last release without a changelog :(
[#1746]: https://github.com/linebender/druid/pull/1746
[#1751]: https://github.com/linebender/druid/pull/1751
[#1754]: https://github.com/linebender/druid/pull/1754
[#1755]: https://github.com/linebender/druid/pull/1755

[Unreleased]: https://github.com/linebender/druid/compare/v0.7.0...master
[0.7.0]: https://github.com/linebender/druid/compare/v0.6.0...v0.7.0
Expand Down
2 changes: 1 addition & 1 deletion druid-shell/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ glib = { version = "0.10.1", optional = true }
glib-sys = { version = "0.10.0", optional = true }
gtk-sys = { version = "0.10.0", optional = true }
nix = { version = "0.18.0", optional = true }
x11rb = { version = "0.8.0", features = ["allow-unsafe-code", "present", "randr", "xfixes", "resource_manager"], optional = true }
x11rb = { version = "0.8.0", features = ["allow-unsafe-code", "present", "randr", "xfixes", "resource_manager", "cursor"], optional = true }

[target.'cfg(target_arch="wasm32")'.dependencies]
wasm-bindgen = "0.2.67"
Expand Down
33 changes: 32 additions & 1 deletion druid-shell/src/platform/x11/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use anyhow::{anyhow, Context, Error};
use x11rb::connection::Connection;
use x11rb::protocol::present::ConnectionExt as _;
use x11rb::protocol::xfixes::ConnectionExt as _;
use x11rb::protocol::xproto::{ConnectionExt, CreateWindowAux, EventMask, WindowClass};
use x11rb::protocol::xproto::{self, ConnectionExt, CreateWindowAux, EventMask, WindowClass};
use x11rb::protocol::Event;
use x11rb::resource_manager::Database as ResourceDb;
use x11rb::xcb_ffi::XCBConnection;
Expand Down Expand Up @@ -53,6 +53,7 @@ pub(crate) struct Application {

/// The X11 resource database used to query dpi.
pub(crate) rdb: ResourceDb,
pub(crate) cursors: Cursors,
/// The default screen of the connected display.
///
/// The connected display may also have additional screens.
Expand Down Expand Up @@ -92,6 +93,17 @@ struct State {
windows: HashMap<u32, Rc<Window>>,
}

#[derive(Clone, Debug)]
pub(crate) struct Cursors {
pub default: Option<xproto::Cursor>,
pub text: Option<xproto::Cursor>,
pub pointer: Option<xproto::Cursor>,
pub crosshair: Option<xproto::Cursor>,
pub not_allowed: Option<xproto::Cursor>,
pub row_resize: Option<xproto::Cursor>,
pub col_resize: Option<xproto::Cursor>,
}

impl Application {
pub fn new() -> Result<Application, Error> {
// If we want to support OpenGL, we will need to open a connection with Xlib support (see
Expand Down Expand Up @@ -126,13 +138,32 @@ impl Application {
}
};

let handle = x11rb::cursor::Handle::new(connection.as_ref(), screen_num, &rdb)?.reply()?;
let load_cursor = |cursor| {
handle
.load_cursor(connection.as_ref(), cursor)
.map_err(|e| tracing::warn!("Unable to load cursor {}, error: {}", cursor, e))
.ok()
};

let cursors = Cursors {
default: load_cursor("default"),
text: load_cursor("text"),
pointer: load_cursor("pointer"),
crosshair: load_cursor("crosshair"),
not_allowed: load_cursor("not-allowed"),
row_resize: load_cursor("row-resize"),
col_resize: load_cursor("col-resize"),
};

Ok(Application {
connection,
rdb,
screen_num: screen_num as i32,
window_id,
state,
idle_read,
cursors,
idle_write,
present_opcode,
marker: std::marker::PhantomData,
Expand Down
39 changes: 35 additions & 4 deletions druid-shell/src/platform/x11/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ use x11rb::connection::Connection;
use x11rb::protocol::present::{CompleteNotifyEvent, ConnectionExt as _, IdleNotifyEvent};
use x11rb::protocol::xfixes::{ConnectionExt as _, Region as XRegion};
use x11rb::protocol::xproto::{
self, AtomEnum, ConfigureNotifyEvent, ConnectionExt, CreateGCAux, EventMask, Gcontext, Pixmap,
PropMode, Rectangle, Visualtype, WindowClass,
self, AtomEnum, ChangeWindowAttributesAux, ConfigureNotifyEvent, ConnectionExt, CreateGCAux,
EventMask, Gcontext, Pixmap, PropMode, Rectangle, Visualtype, WindowClass,
};
use x11rb::wrapper::ConnectionExt as _;
use x11rb::xcb_ffi::XCBConnection;
Expand Down Expand Up @@ -884,6 +884,35 @@ impl Window {
));
}

fn set_cursor(&self, cursor: &Cursor) {
let cursors = &self.app.cursors;
#[allow(deprecated)]
let cursor = match cursor {
Cursor::Arrow => cursors.default,
Cursor::IBeam => cursors.text,
Cursor::Pointer => cursors.pointer,
Cursor::Crosshair => cursors.crosshair,
Cursor::OpenHand => {
warn!("Cursor::OpenHand not supported for x11 backend. using arrow cursor");
None
}
Cursor::NotAllowed => cursors.not_allowed,
Cursor::ResizeLeftRight => cursors.col_resize,
Cursor::ResizeUpDown => cursors.row_resize,
// TODO: (x11/custom cursor)
Cursor::Custom(_) => None,
};
if cursor.is_none() {
warn!("Unable to load cursor {:?}", cursor);
return;
}
let conn = self.app.connection();
let changes = ChangeWindowAttributesAux::new().cursor(cursor);
if let Err(e) = conn.change_window_attributes(self.id, &changes) {
error!("Changing cursor window attribute failed {}", e);
};
}

fn set_menu(&self, _menu: Menu) {
// TODO(x11/menus): implement Window::set_menu (currently a no-op)
}
Expand Down Expand Up @@ -1592,8 +1621,10 @@ impl WindowHandle {
}
}

pub fn set_cursor(&mut self, _cursor: &Cursor) {
// TODO(x11/cursors): implement WindowHandle::set_cursor
pub fn set_cursor(&mut self, cursor: &Cursor) {
if let Some(w) = self.window.upgrade() {
w.set_cursor(cursor);
}
}

pub fn make_cursor(&self, _cursor_desc: &CursorDesc) -> Option<Cursor> {
Expand Down

0 comments on commit 20f05cc

Please sign in to comment.