Skip to content

Commit

Permalink
seat/pointer: simplify ThemedPointer handling
Browse files Browse the repository at this point in the history
This should simplify the handling of custom cursors in the user
applications by incapsulating all the necessary state in the
ThemedPointer.

The new cursor-icon crate for better compatibility across the
ecosystem, so the icon could be passed as is.

In the future we can automatically handle the `wp_cursor_shape`
under the hood.
  • Loading branch information
kchibisov committed May 6, 2023
1 parent c0eabf6 commit 79927ac
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 68 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## Unreleased

#### Breaking Changes

- `ThemedPointer::set_cursor` now takes only `Connection` and `&str`.
- `SeatState:get_pointer_with_them*` now takes `Shm` and `WlSurface` for the themed cursor.
- `ThemedPointer` now automatically releases the associated `WlPointer`.
- `CursorIcon` from `cursor-icon` crate is now used for `set_cursor` and `Frame`.

## 0.17.0 - 2023-03-28

#### Breaking Changes
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ wayland-protocols = { version = "0.30.0", features = ["client", "unstable"] }
wayland-protocols-wlr = { version = "0.1.0", features = ["client"] }
wayland-cursor = "0.30.0"
wayland-scanner = "0.30.0"
cursor-icon = { git = "https://github.com/rust-windowing/cursor-icon" }

