Split Wayland protocol handlers into dedicated modules

Move handler trait impls and delegate macros from state.rs into
handlers/{compositor,xdg_shell,input,output}.rs. Flesh out
CompositorHandler::commit with on_commit_buffer_handler and
XdgShellHandler::new_toplevel with window mapping. Add DataDeviceHandler,
SelectionHandler, ClientDndGrabHandler, and ServerDndGrabHandler impls
with DataDeviceState in the WayRay struct. State.rs now contains only
the struct definition and constructor.
This commit is contained in:
Till Wegmueller 2026-04-04 18:30:32 +02:00
parent 1f44288bce
commit 383e91addf
7 changed files with 187 additions and 127 deletions

View file

@ -0,0 +1,65 @@
use smithay::{
delegate_compositor, delegate_shm,
reexports::wayland_server::{
Client,
protocol::wl_surface::WlSurface,
},
wayland::{
buffer::BufferHandler,
compositor::{CompositorClientState, CompositorHandler, CompositorState},
shm::{ShmHandler, ShmState},
},
};
use tracing::trace;
use crate::state::WayRay;
/// Per-client state required by Smithay's compositor subsystem.
///
/// Must be stored in the client's `ClientData` so that `CompositorHandler`
/// can retrieve it. Implements `wayland_server::backend::ClientData`.
pub struct ClientState {
pub compositor_state: CompositorClientState,
}
impl smithay::reexports::wayland_server::backend::ClientData for ClientState {
fn initialized(&self, _client_id: smithay::reexports::wayland_server::backend::ClientId) {}
fn disconnected(
&self,
_client_id: smithay::reexports::wayland_server::backend::ClientId,
_reason: smithay::reexports::wayland_server::backend::DisconnectReason,
) {
}
}
impl CompositorHandler for WayRay {
fn compositor_state(&mut self) -> &mut CompositorState {
&mut self.compositor_state
}
fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {
&client.get_data::<ClientState>().unwrap().compositor_state
}
fn commit(&mut self, surface: &WlSurface) {
trace!(?surface, "surface commit");
smithay::backend::renderer::utils::on_commit_buffer_handler::<Self>(surface);
}
}
impl BufferHandler for WayRay {
fn buffer_destroyed(
&mut self,
_buffer: &smithay::reexports::wayland_server::protocol::wl_buffer::WlBuffer,
) {
}
}
impl ShmHandler for WayRay {
fn shm_state(&self) -> &ShmState {
&self.shm_state
}
}
delegate_compositor!(WayRay);
delegate_shm!(WayRay);

View file

@ -0,0 +1,43 @@
use smithay::{
delegate_data_device, delegate_seat,
input::{Seat, SeatHandler, SeatState, pointer::CursorImageStatus},
reexports::wayland_server::protocol::wl_surface::WlSurface,
wayland::selection::{
SelectionHandler,
data_device::{
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
},
},
};
use crate::state::WayRay;
impl SeatHandler for WayRay {
type KeyboardFocus = WlSurface;
type PointerFocus = WlSurface;
type TouchFocus = WlSurface;
fn seat_state(&mut self) -> &mut SeatState<Self> {
&mut self.seat_state
}
fn focus_changed(&mut self, _seat: &Seat<Self>, _focused: Option<&WlSurface>) {}
fn cursor_image(&mut self, _seat: &Seat<Self>, _image: CursorImageStatus) {}
}
impl SelectionHandler for WayRay {
type SelectionUserData = ();
}
impl ClientDndGrabHandler for WayRay {}
impl ServerDndGrabHandler for WayRay {}
impl DataDeviceHandler for WayRay {
fn data_device_state(&self) -> &DataDeviceState {
&self.data_device_state
}
}
delegate_seat!(WayRay);
delegate_data_device!(WayRay);

View file

@ -0,0 +1,6 @@
mod compositor;
mod input;
mod output;
mod xdg_shell;
pub use compositor::ClientState;

View file

