From 060bd59d01478b3dd512cf7eaff30e11fa9d1cdc Mon Sep 17 00:00:00 2001 From: Nova Date: Mon, 22 Aug 2022 07:57:03 -0400 Subject: [PATCH] feat(wayland): implement all essential handlers --- src/main.rs | 5 ++ src/wayland/compositor.rs | 23 ++++++++ src/wayland/mod.rs | 103 ++++++++++++++++++++++------------ src/wayland/xdg_decoration.rs | 36 ++++++++++++ src/wayland/xdg_shell.rs | 52 +++++++++++++++++ 5 files changed, 183 insertions(+), 36 deletions(-) create mode 100644 src/wayland/compositor.rs create mode 100644 src/wayland/xdg_decoration.rs create mode 100644 src/wayland/xdg_shell.rs diff --git a/src/main.rs b/src/main.rs index 9fdc1a1..52d4d35 100644 --- a/src/main.rs +++ b/src/main.rs @@ -121,6 +121,11 @@ fn main() -> Result<()> { }, ); + drop(wayland_state); + drop(socket); + drop(display); + println!("Cleanly shut down the Wayland compositor"); + let _ = event_stop_tx.send(()); event_thread .join() diff --git a/src/wayland/compositor.rs b/src/wayland/compositor.rs new file mode 100644 index 0000000..ed5b39c --- /dev/null +++ b/src/wayland/compositor.rs @@ -0,0 +1,23 @@ +use super::WaylandState; +use smithay::{ + backend::renderer::utils::{import_surface_tree, on_commit_buffer_handler}, + delegate_compositor, + wayland::compositor::CompositorHandler, +}; + +impl CompositorHandler for WaylandState { + fn compositor_state(&mut self) -> &mut smithay::wayland::compositor::CompositorState { + &mut self.compositor_state + } + + fn commit( + &mut self, + _dh: &smithay::reexports::wayland_server::DisplayHandle, + surface: &smithay::reexports::wayland_server::protocol::wl_surface::WlSurface, + ) { + on_commit_buffer_handler(surface); + import_surface_tree(&mut self.renderer, surface, &self.log).unwrap(); + } +} + +delegate_compositor!(WaylandState); diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index b0df5d2..0fa0292 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -1,21 +1,38 @@ +pub mod compositor; +pub mod xdg_decoration; +mod xdg_shell; use anyhow::Result; use slog::Logger; use smithay::{ backend::renderer::gles2::Gles2Renderer, + delegate_output, delegate_shm, reexports::wayland_server::{ backend::{ClientData, ClientId, DisconnectReason}, + protocol::wl_output::Subpixel, Display, DisplayHandle, }, + utils::Size, + wayland::{ + buffer::BufferHandler, + compositor::CompositorState, + output::{Output, OutputManagerState, Scale::Integer}, + seat::SeatState, + shell::xdg::{decoration::XdgDecorationState, XdgShellState}, + shm::{ShmHandler, ShmState}, + }, }; pub struct ClientState; impl ClientData for ClientState { - fn initialized(&self, _client_id: ClientId) { - println!("initialized"); + fn initialized(&self, client_id: ClientId) { + println!("Wayland client {:?} connected", client_id); } - fn disconnected(&self, _client_id: ClientId, _reason: DisconnectReason) { - println!("disconnected"); + fn disconnected(&self, client_id: ClientId, reason: DisconnectReason) { + println!( + "Wayland client {:?} disconnected because {:#?}", + client_id, reason + ); } } @@ -24,13 +41,13 @@ pub struct WaylandState { pub display_handle: DisplayHandle, pub renderer: Gles2Renderer, - // pub compositor_state: CompositorState, - // pub xdg_shell_state: XdgShellState, - // pub xdg_decoration_state: XdgDecorationState, - // pub shm_state: ShmState, - // pub output_manager_state: OutputManagerState, - // pub output: Output, - // pub seat_state: SeatState, + pub compositor_state: CompositorState, + pub xdg_shell_state: XdgShellState, + pub xdg_decoration_state: XdgDecorationState, + pub shm_state: ShmState, + pub output_manager_state: OutputManagerState, + pub output: Output, + pub seat_state: SeatState, // pub data_device_state: DataDeviceState, } @@ -42,38 +59,52 @@ impl WaylandState { ) -> Result { let display_handle = display.handle(); - // let compositor_state = CompositorState::new::(&display_handle, log.clone()); - // let xdg_shell_state = XdgShellState::new::(&display_handle, log.clone()); - // let xdg_decoration_state = XdgDecorationState::new::(&display_handle, log.clone()); - // let shm_state = ShmState::new::(&display_handle, vec![], log.clone()); - // let output_manager_state = OutputManagerState::new_with_xdg_output::(&display_handle); - // let output = Output::new( - // "1x".to_owned(), - // smithay::wayland::output::PhysicalProperties { - // size: Size::default(), - // subpixel: Subpixel::None, - // make: "Virtual XR Display".to_owned(), - // model: "Your Headset Name Here".to_owned(), - // }, - // log.clone(), - // ); - // let _global = output.create_global::(&display_handle); - // output.change_current_state(None, None, Some(Integer(2)), None); - // let seat_state = SeatState::new(); + let compositor_state = CompositorState::new::(&display_handle, log.clone()); + let xdg_shell_state = XdgShellState::new::(&display_handle, log.clone()); + let xdg_decoration_state = XdgDecorationState::new::(&display_handle, log.clone()); + let shm_state = ShmState::new::(&display_handle, vec![], log.clone()); + let output_manager_state = OutputManagerState::new_with_xdg_output::(&display_handle); + let output = Output::new( + "1x".to_owned(), + smithay::wayland::output::PhysicalProperties { + size: Size::default(), + subpixel: Subpixel::None, + make: "Virtual XR Display".to_owned(), + model: "Your Headset Name Here".to_owned(), + }, + log.clone(), + ); + let _global = output.create_global::(&display_handle); + output.change_current_state(None, None, Some(Integer(2)), None); + let seat_state = SeatState::new(); // let data_device_state = DataDeviceState::new(&dh, log.clone()); Ok(WaylandState { log, display_handle, renderer, - // compositor_state, - // xdg_shell_state, - // xdg_decoration_state, - // shm_state, - // output_manager_state, - // output, - // seat_state, + compositor_state, + xdg_shell_state, + xdg_decoration_state, + shm_state, + output_manager_state, + output, + seat_state, // data_device_state, }) } } +impl BufferHandler for WaylandState { + fn buffer_destroyed( + &mut self, + _buffer: &smithay::reexports::wayland_server::protocol::wl_buffer::WlBuffer, + ) { + } +} +impl ShmHandler for WaylandState { + fn shm_state(&self) -> &smithay::wayland::shm::ShmState { + &self.shm_state + } +} +delegate_shm!(WaylandState); +delegate_output!(WaylandState); diff --git a/src/wayland/xdg_decoration.rs b/src/wayland/xdg_decoration.rs new file mode 100644 index 0000000..32fb7ce --- /dev/null +++ b/src/wayland/xdg_decoration.rs @@ -0,0 +1,36 @@ +use smithay::{ + delegate_xdg_decoration, + reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode, + wayland::shell::xdg::decoration::XdgDecorationHandler, +}; + +use super::WaylandState; + +impl XdgDecorationHandler for WaylandState { + fn new_decoration( + &mut self, + _dh: &smithay::reexports::wayland_server::DisplayHandle, + toplevel: smithay::wayland::shell::xdg::ToplevelSurface, + ) { + toplevel.with_pending_state(|state| { + state.decoration_mode = Some(Mode::ServerSide); + }); + toplevel.send_configure(); + } + + fn request_mode( + &mut self, + _dh: &smithay::reexports::wayland_server::DisplayHandle, + _toplevel: smithay::wayland::shell::xdg::ToplevelSurface, + _mode: smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode, + ) { + } + + fn unset_mode( + &mut self, + _dh: &smithay::reexports::wayland_server::DisplayHandle, + _toplevel: smithay::wayland::shell::xdg::ToplevelSurface, + ) { + } +} +delegate_xdg_decoration!(WaylandState); diff --git a/src/wayland/xdg_shell.rs b/src/wayland/xdg_shell.rs new file mode 100644 index 0000000..0dccd91 --- /dev/null +++ b/src/wayland/xdg_shell.rs @@ -0,0 +1,52 @@ +use smithay::{ + delegate_xdg_shell, + reexports::wayland_protocols::xdg::{ + decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode, + shell::server::xdg_toplevel::State, + }, + wayland::shell::xdg::XdgShellHandler, +}; + +use super::WaylandState; + +impl XdgShellHandler for WaylandState { + fn xdg_shell_state(&mut self) -> &mut smithay::wayland::shell::xdg::XdgShellState { + &mut self.xdg_shell_state + } + + fn new_toplevel( + &mut self, + _dh: &smithay::reexports::wayland_server::DisplayHandle, + surface: smithay::wayland::shell::xdg::ToplevelSurface, + ) { + self.output + .enter(&self.display_handle, surface.wl_surface()); + surface.with_pending_state(|state| { + state.states.set(State::Fullscreen); + state.decoration_mode = Some(Mode::ServerSide); + }); + surface.send_configure(); + } + + fn new_popup( + &mut self, + _dh: &smithay::reexports::wayland_server::DisplayHandle, + surface: smithay::wayland::shell::xdg::PopupSurface, + _positioner: smithay::wayland::shell::xdg::PositionerState, + ) { + self.output + .enter(&self.display_handle, surface.wl_surface()); + let _ = surface.send_configure(); + } + + fn grab( + &mut self, + _dh: &smithay::reexports::wayland_server::DisplayHandle, + _surface: smithay::wayland::shell::xdg::PopupSurface, + _seat: smithay::reexports::wayland_server::protocol::wl_seat::WlSeat, + _serial: smithay::wayland::Serial, + ) { + todo!() + } +} +delegate_xdg_shell!(WaylandState);