xkbcommon = { version = "0.5", optional = true, features = ["wayland"] }
calloop = { version = "0.10.5", optional = true }
Expand Down
35 changes: 17 additions & 18 deletions examples/themed_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ use smithay_client_toolkit::{
seat::{
keyboard::{KeyEvent, KeyboardHandler, Modifiers},
pointer::{
PointerData, PointerEvent, PointerEventKind, PointerHandler, ThemeSpec, ThemedPointer,
CursorIcon, PointerData, PointerEvent, PointerEventKind, PointerHandler, ThemeSpec,
ThemedPointer,
},
Capability, SeatHandler, SeatState,
},
Expand Down Expand Up @@ -60,7 +61,6 @@ fn main() {
.expect("Failed to create pool");

let window_surface = compositor_state.create_surface(&qh);
let pointer_surface = compositor_state.create_surface(&qh);

let window =
xdg_shell_state.create_window(window_surface, WindowDecorations::ServerDefault, &qh);
Expand All @@ -80,7 +80,7 @@ fn main() {
registry_state,
seat_state,
output_state,
_compositor_state: compositor_state,
compositor_state,
subcompositor_state: Arc::new(subcompositor_state),
shm_state,
_xdg_shell_state: xdg_shell_state,
Expand All @@ -94,12 +94,11 @@ fn main() {
buffer: None,
window,
window_frame: None,
pointer_surface,
keyboard: None,
keyboard_focus: false,
themed_pointer: None,
set_cursor: false,
cursor_icon: String::from("diamond_cross"),
cursor_icon: CursorIcon::Crosshair,
};

// We don't draw immediately, the configure will notify us when to first draw.
Expand All @@ -118,7 +117,7 @@ struct SimpleWindow {
registry_state: RegistryState,
seat_state: SeatState,
output_state: OutputState,
_compositor_state: CompositorState,
compositor_state: CompositorState,
subcompositor_state: Arc<SubcompositorState>,
shm_state: Shm,
_xdg_shell_state: XdgShell,
Expand All @@ -132,12 +131,11 @@ struct SimpleWindow {
buffer: Option<Buffer>,
window: Window,
window_frame: Option<FallbackFrame<Self>>,
pointer_surface: wl_surface::WlSurface,
keyboard: Option<wl_keyboard::WlKeyboard>,
keyboard_focus: bool,
themed_pointer: Option<ThemedPointer>,
set_cursor: bool,
cursor_icon: String,
cursor_icon: CursorIcon,
}

impl CompositorHandler for SimpleWindow {
Expand Down Expand Up @@ -312,9 +310,16 @@ impl SeatHandler for SimpleWindow {
if capability == Capability::Pointer && self.themed_pointer.is_none() {
println!("Set pointer capability");
println!("Creating pointer theme");
let surface = self.compositor_state.create_surface(qh);
let themed_pointer = self
.seat_state
.get_pointer_with_theme(qh, &seat, ThemeSpec::default())
.get_pointer_with_theme(
qh,
&seat,
self.shm_state.wl_shm(),
surface,
ThemeSpec::default(),
)
.expect("Failed to create pointer");
self.themed_pointer.replace(themed_pointer);
}
Expand Down Expand Up @@ -424,7 +429,7 @@ impl PointerHandler for SimpleWindow {
.window_frame
.as_mut()
.and_then(|frame| frame.click_point_moved(&event.surface, x, y))
.unwrap_or("diamond_cross")
.unwrap_or(CursorIcon::Crosshair)
.to_owned();

if &event.surface == self.window.wl_surface() {
Expand All @@ -446,7 +451,7 @@ impl PointerHandler for SimpleWindow {
.and_then(|frame| frame.click_point_moved(&event.surface, x, y))
{
self.set_cursor = true;
self.cursor_icon = new_cursor.to_owned();
self.cursor_icon = new_cursor;
}
}
Press { button, serial, .. } | Release { button, serial, .. } => {
Expand Down Expand Up @@ -504,13 +509,7 @@ impl ShmHandler for SimpleWindow {
impl SimpleWindow {
pub fn draw(&mut self, conn: &Connection, qh: &QueueHandle<Self>) {
if self.set_cursor {
let _ = self.themed_pointer.as_mut().unwrap().set_cursor(
conn,
&self.cursor_icon,
self.shm_state.wl_shm(),
&self.pointer_surface,
1,
);
let _ = self.themed_pointer.as_mut().unwrap().set_cursor(conn, self.cursor_icon);
self.set_cursor = false;
}

Expand Down
39 changes: 32 additions & 7 deletions src/seat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ use std::{

use wayland_client::{
globals::GlobalList,
protocol::{wl_pointer, wl_seat, wl_touch},
protocol::{wl_pointer, wl_seat, wl_shm, wl_surface, wl_touch},
Connection, Dispatch, Proxy, QueueHandle,
};

use crate::registry::{ProvidesRegistryState, RegistryHandler};
use crate::{
compositor::SurfaceDataExt,
registry::{ProvidesRegistryState, RegistryHandler},
};

use self::{
pointer::{PointerData, PointerDataExt, PointerHandler, ThemeSpec, ThemedPointer, Themes},
Expand Down Expand Up @@ -130,16 +133,29 @@ impl SeatState {
/// ## Errors
///
/// This will return [`SeatError::UnsupportedCapability`] if the seat does not support a pointer.
pub fn get_pointer_with_theme<D>(
pub fn get_pointer_with_theme<D, S>(
&mut self,
qh: &QueueHandle<D>,
seat: &wl_seat::WlSeat,
shm: &wl_shm::WlShm,
surface: wl_surface::WlSurface,
theme: ThemeSpec,
) -> Result<ThemedPointer<PointerData>, SeatError>
where
D: Dispatch<wl_pointer::WlPointer, PointerData> + PointerHandler + 'static,
D: Dispatch<wl_pointer::WlPointer, PointerData>
+ Dispatch<wl_surface::WlSurface, S>
+ PointerHandler
+ 'static,
S: SurfaceDataExt + 'static,
{
self.get_pointer_with_theme_and_data(qh, seat, theme, PointerData::new(seat.clone()))
self.get_pointer_with_theme_and_data(
qh,
seat,
shm,
surface,
theme,
PointerData::new(seat.clone()),
)
}

/// Creates a pointer from a seat.
Expand Down Expand Up @@ -172,15 +188,21 @@ impl SeatState {
/// ## Errors
///
/// This will return [`SeatError::UnsupportedCapability`] if the seat does not support a pointer.
pub fn get_pointer_with_theme_and_data<D, U>(
pub fn get_pointer_with_theme_and_data<D, S, U>(
&mut self,
qh: &QueueHandle<D>,
seat: &wl_seat::WlSeat,
shm: &wl_shm::WlShm,
surface: wl_surface::WlSurface,
theme: ThemeSpec,
pointer_data: U,
) -> Result<ThemedPointer<U>, SeatError>
where
D: Dispatch<wl_pointer::WlPointer, U> + PointerHandler + 'static,
D: Dispatch<wl_pointer::WlPointer, U>
+ Dispatch<wl_surface::WlSurface, S>
+ PointerHandler
+ 'static,
S: SurfaceDataExt + 'static,
U: PointerDataExt + 'static,
{
let inner =
Expand All @@ -194,7 +216,10 @@ impl SeatState {
Ok(ThemedPointer {
themes: Arc::new(Mutex::new(Themes::new(theme))),
pointer: wl_ptr,
shm: shm.clone(),
surface,
_marker: std::marker::PhantomData,
_surface_data: std::marker::PhantomData,
})
}

Expand Down
Loading

0 comments on commit 79927ac

Please # to comment.