@ -0,0 +1,18 @@
use smithay::{
delegate_output,
output::Output,
wayland::output::OutputHandler,
};
use crate::state::WayRay;
impl OutputHandler for WayRay {
fn output_bound(
&mut self,
_output: Output,
_wl_output: smithay::reexports::wayland_server::protocol::wl_output::WlOutput,
) {
}
}
delegate_output!(WayRay);

View file

@ -0,0 +1,43 @@
use smithay::{
delegate_xdg_shell,
desktop::Window,
reexports::wayland_server::protocol::wl_seat,
utils::Serial,
wayland::shell::xdg::{
PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
},
};
use tracing::info;
use crate::state::WayRay;
impl XdgShellHandler for WayRay {
fn xdg_shell_state(&mut self) -> &mut XdgShellState {
&mut self.xdg_shell_state
}
fn new_toplevel(&mut self, surface: ToplevelSurface) {
let window = Window::new_wayland_window(surface);
self.space.map_element(window, (0, 0), false);
info!("new toplevel mapped");
}
fn new_popup(&mut self, _surface: PopupSurface, _positioner: PositionerState) {
// TODO: handle new popups
}
fn grab(&mut self, _surface: PopupSurface, _seat: wl_seat::WlSeat, _serial: Serial) {
// TODO: handle popup grabs
}
fn reposition_request(
&mut self,
_surface: PopupSurface,
_positioner: PositionerState,
_token: u32,
) {
// TODO: handle popup reposition requests
}
}
delegate_xdg_shell!(WayRay);

View file

@ -1,4 +1,5 @@
mod errors; mod errors;
mod handlers;
mod state; mod state;
use crate::state::WayRay; use crate::state::WayRay;

View file

