From 219ede738ea5c2ae41bfd10ddf6b99022e7a8ea2 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 5 Jul 2026 18:33:30 -0700 Subject: [PATCH] got a few low hanging fruit xdg/wl protocols out of the way --- src/handlers/mod.rs | 5 +++ src/handlers/xdg_activation.rs | 45 ++++++++++++++++++++++ src/handlers/xdg_decoration.rs | 24 ++++++++++++ src/handlers/xdg_icon.rs | 5 +++ src/handlers/xdg_system_bell.rs | 9 +++++ src/handlers/xdg_tag.rs | 5 +++ src/main.rs | 7 ++-- src/state.rs | 68 ++++++++++++++++++++++++--------- src/winit.rs | 1 - 9 files changed, 147 insertions(+), 22 deletions(-) create mode 100644 src/handlers/xdg_activation.rs create mode 100644 src/handlers/xdg_decoration.rs create mode 100644 src/handlers/xdg_icon.rs create mode 100644 src/handlers/xdg_system_bell.rs create mode 100644 src/handlers/xdg_tag.rs diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index df07d0a..2694cff 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -1,5 +1,10 @@ mod compositor; +mod xdg_activation; +mod xdg_decoration; +mod xdg_icon; mod xdg_shell; +mod xdg_system_bell; +mod xdg_tag; use crate::State; diff --git a/src/handlers/xdg_activation.rs b/src/handlers/xdg_activation.rs new file mode 100644 index 0000000..58d1d56 --- /dev/null +++ b/src/handlers/xdg_activation.rs @@ -0,0 +1,45 @@ +use smithay::{desktop::WindowSurface, wayland::xdg_activation::XdgActivationHandler}; +use wayland_server::protocol::wl_surface::WlSurface; + +use crate::State; +use smithay::desktop::space::SpaceElement; + +impl XdgActivationHandler for State { + fn activation_state(&mut self) -> &mut smithay::wayland::xdg_activation::XdgActivationState { + &mut self.xdg_activation_state + } + + fn request_activation( + &mut self, + token: smithay::wayland::xdg_activation::XdgActivationToken, + token_data: smithay::wayland::xdg_activation::XdgActivationTokenData, + surface: WlSurface, + ) { + let mut raised_element = None; + + { + for element in self.space.elements() { + match element.underlying_surface() { + WindowSurface::Wayland(wl) => { + if *wl.wl_surface() == surface { + raised_element = Some(element); + break; + } + } + WindowSurface::X11(x) => { + if let Some(wl_surface) = x.wl_surface() { + if wl_surface == surface { + raised_element = Some(element); + break; + } + } + } + } + } + } + if let Some(element) = raised_element { + element.set_activate(true); + // self.space.activ(element, true); + } + } +} diff --git a/src/handlers/xdg_decoration.rs b/src/handlers/xdg_decoration.rs new file mode 100644 index 0000000..c13d2b7 --- /dev/null +++ b/src/handlers/xdg_decoration.rs @@ -0,0 +1,24 @@ +use crate::State; +use smithay::wayland::shell::xdg::decoration::XdgDecorationHandler; +use wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode; + +impl XdgDecorationHandler for State { + fn new_decoration(&mut self, toplevel: smithay::wayland::shell::xdg::ToplevelSurface) { + println!("new_decoration"); + // todo!() + } + + fn request_mode( + &mut self, + toplevel: smithay::wayland::shell::xdg::ToplevelSurface, + mode: Mode, + ) { + println!("request_mode"); + // todo!() + } + + fn unset_mode(&mut self, toplevel: smithay::wayland::shell::xdg::ToplevelSurface) { + println!("unset_mode"); + // todo!() + } +} diff --git a/src/handlers/xdg_icon.rs b/src/handlers/xdg_icon.rs new file mode 100644 index 0000000..578fe18 --- /dev/null +++ b/src/handlers/xdg_icon.rs @@ -0,0 +1,5 @@ +use smithay::wayland::xdg_toplevel_icon::XdgToplevelIconHandler; + +use crate::State; + +impl XdgToplevelIconHandler for State {} diff --git a/src/handlers/xdg_system_bell.rs b/src/handlers/xdg_system_bell.rs new file mode 100644 index 0000000..df9672e --- /dev/null +++ b/src/handlers/xdg_system_bell.rs @@ -0,0 +1,9 @@ +use crate::State; +use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; +use smithay::wayland::xdg_system_bell::XdgSystemBellHandler; + +impl XdgSystemBellHandler for State { + fn ring(&mut self, surface: Option) { + println!("{:?} ringed!", surface); + } +} diff --git a/src/handlers/xdg_tag.rs b/src/handlers/xdg_tag.rs new file mode 100644 index 0000000..b50314a --- /dev/null +++ b/src/handlers/xdg_tag.rs @@ -0,0 +1,5 @@ +use smithay::wayland::xdg_toplevel_tag::XdgToplevelTagHandler; + +use crate::State; + +impl XdgToplevelTagHandler for State {} diff --git a/src/main.rs b/src/main.rs index ecedd53..199e733 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ mod state; mod winit; mod xwayland; -use smithay::reexports::{calloop::EventLoop, wayland_server::Display, winit::event_loop}; +use smithay::reexports::{calloop::EventLoop, wayland_server::Display}; pub use state::State; fn main() -> Result<(), Box> { @@ -17,7 +17,7 @@ fn main() -> Result<(), Box> { let mut event_loop = EventLoop::try_new()?; let display: Display = Display::new()?; - let mut state = State::new(display, event_loop.handle()); + let mut state = State::new(display, event_loop.handle())?; // Open a Wayland/X11 window for our nested compositor crate::winit::init_winit(&mut state)?; @@ -53,7 +53,8 @@ fn spawn_client() { // std::process::Command::new(command).spawn().ok(); // } _ => { - std::process::Command::new("weston-terminal").spawn().ok(); + std::process::Command::new("startmde").spawn().ok(); + std::process::Command::new("konsole").spawn().ok(); } } } diff --git a/src/state.rs b/src/state.rs index 9589c6c..f2a46b9 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,13 +1,10 @@ -use std::{ffi::OsString, sync::Arc, time::Duration}; +use std::{ffi::OsString, sync::Arc}; -use parking_lot::Mutex; use smithay::{ desktop::{PopupManager, Space, Window, WindowSurfaceType}, input::{Seat, SeatState}, reexports::{ - calloop::{ - generic::Generic, EventLoop, Interest, LoopHandle, LoopSignal, Mode, PostAction, - }, + calloop::{generic::Generic, Interest, LoopHandle, Mode, PostAction}, wayland_server::{ backend::{ClientData, ClientId, DisconnectReason}, protocol::wl_surface::WlSurface, @@ -17,11 +14,16 @@ use smithay::{ utils::{Logical, Point}, wayland::{ compositor::{CompositorClientState, CompositorState}, + fixes::FixesState, output::OutputManagerState, selection::data_device::DataDeviceState, - shell::xdg::XdgShellState, + shell::xdg::{decoration::XdgDecorationState, XdgShellState}, shm::ShmState, socket::ListeningSocketSource, + xdg_activation::XdgActivationState, + xdg_system_bell::XdgSystemBellState, + xdg_toplevel_icon::XdgToplevelIconManager, + xdg_toplevel_tag::XdgToplevelTagManager, xwayland_shell::XWaylandShellState, }, }; @@ -35,24 +37,34 @@ pub struct State { pub space: Space, pub handle: LoopHandle<'static, Self>, - // pub loop_signal: LoopSignal, + pub popups: PopupManager, + pub seat: Seat, - // Smithay State + // core pub compositor_state: CompositorState, - pub xdg_shell_state: XdgShellState, pub shm_state: ShmState, - pub output_manager_state: OutputManagerState, pub seat_state: SeatState, pub data_device_state: DataDeviceState, - pub popups: PopupManager, + pub wl_fixes_state: FixesState, - pub seat: Seat, + // xdg + pub xdg_shell_state: XdgShellState, + pub xdg_decoration_state: XdgDecorationState, + pub xdg_activation_state: XdgActivationState, + pub xdg_toplevel_icon_manager_state: XdgToplevelIconManager, + pub xdg_toplevel_tag_manager_state: XdgToplevelTagManager, + pub xdg_system_bell_state: XdgSystemBellState, + + pub output_manager_state: OutputManagerState, pub xwayland_state: XWaylandState, } impl State { - pub fn new(display: Display, handle: LoopHandle<'static, Self>) -> Self { + pub fn new( + display: Display, + handle: LoopHandle<'static, Self>, + ) -> Result> { let start_time = std::time::Instant::now(); let dh = display.handle(); @@ -64,6 +76,16 @@ impl State { // Initialize protocols needed for displaying windows let compositor_state = CompositorState::new::(&dh); let xdg_shell_state = XdgShellState::new::(&dh); + + let xdg_decoration_state = XdgDecorationState::new::(&dh); + + let xdg_shell_state = XdgShellState::new::(&dh); + let xdg_decoration_state = XdgDecorationState::new::(&dh); + let xdg_activation_state = XdgActivationState::new::(&dh); + let xdg_toplevel_icon_manager_state = XdgToplevelIconManager::new::(&dh); + let xdg_toplevel_tag_manager_state = XdgToplevelTagManager::new::(&dh); + let xdg_system_bell_state = XdgSystemBellState::new::(&dh); + let shm_state = ShmState::new::(&dh, vec![]); let popups = PopupManager::default(); @@ -72,6 +94,8 @@ impl State { // Data device is responsible for clipboard and drag-and-drop let data_device_state = DataDeviceState::new::(&dh); + let wl_fixes_state = FixesState::new::(&dh); + // A seat is a group of keyboards, pointer and touch devices. // A seat typically has a pointer and maintains a keyboard focus and a pointer focus. let mut seat_state = SeatState::new(); @@ -90,7 +114,7 @@ impl State { // Windows get a position and stacking order through mapping. // Outputs become views of a part of the Space and can be rendered via Space::render_output. let space = Space::default(); - Self::setup_xwayland(display.handle(), handle.clone()); + Self::setup_xwayland(display.handle(), handle.clone())?; let socket_name = Self::init_wayland_listener(display, handle.clone()); @@ -99,7 +123,7 @@ impl State { xwayland_shell_state: XWaylandShellState::new::(&dh), }; - Self { + Ok(Self { start_time, display_handle: dh, @@ -109,14 +133,22 @@ impl State { compositor_state, xdg_shell_state, shm_state, - output_manager_state, seat_state, data_device_state, + wl_fixes_state, + output_manager_state, + + xdg_decoration_state, + xdg_activation_state, + xdg_toplevel_icon_manager_state, + xdg_toplevel_tag_manager_state, + xdg_system_bell_state, + + xwayland_state, popups, seat, - xwayland_state, handle, - } + }) } fn init_wayland_listener( diff --git a/src/winit.rs b/src/winit.rs index 650a83c..8056036 100644 --- a/src/winit.rs +++ b/src/winit.rs @@ -9,7 +9,6 @@ use smithay::{ winit::{self, WinitEvent}, }, output::{Mode, Output, PhysicalProperties, Subpixel}, - reexports::calloop::EventLoop, utils::{Rectangle, Transform}, };