@ -1,41 +1,18 @@
use smithay::{ use smithay::{
delegate_compositor, delegate_output, delegate_seat, delegate_shm, delegate_xdg_shell,
desktop::Space, desktop::Space,
input::{Seat, SeatHandler, SeatState, pointer::CursorImageStatus}, input::{Seat, SeatState},
output::Output, reexports::wayland_server::{Display, DisplayHandle},
reexports::wayland_server::{ utils::{Clock, Monotonic},
Display, DisplayHandle, Client,
protocol::{wl_seat, wl_surface::WlSurface},
},
utils::{Clock, Monotonic, Serial},
wayland::{ wayland::{
buffer::BufferHandler, compositor::CompositorState,
compositor::{CompositorClientState, CompositorHandler, CompositorState}, output::OutputManagerState,
output::{OutputHandler, OutputManagerState}, selection::data_device::DataDeviceState,
shell::xdg::{XdgShellHandler, XdgShellState, ToplevelSurface, PopupSurface, PositionerState}, shell::xdg::XdgShellState,
shm::{ShmHandler, ShmState}, shm::ShmState,
}, },
}; };
use tracing::info; use tracing::info;
/// Per-client state required by Smithay's compositor subsystem.
///
/// Must be stored in the client's `ClientData` so that `CompositorHandler`
/// can retrieve it. Implements `wayland_server::backend::ClientData`.
pub struct ClientState {
pub compositor_state: CompositorClientState,
}
impl smithay::reexports::wayland_server::backend::ClientData for ClientState {
fn initialized(&self, _client_id: smithay::reexports::wayland_server::backend::ClientId) {}
fn disconnected(
&self,
_client_id: smithay::reexports::wayland_server::backend::ClientId,
_reason: smithay::reexports::wayland_server::backend::DisconnectReason,
) {
}
}
/// Central compositor state holding all Smithay subsystem states. /// Central compositor state holding all Smithay subsystem states.
/// ///
/// This is the "god struct" pattern required by Smithay — a single type that /// This is the "god struct" pattern required by Smithay — a single type that
@ -47,6 +24,7 @@ pub struct WayRay {
pub shm_state: ShmState, pub shm_state: ShmState,
pub seat_state: SeatState<Self>, pub seat_state: SeatState<Self>,
pub output_manager_state: OutputManagerState, pub output_manager_state: OutputManagerState,
pub data_device_state: DataDeviceState,
pub space: Space<smithay::desktop::Window>, pub space: Space<smithay::desktop::Window>,
pub seat: Seat<Self>, pub seat: Seat<Self>,
pub clock: Clock<Monotonic>, pub clock: Clock<Monotonic>,
@ -60,6 +38,7 @@ impl WayRay {
let compositor_state = CompositorState::new::<Self>(&dh); let compositor_state = CompositorState::new::<Self>(&dh);
let xdg_shell_state = XdgShellState::new::<Self>(&dh); let xdg_shell_state = XdgShellState::new::<Self>(&dh);
let shm_state = ShmState::new::<Self>(&dh, vec![]); let shm_state = ShmState::new::<Self>(&dh, vec![]);
let data_device_state = DataDeviceState::new::<Self>(&dh);
let mut seat_state = SeatState::new(); let mut seat_state = SeatState::new();
let seat = seat_state.new_wl_seat(&dh, "wayray"); let seat = seat_state.new_wl_seat(&dh, "wayray");
@ -75,105 +54,10 @@ impl WayRay {
shm_state, shm_state,
seat_state, seat_state,
output_manager_state, output_manager_state,
data_device_state,
space: Space::default(), space: Space::default(),
seat, seat,
clock: Clock::new(), clock: Clock::new(),
} }
} }
} }
// --- Minimal handler trait impls required by delegate macros ---
// TODO: These will be expanded and moved to handlers/ in Task 4.
impl CompositorHandler for WayRay {
fn compositor_state(&mut self) -> &mut CompositorState {
&mut self.compositor_state
}
fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {
&client.get_data::<ClientState>().unwrap().compositor_state
}
fn commit(&mut self, _surface: &WlSurface) {
// TODO: handle surface commits (Task 4)
}
}
impl XdgShellHandler for WayRay {
fn xdg_shell_state(&mut self) -> &mut XdgShellState {
&mut self.xdg_shell_state
}
fn new_toplevel(&mut self, _surface: ToplevelSurface) {
// TODO: handle new toplevel windows (Task 4)
}
fn new_popup(&mut self, _surface: PopupSurface, _positioner: PositionerState) {
// TODO: handle new popups (Task 4)
}
fn grab(&mut self, _surface: PopupSurface, _seat: wl_seat::WlSeat, _serial: Serial) {
// TODO: handle popup grabs (Task 4)
}
fn reposition_request(
&mut self,
_surface: PopupSurface,
_positioner: PositionerState,
_token: u32,
) {
// TODO: handle popup reposition requests (Task 4)
}
}
impl ShmHandler for WayRay {
fn shm_state(&self) -> &ShmState {
&self.shm_state
}
}
impl BufferHandler for WayRay {
fn buffer_destroyed(
&mut self,
_buffer: &smithay::reexports::wayland_server::protocol::wl_buffer::WlBuffer,
) {
// TODO: handle buffer destruction (Task 4)
}
}
impl SeatHandler for WayRay {
type KeyboardFocus = WlSurface;
type PointerFocus = WlSurface;
type TouchFocus = WlSurface;
fn seat_state(&mut self) -> &mut SeatState<Self> {
&mut self.seat_state
}
fn focus_changed(&mut self, _seat: &Seat<Self>, _focused: Option<&WlSurface>) {
// TODO: handle focus changes (Task 4)
}
fn cursor_image(&mut self, _seat: &Seat<Self>, _image: CursorImageStatus) {
// TODO: handle cursor image updates (Task 4)
}
}
impl OutputHandler for WayRay {
fn output_bound(
&mut self,
_output: Output,
_wl_output: smithay::reexports::wayland_server::protocol::wl_output::WlOutput,
) {
// TODO: handle output binding (Task 4)
}
}
// --- Delegate macros wiring Smithay's Dispatch impls ---
// TODO: These will be moved to handlers/ in Task 4.
delegate_compositor!(WayRay);
delegate_xdg_shell!(WayRay);
delegate_shm!(WayRay);
delegate_seat!(WayRay);
delegate_output!(WayRay);