upgrade: waynest

This commit is contained in:
Nova
2025-09-26 16:32:46 -07:00
parent 96e910c450
commit 621a9c6d85
32 changed files with 774 additions and 637 deletions

97
Cargo.lock generated
View File

@@ -2215,6 +2215,41 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f"
[[package]]
name = "darling"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 2.0.104",
]
[[package]]
name = "darling_macro"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
dependencies = [
"darling_core",
"quote",
"syn 2.0.104",
]
[[package]] [[package]]
name = "dashmap" name = "dashmap"
version = "6.1.0" version = "6.1.0"
@@ -2494,7 +2529,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.52.0", "windows-sys 0.60.2",
] ]
[[package]] [[package]]
@@ -3211,6 +3246,12 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "image" name = "image"
version = "0.25.6" version = "0.25.6"
@@ -5072,7 +5113,7 @@ dependencies = [
"errno", "errno",
"libc", "libc",
"linux-raw-sys 0.4.15", "linux-raw-sys 0.4.15",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -5085,7 +5126,7 @@ dependencies = [
"errno", "errno",
"libc", "libc",
"linux-raw-sys 0.11.0", "linux-raw-sys 0.11.0",
"windows-sys 0.52.0", "windows-sys 0.60.2",
] ]
[[package]] [[package]]
@@ -5502,6 +5543,8 @@ dependencies = [
"tracy-client", "tracy-client",
"vulkano", "vulkano",
"waynest", "waynest",
"waynest-protocols",
"waynest-server",
"wgpu-hal", "wgpu-hal",
"xkbcommon-rs", "xkbcommon-rs",
"zbus", "zbus",
@@ -5694,7 +5737,7 @@ dependencies = [
"getrandom 0.3.3", "getrandom 0.3.3",
"once_cell", "once_cell",
"rustix 1.1.2", "rustix 1.1.2",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -6543,34 +6586,56 @@ dependencies = [
[[package]] [[package]]
name = "waynest" name = "waynest"
version = "0.0.26" version = "0.1.0"
source = "git+https://github.com/verdiwm/waynest.git?branch=codec-test#d03960abdd585d923cb068297487932511d997cb" source = "git+https://github.com/verdiwm/waynest.git#cbbc19ed20ba5610fcc5577375d6b743d615da31"
dependencies = [ dependencies = [
"async-trait",
"bitflags 2.9.4",
"bytes", "bytes",
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"futures-util",
"pin-project-lite", "pin-project-lite",
"rustix 1.1.2", "rustix 1.1.2",
"thiserror 2.0.16",
"tokio", "tokio",
"tokio-stream",
"tokio-util", "tokio-util",
"tracing",
"waynest-macros",
] ]
[[package]] [[package]]
name = "waynest-macros" name = "waynest-macros"
version = "0.0.26" version = "0.1.0"
source = "git+https://github.com/verdiwm/waynest.git?branch=codec-test#d03960abdd585d923cb068297487932511d997cb" source = "git+https://github.com/verdiwm/waynest.git#cbbc19ed20ba5610fcc5577375d6b743d615da31"
dependencies = [ dependencies = [
"darling",
"quote", "quote",
"syn 2.0.104", "syn 2.0.104",
] ]
[[package]]
name = "waynest-protocols"
version = "0.1.0"
source = "git+https://github.com/verdiwm/waynest.git#cbbc19ed20ba5610fcc5577375d6b743d615da31"
dependencies = [
"bitflags 2.9.4",
"futures-core",
"futures-sink",
"futures-util",
"tracing",
"waynest",
]
[[package]]
name = "waynest-server"
version = "0.1.0"
source = "git+https://github.com/verdiwm/waynest.git#cbbc19ed20ba5610fcc5577375d6b743d615da31"
dependencies = [
"async-trait",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
"tokio-stream",
"waynest",
"waynest-macros",
]
[[package]] [[package]]
name = "web-sys" name = "web-sys"
version = "0.3.77" version = "0.3.77"
@@ -6719,7 +6784,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]

View File

@@ -24,6 +24,8 @@ path = "src/main.rs"
default = ["wayland"] default = ["wayland"]
wayland = [ wayland = [
"dep:waynest", "dep:waynest",
"dep:waynest-protocols",
"dep:waynest-server",
"dep:tokio-stream", "dep:tokio-stream",
"dep:memmap2", "dep:memmap2",
"dep:drm-fourcc", "dep:drm-fourcc",
@@ -145,12 +147,14 @@ xkbcommon-rs = "0.1.0"
cosmic-text = "0.14.2" cosmic-text = "0.14.2"
# Wayland # Wayland
waynest = { git = "https://github.com/verdiwm/waynest.git", branch="codec-test", features = [ waynest = { git = "https://github.com/verdiwm/waynest.git", default-features = false, optional = true }
waynest-protocols = { git = "https://github.com/verdiwm/waynest.git", features = [
"server", "server",
"stable", "stable",
"mesa", "mesa",
"tracing", "tracing",
], default-features = false, optional = true } ], default-features = false, optional = true }
waynest-server = { git = "https://github.com/verdiwm/waynest.git", default-features = false, optional = true }
tokio-stream = { version = "0.1.17", optional = true } tokio-stream = { version = "0.1.17", optional = true }
memmap2 = { version = "0.9.5", optional = true } memmap2 = { version = "0.9.5", optional = true }
drm-fourcc = { version = "2.2.0", optional = true } drm-fourcc = { version = "2.2.0", optional = true }

View File

@@ -29,8 +29,6 @@ pub enum ServerError {
#[error("Reader error: {0}")] #[error("Reader error: {0}")]
ReaderError(#[from] ReaderError), ReaderError(#[from] ReaderError),
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
#[error("Wayland error: {0}")]
WaylandError(waynest::server::Error),
#[error("Aspect {} does not exist for node", 0.to_string())] #[error("Aspect {} does not exist for node", 0.to_string())]
NoAspect(TypeId), NoAspect(TypeId),
#[error("{0}")] #[error("{0}")]

View File

@@ -1,5 +1,5 @@
use crate::wayland::Message;
use crate::wayland::dmabuf::buffer_backing::DmabufBacking; use crate::wayland::dmabuf::buffer_backing::DmabufBacking;
use crate::wayland::{Client, Message, WaylandResult};
use crate::wayland::{MessageSink, core::shm_buffer_backing::ShmBufferBacking, util::ClientExt}; use crate::wayland::{MessageSink, core::shm_buffer_backing::ShmBufferBacking, util::ClientExt};
use bevy::{ use bevy::{
asset::{Assets, Handle}, asset::{Assets, Handle},
@@ -8,11 +8,9 @@ use bevy::{
use bevy_dmabuf::import::ImportedDmatexs; use bevy_dmabuf::import::ImportedDmatexs;
use mint::Vector2; use mint::Vector2;
use std::sync::Arc; use std::sync::Arc;
pub use waynest::server::protocol::core::wayland::wl_buffer::*; use waynest::ObjectId;
use waynest::{ pub use waynest_protocols::server::core::wayland::wl_buffer::*;
server::{Client, Dispatcher, Result}, use waynest_server::RequestDispatcher;
wire::ObjectId,
};
#[derive(Debug)] #[derive(Debug)]
pub struct BufferUsage { pub struct BufferUsage {
@@ -41,7 +39,8 @@ pub enum BufferBacking {
Dmabuf(DmabufBacking), Dmabuf(DmabufBacking),
} }
#[derive(Debug, Dispatcher)] #[derive(Debug, RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Buffer { pub struct Buffer {
pub id: ObjectId, pub id: ObjectId,
backing: BufferBacking, backing: BufferBacking,
@@ -98,8 +97,10 @@ impl Buffer {
} }
impl WlBuffer for Buffer { impl WlBuffer for Buffer {
type Connection = crate::wayland::Client;
/// https://wayland.app/protocols/wayland#wl_buffer:request:destroy /// https://wayland.app/protocols/wayland#wl_buffer:request:destroy
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> WaylandResult<()> {
tracing::info!("Destroying buffer {:?}", self.id); tracing::info!("Destroying buffer {:?}", self.id);
Ok(()) Ok(())
} }

View File

@@ -1,10 +1,11 @@
pub use waynest::server::protocol::core::wayland::wl_callback::*; use waynest::ObjectId;
use waynest::{ pub use waynest_protocols::server::core::wayland::wl_callback::*;
server::{Dispatcher, Result}, use waynest_server::RequestDispatcher;
wire::ObjectId,
};
#[derive(Debug, Dispatcher, Clone)] #[derive(Debug, RequestDispatcher, Clone)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Callback(pub ObjectId); pub struct Callback(pub ObjectId);
/// https://wayland.app/protocols/wayland#wl_callback /// https://wayland.app/protocols/wayland#wl_callback
impl WlCallback for Callback {} impl WlCallback for Callback {
type Connection = crate::wayland::Client;
}

View File

@@ -1,24 +1,24 @@
use super::surface::WL_SURFACE_REGISTRY; use super::surface::WL_SURFACE_REGISTRY;
use crate::wayland::{WaylandResult, WaylandError};
use crate::wayland::{core::surface::Surface, util::ClientExt}; use crate::wayland::{core::surface::Surface, util::ClientExt};
pub use waynest::server::protocol::core::wayland::wl_compositor::*; use waynest::ObjectId;
use waynest::{ use waynest_protocols::server::core::wayland::wl_surface::WlSurface;
server::{ pub use waynest_protocols::server::core::wayland::{wl_compositor::*, wl_region::*};
Client, Dispatcher, Result, use waynest_server::RequestDispatcher;
protocol::core::wayland::{wl_region::WlRegion, wl_surface::WlSurface},
},
wire::ObjectId,
};
#[derive(Debug, Dispatcher, Default)] #[derive(Debug, waynest_server::RequestDispatcher, Default)]
#[waynest(error = WaylandError)]
pub struct Compositor; pub struct Compositor;
impl WlCompositor for Compositor { impl WlCompositor for Compositor {
type Connection = crate::wayland::Client;
/// https://wayland.app/protocols/wayland#wl_compositor:request:create_surface /// https://wayland.app/protocols/wayland#wl_compositor:request:create_surface
async fn create_surface( async fn create_surface(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
id: ObjectId, id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
let surface = client.insert(id, Surface::new(client, id)); let surface = client.insert(id, Surface::new(client, id));
if let Some(output) = client.display().output.get() { if let Some(output) = client.display().output.get() {
surface.enter(client, id, output.id).await?; surface.enter(client, id, output.id).await?;
@@ -31,46 +31,49 @@ impl WlCompositor for Compositor {
/// https://wayland.app/protocols/wayland#wl_compositor:request:create_region /// https://wayland.app/protocols/wayland#wl_compositor:request:create_region
async fn create_region( async fn create_region(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
id: ObjectId, id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
client.insert(id, Region::default()); client.insert(id, Region::default());
Ok(()) Ok(())
} }
} }
#[derive(Debug, Dispatcher, Default)] #[derive(Debug, RequestDispatcher, Default)]
#[waynest(error = WaylandError)]
pub struct Region {} pub struct Region {}
impl WlRegion for Region { impl WlRegion for Region {
type Connection = crate::wayland::Client;
/// https://wayland.app/protocols/wayland#wl_region:request:add /// https://wayland.app/protocols/wayland#wl_region:request:add
async fn add( async fn add(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_x: i32, _x: i32,
_y: i32, _y: i32,
_width: i32, _width: i32,
_height: i32, _height: i32,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
/// https://wayland.app/protocols/wayland#wl_region:request:subtract /// https://wayland.app/protocols/wayland#wl_region:request:subtract
async fn subtract( async fn subtract(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_x: i32, _x: i32,
_y: i32, _y: i32,
_width: i32, _width: i32,
_height: i32, _height: i32,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
/// https://wayland.app/protocols/wayland#wl_region:request:destroy /// https://wayland.app/protocols/wayland#wl_region:request:destroy
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -1,26 +1,24 @@
use crate::wayland::{Client, WaylandResult};
use std::os::fd::OwnedFd; use std::os::fd::OwnedFd;
use waynest::{ use waynest::ObjectId;
server::{ use waynest_protocols::server::core::wayland::{
Client, Dispatcher, Result, wl_data_device::*, wl_data_device_manager::*, wl_data_offer::WlDataOffer, wl_data_source::*,
protocol::core::wayland::{
wl_data_device::*, wl_data_device_manager::*, wl_data_offer::WlDataOffer,
wl_data_source::*,
},
},
wire::ObjectId,
}; };
// TODO: actually implement this // TODO: actually implement this
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct DataDeviceManager; pub struct DataDeviceManager;
impl WlDataDeviceManager for DataDeviceManager { impl WlDataDeviceManager for DataDeviceManager {
type Connection = Client;
async fn create_data_source( async fn create_data_source(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
id: ObjectId, id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
client.insert(id, DataSource); client.insert(id, DataSource);
Ok(()) Ok(())
} }
@@ -31,116 +29,125 @@ impl WlDataDeviceManager for DataDeviceManager {
_sender_id: ObjectId, _sender_id: ObjectId,
id: ObjectId, id: ObjectId,
_seat: ObjectId, _seat: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
client.insert(id, DataDevice); client.insert(id, DataDevice);
Ok(()) Ok(())
} }
} }
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct DataSource; pub struct DataSource;
impl WlDataSource for DataSource { impl WlDataSource for DataSource {
type Connection = Client;
async fn send( async fn send(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_mime_type: String, _mime_type: String,
_fd: OwnedFd, _fd: OwnedFd,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn offer( async fn offer(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_mime_type: String, _mime_type: String,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn set_actions( async fn set_actions(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_dnd_actions: DndAction, _dnd_actions: DndAction,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct DataDevice; pub struct DataDevice;
impl WlDataDevice for DataDevice { impl WlDataDevice for DataDevice {
type Connection = Client;
async fn start_drag( async fn start_drag(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_source: Option<ObjectId>, _source: Option<ObjectId>,
_origin: ObjectId, _origin: ObjectId,
_icon: Option<ObjectId>, _icon: Option<ObjectId>,
_serial: u32, _serial: u32,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn set_selection( async fn set_selection(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_source: Option<ObjectId>, _source: Option<ObjectId>,
_serial: u32, _serial: u32,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn release(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct DataOffer; pub struct DataOffer;
impl WlDataOffer for DataOffer { impl WlDataOffer for DataOffer {
type Connection = Client;
async fn accept( async fn accept(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_serial: u32, _serial: u32,
_mime_type: Option<String>, _mime_type: Option<String>,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn receive( async fn receive(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_mime_type: String, _mime_type: String,
_fd: OwnedFd, _fd: OwnedFd,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn finish(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn finish(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn set_actions( async fn set_actions(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_dnd_actions: DndAction, _dnd_actions: DndAction,
_preferred_action: DndAction, _preferred_action: DndAction,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -1,6 +1,6 @@
use crate::{ use crate::{
nodes::items::panel::KEYMAPS, nodes::items::panel::KEYMAPS,
wayland::{core::surface::Surface, util::ClientExt}, wayland::{Client, WaylandResult, core::surface::Surface, util::ClientExt},
}; };
use dashmap::{DashMap, DashSet}; use dashmap::{DashMap, DashSet};
use memfd::MemfdOptions; use memfd::MemfdOptions;
@@ -15,11 +15,8 @@ use std::{
sync::{Arc, Weak}, sync::{Arc, Weak},
}; };
use tokio::sync::Mutex; use tokio::sync::Mutex;
pub use waynest::server::protocol::core::wayland::wl_keyboard::*; use waynest::ObjectId;
use waynest::{ pub use waynest_protocols::server::core::wayland::wl_keyboard::*;
server::{Client, Dispatcher, Result},
wire::ObjectId,
};
#[derive(Default)] #[derive(Default)]
struct ModifierState { struct ModifierState {
@@ -69,7 +66,8 @@ impl ModifierState {
} }
} }
#[derive(Dispatcher)] #[derive(waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Keyboard { pub struct Keyboard {
pub id: ObjectId, pub id: ObjectId,
focused_surface: Mutex<Weak<Surface>>, focused_surface: Mutex<Weak<Surface>>,
@@ -89,10 +87,9 @@ impl Keyboard {
} }
} }
async fn send_keymap(&self, client: &mut Client, keymap: &[u8]) -> Result<()> { async fn send_keymap(&self, client: &mut Client, keymap: &[u8]) -> WaylandResult<()> {
let mut file = MemfdOptions::default() let mut file = MemfdOptions::default()
.create("stardust-keymap") .create("stardust-keymap")?
.map_err(|e| waynest::server::Error::Custom(e.to_string()))?
.into_file(); .into_file();
file.set_len(keymap.len() as u64)?; file.set_len(keymap.len() as u64)?;
file.write_all(keymap)?; file.write_all(keymap)?;
@@ -121,7 +118,7 @@ impl Keyboard {
keymap_id: u64, keymap_id: u64,
key: u32, key: u32,
pressed: bool, pressed: bool,
) -> Result<()> { ) -> WaylandResult<()> {
// KEYMAP UPDATES // KEYMAP UPDATES
{ {
let mut old_keymap_id = self.current_keymap_id.lock().await; let mut old_keymap_id = self.current_keymap_id.lock().await;
@@ -224,7 +221,7 @@ impl Keyboard {
Ok(()) Ok(())
} }
pub async fn reset(&self, client: &mut Client) -> Result<()> { pub async fn reset(&self, client: &mut Client) -> WaylandResult<()> {
let mut modifier_state = self.modifier_state.lock().await; let mut modifier_state = self.modifier_state.lock().await;
modifier_state.pressed_keys.clear(); modifier_state.pressed_keys.clear();
modifier_state.mods_depressed = 0; modifier_state.mods_depressed = 0;
@@ -247,8 +244,10 @@ impl Keyboard {
} }
impl WlKeyboard for Keyboard { impl WlKeyboard for Keyboard {
type Connection = Client;
/// https://wayland.app/protocols/wayland#wl_keyboard:request:release /// https://wayland.app/protocols/wayland#wl_keyboard:request:release
async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn release(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -1,17 +1,15 @@
use waynest::{ use crate::wayland::{Client, WaylandResult};
server::{Client, Dispatcher, Result}, use waynest::ObjectId;
wire::ObjectId, pub use waynest_protocols::server::core::wayland::wl_output::*;
};
pub use waynest::server::protocol::core::wayland::wl_output::*; #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
#[derive(Debug, Dispatcher)]
pub struct Output { pub struct Output {
pub id: ObjectId, pub id: ObjectId,
pub version: u32, pub version: u32,
} }
impl Output { impl Output {
pub async fn advertise_outputs(&self, client: &mut Client) -> Result<()> { pub async fn advertise_outputs(&self, client: &mut Client) -> WaylandResult<()> {
self.geometry( self.geometry(
client, client,
self.id, self.id,
@@ -46,8 +44,10 @@ impl Output {
} }
} }
impl WlOutput for Output { impl WlOutput for Output {
type Connection = Client;
/// https://wayland.app/protocols/wayland#wl_output:request:release /// https://wayland.app/protocols/wayland#wl_output:request:release
async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn release(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -1,19 +1,18 @@
use super::surface::SurfaceRole;
use crate::nodes::items::panel::Geometry; use crate::nodes::items::panel::Geometry;
use crate::wayland::core::{seat::fixed_from_f32, surface::Surface}; use crate::wayland::core::surface::Surface;
use crate::wayland::{Client, WaylandResult};
use mint::Vector2; use mint::Vector2;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Weak; use std::sync::Weak;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tracing; use tracing;
pub use waynest::server::protocol::core::wayland::wl_pointer::*; use waynest::ObjectId;
use waynest::{
server::{Client, Dispatcher, Result},
wire::ObjectId,
};
use super::surface::SurfaceRole; pub use waynest_protocols::server::core::wayland::wl_pointer::*;
#[derive(Dispatcher)] #[derive(waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Pointer { pub struct Pointer {
pub id: ObjectId, pub id: ObjectId,
version: u32, version: u32,
@@ -35,7 +34,7 @@ impl Pointer {
client: &mut Client, client: &mut Client,
surface: Arc<Surface>, surface: Arc<Surface>,
position: Vector2<f32>, position: Vector2<f32>,
) -> Result<()> { ) -> WaylandResult<()> {
tracing::debug!( tracing::debug!(
"Handling pointer motion at ({}, {})", "Handling pointer motion at ({}, {})",
position.x, position.x,
@@ -65,8 +64,8 @@ impl Pointer {
self.id, self.id,
serial, serial,
surface.id, surface.id,
fixed_from_f32(position.x), (position.x as f64).into(),
fixed_from_f32(position.y), (position.y as f64).into(),
) )
.await?; .await?;
@@ -80,8 +79,8 @@ impl Pointer {
client, client,
self.id, self.id,
0, // time 0, // time
fixed_from_f32(position.x), (position.x as f64).into(),
fixed_from_f32(position.y), (position.y as f64).into(),
) )
.await?; .await?;
if self.version >= 5 { if self.version >= 5 {
@@ -97,7 +96,7 @@ impl Pointer {
surface: Arc<Surface>, surface: Arc<Surface>,
button: u32, button: u32,
pressed: bool, pressed: bool,
) -> Result<()> { ) -> WaylandResult<()> {
tracing::debug!( tracing::debug!(
"Handling pointer button {} {} on surface {:?}", "Handling pointer button {} {} on surface {:?}",
button, button,
@@ -126,7 +125,7 @@ impl Pointer {
_surface: Arc<Surface>, _surface: Arc<Surface>,
scroll_distance: Option<Vector2<f32>>, scroll_distance: Option<Vector2<f32>>,
scroll_steps: Option<Vector2<f32>>, scroll_steps: Option<Vector2<f32>>,
) -> Result<()> { ) -> WaylandResult<()> {
tracing::debug!( tracing::debug!(
"Handling pointer scroll: distance={:?}, steps={:?}", "Handling pointer scroll: distance={:?}, steps={:?}",
scroll_distance, scroll_distance,
@@ -138,7 +137,7 @@ impl Pointer {
self.id, self.id,
0, // time 0, // time
Axis::HorizontalScroll, Axis::HorizontalScroll,
fixed_from_f32(distance.x), (distance.x as f64).into(),
) )
.await?; .await?;
self.axis( self.axis(
@@ -146,7 +145,7 @@ impl Pointer {
self.id, self.id,
0, // time 0, // time
Axis::VerticalScroll, Axis::VerticalScroll,
fixed_from_f32(distance.y), (distance.y as f64).into(),
) )
.await?; .await?;
} }
@@ -162,7 +161,7 @@ impl Pointer {
Ok(()) Ok(())
} }
pub async fn reset(&self, client: &mut Client) -> Result<()> { pub async fn reset(&self, client: &mut Client) -> WaylandResult<()> {
let mut focused = self.focused_surface.lock().await; let mut focused = self.focused_surface.lock().await;
if let Some(old_surface) = focused.upgrade() { if let Some(old_surface) = focused.upgrade() {
let serial = client.next_event_serial(); let serial = client.next_event_serial();
@@ -179,16 +178,18 @@ impl Pointer {
} }
impl WlPointer for Pointer { impl WlPointer for Pointer {
type Connection = crate::wayland::Client;
/// https://wayland.app/protocols/wayland#wl_pointer:request:set_cursor /// https://wayland.app/protocols/wayland#wl_pointer:request:set_cursor
async fn set_cursor( async fn set_cursor(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_serial: u32, _serial: u32,
surface: Option<ObjectId>, surface: Option<ObjectId>,
hotspot_x: i32, hotspot_x: i32,
hotspot_y: i32, hotspot_y: i32,
) -> Result<()> { ) -> WaylandResult<()> {
if let Some(focused_surface) = self.focused_surface.lock().await.upgrade() if let Some(focused_surface) = self.focused_surface.lock().await.upgrade()
&& let Some(panel_item) = focused_surface.panel_item.lock().upgrade() && let Some(panel_item) = focused_surface.panel_item.lock().upgrade()
{ {
@@ -211,13 +212,19 @@ impl WlPointer for Pointer {
return Ok(()); return Ok(());
}; };
surface.try_set_role(client, SurfaceRole::Cursor).await?; surface
.try_set_role(SurfaceRole::Cursor, Error::Role)
.await?;
self.cursor_surface.lock().await.replace(surface); self.cursor_surface.lock().await.replace(surface);
Ok(()) Ok(())
} }
/// https://wayland.app/protocols/wayland#wl_pointer:request:release /// https://wayland.app/protocols/wayland#wl_pointer:request:release
async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn release(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -1,10 +1,11 @@
use crate::wayland::Client;
use crate::wayland::WaylandResult;
use crate::wayland::core::{keyboard::Keyboard, pointer::Pointer, surface::Surface, touch::Touch}; use crate::wayland::core::{keyboard::Keyboard, pointer::Pointer, surface::Surface, touch::Touch};
use mint::Vector2; use mint::Vector2;
use std::sync::Arc; use std::sync::Arc;
use std::sync::OnceLock; use std::sync::OnceLock;
pub use waynest::server::protocol::core::wayland::wl_seat::*; use waynest::ObjectId;
use waynest::server::{Client, Dispatcher, Result}; pub use waynest_protocols::server::core::wayland::wl_seat::*;
use waynest::wire::{Fixed, ObjectId};
#[derive(Debug)] #[derive(Debug)]
pub enum SeatMessage { pub enum SeatMessage {
@@ -43,11 +44,8 @@ pub enum SeatMessage {
Reset, Reset,
} }
pub fn fixed_from_f32(f: f32) -> Fixed { #[derive(Default, waynest_server::RequestDispatcher)]
unsafe { Fixed::from_raw((f * 256.0).round() as u32) } #[waynest(error = crate::wayland::WaylandError)]
}
#[derive(Default, Dispatcher)]
pub struct Seat { pub struct Seat {
version: u32, version: u32,
pointer: OnceLock<Arc<Pointer>>, pointer: OnceLock<Arc<Pointer>>,
@@ -56,7 +54,7 @@ pub struct Seat {
} }
impl Seat { impl Seat {
pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> Result<Self> { pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> WaylandResult<Self> {
let seat = Self { let seat = Self {
version, version,
pointer: OnceLock::new(), pointer: OnceLock::new(),
@@ -76,7 +74,11 @@ impl Seat {
Ok(seat) Ok(seat)
} }
pub async fn handle_message(&self, client: &mut Client, message: SeatMessage) -> Result<()> { pub async fn handle_message(
&self,
client: &mut Client,
message: SeatMessage,
) -> WaylandResult<()> {
match message { match message {
SeatMessage::PointerMotion { surface, position } => { SeatMessage::PointerMotion { surface, position } => {
if let Some(pointer) = self.pointer.get() { if let Some(pointer) = self.pointer.get() {
@@ -160,13 +162,15 @@ impl Seat {
} }
} }
impl WlSeat for Seat { impl WlSeat for Seat {
type Connection = crate::wayland::Client;
/// https://wayland.app/protocols/wayland#wl_seat:request:get_pointer /// https://wayland.app/protocols/wayland#wl_seat:request:get_pointer
async fn get_pointer( async fn get_pointer(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
id: ObjectId, id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
let pointer = client.insert(id, Pointer::new(id, self.version)); let pointer = client.insert(id, Pointer::new(id, self.version));
let _ = self.pointer.set(pointer); let _ = self.pointer.set(pointer);
Ok(()) Ok(())
@@ -175,10 +179,10 @@ impl WlSeat for Seat {
/// https://wayland.app/protocols/wayland#wl_seat:request:get_keyboard /// https://wayland.app/protocols/wayland#wl_seat:request:get_keyboard
async fn get_keyboard( async fn get_keyboard(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
id: ObjectId, id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
tracing::info!("Getting keyboard"); tracing::info!("Getting keyboard");
let keyboard = client.insert(id, Keyboard::new(id)); let keyboard = client.insert(id, Keyboard::new(id));
let _ = self.keyboard.set(keyboard); let _ = self.keyboard.set(keyboard);
@@ -188,17 +192,21 @@ impl WlSeat for Seat {
/// https://wayland.app/protocols/wayland#wl_seat:request:get_touch /// https://wayland.app/protocols/wayland#wl_seat:request:get_touch
async fn get_touch( async fn get_touch(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
id: ObjectId, id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
let touch = client.insert(id, Touch(id)); let touch = client.insert(id, Touch(id));
let _ = self.touch.set(touch); let _ = self.touch.set(touch);
Ok(()) Ok(())
} }
/// https://wayland.app/protocols/wayland#wl_seat:request:release /// https://wayland.app/protocols/wayland#wl_seat:request:release
async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn release(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -1,16 +1,13 @@
use crate::wayland::{Client, WaylandResult, core::shm_pool::ShmPool};
use std::os::fd::OwnedFd; use std::os::fd::OwnedFd;
use waynest::ObjectId;
pub use waynest_protocols::server::core::wayland::wl_shm::*;
use crate::wayland::core::shm_pool::ShmPool; #[derive(Debug, waynest_server::RequestDispatcher, Default)]
pub use waynest::server::protocol::core::wayland::wl_shm::*; #[waynest(error = crate::wayland::WaylandError)]
use waynest::{
server::{Client, Dispatcher, Result},
wire::ObjectId,
};
#[derive(Debug, Dispatcher, Default)]
pub struct Shm; pub struct Shm;
impl Shm { impl Shm {
pub async fn advertise_formats(&self, client: &mut Client, sender_id: ObjectId) -> Result<()> { pub async fn advertise_formats(&self, client: &mut Client, sender_id: ObjectId) -> WaylandResult<()> {
self.format(client, sender_id, Format::Argb8888).await?; self.format(client, sender_id, Format::Argb8888).await?;
self.format(client, sender_id, Format::Xrgb8888).await?; self.format(client, sender_id, Format::Xrgb8888).await?;
@@ -18,22 +15,24 @@ impl Shm {
} }
} }
impl WlShm for Shm { impl WlShm for Shm {
type Connection = crate::wayland::Client;
/// https://wayland.app/protocols/wayland#wl_shm:request:create_pool /// https://wayland.app/protocols/wayland#wl_shm:request:create_pool
async fn create_pool( async fn create_pool(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
pool_id: ObjectId, pool_id: ObjectId,
fd: OwnedFd, fd: OwnedFd,
size: i32, size: i32,
) -> Result<()> { ) -> WaylandResult<()> {
client.insert(pool_id, ShmPool::new(fd, size)?); client.insert(pool_id, ShmPool::new(fd, size)?);
Ok(()) Ok(())
} }
/// https://wayland.app/protocols/wayland#wl_shm:request:release /// https://wayland.app/protocols/wayland#wl_shm:request:release
async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn release(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -33,7 +33,7 @@ use vulkano::{
}, },
sync::GpuFuture, sync::GpuFuture,
}; };
use waynest::server::protocol::core::wayland::wl_shm::Format; use waynest_protocols::server::core::wayland::wl_shm::Format;
/// Parameters for a shared memory buffer /// Parameters for a shared memory buffer
pub struct ShmBufferBacking { pub struct ShmBufferBacking {

View File

@@ -1,25 +1,24 @@
use super::shm_buffer_backing::ShmBufferBacking;
use crate::wayland::{
Client, WaylandResult,
core::buffer::{Buffer, BufferBacking},
};
use memmap2::{MmapOptions, RemapOptions}; use memmap2::{MmapOptions, RemapOptions};
use parking_lot::{Mutex, MutexGuard, RawMutex, lock_api::MappedMutexGuard}; use parking_lot::{Mutex, MutexGuard, RawMutex, lock_api::MappedMutexGuard};
use std::os::fd::{IntoRawFd, OwnedFd}; use std::os::fd::{IntoRawFd, OwnedFd};
use waynest::{ use waynest::ObjectId;
server::{Client, Dispatcher, Result, protocol::core::wayland::wl_shm::Format}, use waynest_protocols::server::core::wayland::wl_shm::Format;
wire::ObjectId, pub use waynest_protocols::server::core::wayland::wl_shm_pool::*;
};
use crate::wayland::core::buffer::{Buffer, BufferBacking}; #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub use waynest::server::protocol::core::wayland::wl_shm_pool::*;
use super::shm_buffer_backing::ShmBufferBacking;
#[derive(Debug, Dispatcher)]
pub struct ShmPool { pub struct ShmPool {
inner: Mutex<memmap2::MmapMut>, inner: Mutex<memmap2::MmapMut>,
} }
impl ShmPool { impl ShmPool {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub fn new(fd: OwnedFd, size: i32) -> Result<Self> { pub fn new(fd: OwnedFd, size: i32) -> WaylandResult<Self> {
let map = unsafe { let map = unsafe {
MmapOptions::new() MmapOptions::new()
.len(size as usize) .len(size as usize)
@@ -38,11 +37,13 @@ impl ShmPool {
} }
impl WlShmPool for ShmPool { impl WlShmPool for ShmPool {
type Connection = Client;
/// https://wayland.app/protocols/wayland#wl_shm_pool:request:create_buffer /// https://wayland.app/protocols/wayland#wl_shm_pool:request:create_buffer
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn create_buffer( async fn create_buffer(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
sender_id: ObjectId, sender_id: ObjectId,
id: ObjectId, id: ObjectId,
offset: i32, offset: i32,
@@ -50,7 +51,7 @@ impl WlShmPool for ShmPool {
height: i32, height: i32,
stride: i32, stride: i32,
format: Format, format: Format,
) -> Result<()> { ) -> WaylandResult<()> {
let params = ShmBufferBacking::new( let params = ShmBufferBacking::new(
client.get::<ShmPool>(sender_id).unwrap(), client.get::<ShmPool>(sender_id).unwrap(),
offset as usize, offset as usize,
@@ -65,7 +66,12 @@ impl WlShmPool for ShmPool {
/// https://wayland.app/protocols/wayland#wl_shm_pool:request:resize /// https://wayland.app/protocols/wayland#wl_shm_pool:request:resize
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn resize(&self, _client: &mut Client, _sender_id: ObjectId, size: i32) -> Result<()> { async fn resize(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
size: i32,
) -> WaylandResult<()> {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
unsafe { inner.remap(size as usize, RemapOptions::new().may_move(true))? }; unsafe { inner.remap(size as usize, RemapOptions::new().may_move(true))? };
Ok(()) Ok(())
@@ -73,7 +79,7 @@ impl WlShmPool for ShmPool {
/// https://wayland.app/protocols/wayland#wl_shm_pool:request:destroy /// https://wayland.app/protocols/wayland#wl_shm_pool:request:destroy
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -7,7 +7,7 @@ use crate::{
items::panel::{Geometry, PanelItem, SurfaceId}, items::panel::{Geometry, PanelItem, SurfaceId},
}, },
wayland::{ wayland::{
Message, MessageSink, Client, Message, MessageSink, WaylandError, WaylandResult,
core::buffer::BufferUsage, core::buffer::BufferUsage,
presentation::{MonotonicTimestamp, PresentationFeedback}, presentation::{MonotonicTimestamp, PresentationFeedback},
util::{ClientExt, DoubleBuffer}, util::{ClientExt, DoubleBuffer},
@@ -22,16 +22,14 @@ use bevy::{
use bevy_dmabuf::import::ImportedDmatexs; use bevy_dmabuf::import::ImportedDmatexs;
use mint::Vector2; use mint::Vector2;
use parking_lot::Mutex; use parking_lot::Mutex;
use std::sync::{Arc, OnceLock, Weak}; use std::{
use waynest::{ fmt::Display,
server::{ sync::{Arc, OnceLock, Weak},
self, Client, Dispatcher, Result, };
protocol::{ use waynest::ObjectId;
core::wayland::{wl_output::Transform, wl_surface::*}, use waynest_protocols::server::{
stable::presentation_time::wp_presentation_feedback::{Kind, WpPresentationFeedback}, core::wayland::{wl_output::Transform, wl_surface::*},
}, stable::presentation_time::wp_presentation_feedback::{Kind, WpPresentationFeedback},
},
wire::ObjectId,
}; };
pub static WL_SURFACE_REGISTRY: Registry<Surface> = Registry::new(); pub static WL_SURFACE_REGISTRY: Registry<Surface> = Registry::new();
@@ -43,6 +41,16 @@ pub enum SurfaceRole {
XdgToplevel, XdgToplevel,
XdgPopup, XdgPopup,
} }
impl Display for SurfaceRole {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SurfaceRole::Cursor => f.write_str("SurfaceRole::Cursor"),
SurfaceRole::Subsurface => f.write_str("SurfaceRole::Subsurface"),
SurfaceRole::XdgToplevel => f.write_str("SurfaceRole::XdgToplevel"),
SurfaceRole::XdgPopup => f.write_str("SurfaceRole::XdgPopup"),
}
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct BufferState { pub struct BufferState {
@@ -81,7 +89,8 @@ impl SurfaceState {
// if returning false, don't run this callback again... just remove it // if returning false, don't run this callback again... just remove it
pub type OnCommitCallback = Box<dyn FnMut(&Surface, &SurfaceState) -> bool + Send + Sync>; pub type OnCommitCallback = Box<dyn FnMut(&Surface, &SurfaceState) -> bool + Send + Sync>;
#[derive(Dispatcher)] #[derive(waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Surface { pub struct Surface {
pub id: ObjectId, pub id: ObjectId,
pub surface_id: OnceLock<SurfaceId>, pub surface_id: OnceLock<SurfaceId>,
@@ -130,24 +139,21 @@ impl Surface {
} }
} }
pub async fn try_set_role(&self, client: &mut Client, role: SurfaceRole) -> Result<()> { pub async fn try_set_role(
&self,
role: SurfaceRole,
role_error: impl Into<u32>,
) -> WaylandResult<()> {
match self.role.get().cloned() { match self.role.get().cloned() {
Some(current_role) => { Some(current_role) => {
if current_role == role { if current_role == role {
Ok(()) Ok(())
} else { } else {
client Err(WaylandError::Fatal {
.protocol_error( object_id: self.id,
self.id, code: role_error.into(),
self.id, message: "Surface has an incomparible role",
1, // XDG_WM_BASE_ERROR_ROLE })
"Surface has an incomparible role".to_string(),
)
.await?;
Err(server::Error::Custom(format!(
"Surface {} has role {current_role:?} but tried to set to {role:?}",
self.id
)))
} }
} }
None => { None => {
@@ -248,7 +254,7 @@ impl Surface {
// .map(|b| [b.size.x as u32, b.size.y as u32].into()) // .map(|b| [b.size.x as u32, b.size.y as u32].into())
// } // }
// pub async fn release_old_buffer(&self, client: &mut Client) -> Result<()> { // pub async fn release_old_buffer(&self, client: &mut Self::Connection) -> Result<()> {
// let (old_buffer, object) = { // let (old_buffer, object) = {
// let lock = self.state.lock(); // let lock = self.state.lock();
@@ -291,7 +297,7 @@ impl Surface {
client: &mut Client, client: &mut Client,
display_timestamp: MonotonicTimestamp, display_timestamp: MonotonicTimestamp,
refresh_cycle: u64, refresh_cycle: u64,
) -> Result<()> { ) -> WaylandResult<()> {
let feedbacks = self let feedbacks = self
.presentation_feedback .presentation_feedback
.lock() .lock()
@@ -325,16 +331,18 @@ impl Surface {
} }
} }
impl WlSurface for Surface { impl WlSurface for Surface {
type Connection = crate::wayland::Client;
/// https://wayland.app/protocols/wayland#wl_surface:request:attach /// https://wayland.app/protocols/wayland#wl_surface:request:attach
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn attach( async fn attach(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
buffer: Option<ObjectId>, buffer: Option<ObjectId>,
_x: i32, _x: i32,
_y: i32, _y: i32,
) -> Result<()> { ) -> WaylandResult<()> {
self.state.lock().pending.buffer = buffer.and_then(|b| { self.state.lock().pending.buffer = buffer.and_then(|b| {
let buffer = client.get::<Buffer>(b)?; let buffer = client.get::<Buffer>(b)?;
let mut usage = Some(BufferUsage::new(client, &buffer)); let mut usage = Some(BufferUsage::new(client, &buffer));
@@ -350,13 +358,13 @@ impl WlSurface for Surface {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn damage( async fn damage(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_x: i32, _x: i32,
_y: i32, _y: i32,
_width: i32, _width: i32,
_height: i32, _height: i32,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
@@ -364,10 +372,10 @@ impl WlSurface for Surface {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn frame( async fn frame(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
callback_id: ObjectId, callback_id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
let callback = client.insert(callback_id, Callback(callback_id)); let callback = client.insert(callback_id, Callback(callback_id));
self.state.lock().pending.frame_callbacks.push(callback); self.state.lock().pending.frame_callbacks.push(callback);
Ok(()) Ok(())
@@ -377,10 +385,10 @@ impl WlSurface for Surface {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn set_opaque_region( async fn set_opaque_region(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_region: Option<ObjectId>, _region: Option<ObjectId>,
) -> Result<()> { ) -> WaylandResult<()> {
// nothing we can really do to repaint behind this so ignore it // nothing we can really do to repaint behind this so ignore it
Ok(()) Ok(())
} }
@@ -389,17 +397,21 @@ impl WlSurface for Surface {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn set_input_region( async fn set_input_region(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_region: Option<ObjectId>, _region: Option<ObjectId>,
) -> Result<()> { ) -> WaylandResult<()> {
// too complicated to implement this for now so who the hell cares // too complicated to implement this for now so who the hell cares
Ok(()) Ok(())
} }
/// https://wayland.app/protocols/wayland#wl_surface:request:commit /// https://wayland.app/protocols/wayland#wl_surface:request:commit
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn commit(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn commit(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
// we want the upload to complete before we give the image to bevy // we want the upload to complete before we give the image to bevy
let buffer_option = self let buffer_option = self
.state_lock() .state_lock()
@@ -428,10 +440,10 @@ impl WlSurface for Surface {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn set_buffer_transform( async fn set_buffer_transform(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_transform: Transform, _transform: Transform,
) -> Result<()> { ) -> WaylandResult<()> {
// we just don't have the output transform or fullscreen at all so this optimization is never needed // we just don't have the output transform or fullscreen at all so this optimization is never needed
Ok(()) Ok(())
} }
@@ -440,10 +452,10 @@ impl WlSurface for Surface {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn set_buffer_scale( async fn set_buffer_scale(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
scale: i32, scale: i32,
) -> Result<()> { ) -> WaylandResult<()> {
self.state.lock().pending.density = scale as f32; self.state.lock().pending.density = scale as f32;
Ok(()) Ok(())
} }
@@ -452,13 +464,13 @@ impl WlSurface for Surface {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn damage_buffer( async fn damage_buffer(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_x: i32, _x: i32,
_y: i32, _y: i32,
_width: i32, _width: i32,
_height: i32, _height: i32,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
@@ -466,17 +478,21 @@ impl WlSurface for Surface {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn offset( async fn offset(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_x: i32, _x: i32,
_y: i32, _y: i32,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
/// https://wayland.app/protocols/wayland#wl_surface:request:destroy /// https://wayland.app/protocols/wayland#wl_surface:request:destroy
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn destroy(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -1,15 +1,11 @@
use crate::wayland::core::surface::Surface; use crate::wayland::{Client, WaylandResult, core::surface::Surface};
use mint::Vector2; use mint::Vector2;
use std::sync::Arc; use std::sync::Arc;
pub use waynest::server::protocol::core::wayland::wl_touch::*; use waynest::ObjectId;
use waynest::{ pub use waynest_protocols::server::core::wayland::wl_touch::*;
server::{Client, Dispatcher, Result},
wire::ObjectId,
};
use super::seat::fixed_from_f32; #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
#[derive(Debug, Dispatcher)]
pub struct Touch(pub ObjectId); pub struct Touch(pub ObjectId);
impl Touch { impl Touch {
pub async fn handle_touch_down( pub async fn handle_touch_down(
@@ -18,7 +14,7 @@ impl Touch {
surface: Arc<Surface>, surface: Arc<Surface>,
id: u32, id: u32,
position: Vector2<f32>, position: Vector2<f32>,
) -> Result<()> { ) -> WaylandResult<()> {
let serial = client.next_event_serial(); let serial = client.next_event_serial();
self.down( self.down(
client, client,
@@ -27,8 +23,8 @@ impl Touch {
0, 0,
surface.id, surface.id,
id as i32, id as i32,
fixed_from_f32(position.x), (position.x as f64).into(),
fixed_from_f32(position.y), (position.y as f64).into(),
) )
.await?; .await?;
self.frame(client, self.0).await self.frame(client, self.0).await
@@ -39,37 +35,39 @@ impl Touch {
client: &mut Client, client: &mut Client,
id: u32, id: u32,
position: Vector2<f32>, position: Vector2<f32>,
) -> Result<()> { ) -> WaylandResult<()> {
self.motion( self.motion(
client, client,
self.0, self.0,
0, 0,
id as i32, id as i32,
fixed_from_f32(position.x), (position.x as f64).into(),
fixed_from_f32(position.y), (position.y as f64).into(),
) )
.await?; .await?;
self.frame(client, self.0).await self.frame(client, self.0).await
} }
pub async fn handle_touch_up(&self, client: &mut Client, id: u32) -> Result<()> { pub async fn handle_touch_up(&self, client: &mut Client, id: u32) -> WaylandResult<()> {
let serial = client.next_event_serial(); let serial = client.next_event_serial();
self.up(client, self.0, serial, 0, id as i32).await?; self.up(client, self.0, serial, 0, id as i32).await?;
self.frame(client, self.0).await self.frame(client, self.0).await
} }
pub async fn reset(&self, client: &mut Client) -> Result<()> { pub async fn reset(&self, client: &mut Client) -> WaylandResult<()> {
self.frame(client, self.0).await self.frame(client, self.0).await
} }
} }
impl WlTouch for Touch { impl WlTouch for Touch {
type Connection = crate::wayland::Client;
/// https://wayland.app/protocols/wayland#wl_touch:request:release /// https://wayland.app/protocols/wayland#wl_touch:request:release
async fn release( async fn release(
&self, &self,
_client: &mut waynest::server::Client, _client: &mut Self::Connection,
_sender_id: waynest::wire::ObjectId, _sender_id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -1,7 +1,7 @@
#![allow(unused)] #![allow(unused)]
use crate::wayland::{ use crate::wayland::{
MessageSink, MessageSink, WaylandResult,
core::{ core::{
callback::{Callback, WlCallback}, callback::{Callback, WlCallback},
output::Output, output::Output,
@@ -14,13 +14,11 @@ use std::{
sync::{Arc, OnceLock}, sync::{Arc, OnceLock},
time::Instant, time::Instant,
}; };
pub use waynest::server::protocol::core::wayland::wl_display::*; use waynest::ObjectId;
use waynest::{ pub use waynest_protocols::server::core::wayland::wl_display::*;
server::{Client, Dispatcher, Result},
wire::ObjectId,
};
#[derive(Dispatcher)] #[derive(waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Display { pub struct Display {
pub message_sink: MessageSink, pub message_sink: MessageSink,
pub pid: Option<i32>, pub pid: Option<i32>,
@@ -45,13 +43,15 @@ impl Display {
} }
} }
impl WlDisplay for Display { impl WlDisplay for Display {
type Connection = crate::wayland::Client;
/// https://wayland.app/protocols/wayland#wl_display:request:sync /// https://wayland.app/protocols/wayland#wl_display:request:sync
async fn sync( async fn sync(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
sender_id: ObjectId, sender_id: ObjectId,
callback_id: ObjectId, callback_id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
let serial = client.next_event_serial(); let serial = client.next_event_serial();
Callback(callback_id) Callback(callback_id)
.done(client, callback_id, serial) .done(client, callback_id, serial)
@@ -65,10 +65,10 @@ impl WlDisplay for Display {
/// https://wayland.app/protocols/wayland#wl_display:request:get_registry /// https://wayland.app/protocols/wayland#wl_display:request:get_registry
async fn get_registry( async fn get_registry(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
registry_id: ObjectId, registry_id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
let registry = client.insert(registry_id, Registry); let registry = client.insert(registry_id, Registry);
registry.advertise_globals(client, registry_id).await?; registry.advertise_globals(client, registry_id).await?;

View File

@@ -14,7 +14,7 @@ use drm_fourcc::DrmFourcc;
use mint::Vector2; use mint::Vector2;
use parking_lot::Mutex; use parking_lot::Mutex;
use std::sync::{Arc, OnceLock}; use std::sync::{Arc, OnceLock};
use waynest::server::protocol::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::Flags; use waynest_protocols::server::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::Flags;
/// Parameters for a shared memory buffer /// Parameters for a shared memory buffer
pub struct DmabufBacking { pub struct DmabufBacking {

View File

@@ -1,5 +1,6 @@
use super::buffer_backing::DmabufBacking; use super::buffer_backing::DmabufBacking;
use crate::wayland::{ use crate::wayland::{
Client, WaylandError, WaylandResult,
core::buffer::{Buffer, BufferBacking}, core::buffer::{Buffer, BufferBacking},
util::ClientExt, util::ClientExt,
}; };
@@ -8,14 +9,9 @@ use drm_fourcc::DrmFourcc;
use parking_lot::Mutex; use parking_lot::Mutex;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::os::fd::{AsRawFd, OwnedFd}; use std::os::fd::{AsRawFd, OwnedFd};
use waynest::{ use waynest::ObjectId;
server::{ use waynest_protocols::server::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::{
Client, Dispatcher, Result, Error, Flags, ZwpLinuxBufferParamsV1,
protocol::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::{
Error, Flags, ZwpLinuxBufferParamsV1,
},
},
wire::ObjectId,
}; };
/// Parameters for creating a DMA-BUF-based wl_buffer /// Parameters for creating a DMA-BUF-based wl_buffer
@@ -23,7 +19,8 @@ use waynest::{
/// This is a temporary object that collects dmabufs and other parameters /// This is a temporary object that collects dmabufs and other parameters
/// that together form a single logical buffer. The object may eventually /// that together form a single logical buffer. The object may eventually
/// create one wl_buffer unless cancelled by destroying it. /// create one wl_buffer unless cancelled by destroying it.
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct BufferParams { pub struct BufferParams {
pub id: ObjectId, pub id: ObjectId,
pub(super) planes: Mutex<FxHashMap<u32, DmatexPlane>>, pub(super) planes: Mutex<FxHashMap<u32, DmatexPlane>>,
@@ -41,7 +38,13 @@ impl BufferParams {
} }
impl ZwpLinuxBufferParamsV1 for BufferParams { impl ZwpLinuxBufferParamsV1 for BufferParams {
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { type Connection = Client;
async fn destroy(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
tracing::info!("Destroying BufferParams {:?}", self.id); tracing::info!("Destroying BufferParams {:?}", self.id);
Ok(()) Ok(())
} }
@@ -49,7 +52,7 @@ impl ZwpLinuxBufferParamsV1 for BufferParams {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn add( async fn add(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
fd: OwnedFd, fd: OwnedFd,
plane_idx: u32, plane_idx: u32,
@@ -57,7 +60,7 @@ impl ZwpLinuxBufferParamsV1 for BufferParams {
stride: u32, stride: u32,
modifier_hi: u32, modifier_hi: u32,
modifier_lo: u32, modifier_lo: u32,
) -> Result<()> { ) -> WaylandResult<()> {
let fd_num = fd.as_raw_fd(); let fd_num = fd.as_raw_fd();
tracing::info!( tracing::info!(
"Adding plane {} with fd {} to BufferParams {:?}", "Adding plane {} with fd {} to BufferParams {:?}",
@@ -75,7 +78,7 @@ impl ZwpLinuxBufferParamsV1 for BufferParams {
plane_idx, plane_idx,
self.id self.id
); );
return Err(waynest::server::Error::MissingObject(self.id)); return Err(crate::wayland::WaylandError::MissingObject(self.id));
} }
// Create plane with the provided parameters // Create plane with the provided parameters
@@ -94,13 +97,13 @@ impl ZwpLinuxBufferParamsV1 for BufferParams {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn create( async fn create(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
width: i32, width: i32,
height: i32, height: i32,
format: u32, format: u32,
flags: Flags, flags: Flags,
) -> Result<()> { ) -> WaylandResult<()> {
tracing::info!("Creating buffer from BufferParams {:?}", self.id); tracing::info!("Creating buffer from BufferParams {:?}", self.id);
// Create the buffer with DMA-BUF backing using self as the backing // Create the buffer with DMA-BUF backing using self as the backing
let size = [width as u32, height as u32].into(); let size = [width as u32, height as u32].into();
@@ -128,14 +131,14 @@ impl ZwpLinuxBufferParamsV1 for BufferParams {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn create_immed( async fn create_immed(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
sender_id: ObjectId, _sender_id: ObjectId,
buffer_id: ObjectId, buffer_id: ObjectId,
width: i32, width: i32,
height: i32, height: i32,
format: u32, format: u32,
flags: Flags, flags: Flags,
) -> Result<()> { ) -> WaylandResult<()> {
// TODO: terminate client on fail, or send a fail event or something // TODO: terminate client on fail, or send a fail event or something
// Create the buffer with DMA-BUF backing using self as the backing // Create the buffer with DMA-BUF backing using self as the backing
match DmabufBacking::from_params( match DmabufBacking::from_params(
@@ -148,15 +151,12 @@ impl ZwpLinuxBufferParamsV1 for BufferParams {
Buffer::new(client, buffer_id, BufferBacking::Dmabuf(backing)); Buffer::new(client, buffer_id, BufferBacking::Dmabuf(backing));
} }
Err(e) => { Err(e) => {
client
.protocol_error(
sender_id,
buffer_id,
Error::Incomplete as u32,
format!("Failed to import dmabuf because {e}"),
)
.await?;
tracing::error!("Failed to import dmabuf because {e}"); tracing::error!("Failed to import dmabuf because {e}");
return Err(WaylandError::Fatal {
object_id: buffer_id,
code: Error::Incomplete as u32,
message: "Failed to import dmabuf",
});
} }
} }
Ok(()) Ok(())

View File

@@ -1,26 +1,22 @@
use super::Dmabuf; use super::Dmabuf;
use crate::wayland::vulkano_data::VULKANO_CONTEXT; use crate::wayland::{Client, WaylandResult, vulkano_data::VULKANO_CONTEXT};
use memfd::MemfdOptions; use memfd::MemfdOptions;
use std::{ use std::{
io::Write, io::Write,
os::fd::{FromRawFd, IntoRawFd, OwnedFd}, os::fd::{FromRawFd, IntoRawFd, OwnedFd},
sync::Arc, sync::Arc,
}; };
use waynest::{ use waynest::ObjectId;
server::{ use waynest_protocols::server::stable::linux_dmabuf_v1::zwp_linux_dmabuf_feedback_v1::{
Client, Dispatcher, Result, TrancheFlags, ZwpLinuxDmabufFeedbackV1,
protocol::stable::linux_dmabuf_v1::zwp_linux_dmabuf_feedback_v1::{
TrancheFlags, ZwpLinuxDmabufFeedbackV1,
},
},
wire::ObjectId,
}; };
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct DmabufFeedback(pub Arc<Dmabuf>); pub struct DmabufFeedback(pub Arc<Dmabuf>);
impl DmabufFeedback { impl DmabufFeedback {
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn send_params(&self, client: &mut Client, sender_id: ObjectId) -> Result<()> { pub async fn send_params(&self, client: &mut Client, sender_id: ObjectId) -> WaylandResult<()> {
let num_formats = self.0.formats.len(); let num_formats = self.0.formats.len();
// Send format table first // Send format table first
self.send_format_table(client, sender_id).await?; self.send_format_table(client, sender_id).await?;
@@ -63,16 +59,18 @@ impl DmabufFeedback {
} }
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn send_format_table(&self, client: &mut Client, sender_id: ObjectId) -> Result<()> { pub async fn send_format_table(
&self,
client: &mut Client,
sender_id: ObjectId,
) -> WaylandResult<()> {
// Format + modifier pair (16 bytes): // Format + modifier pair (16 bytes):
// - format: u32 // - format: u32
// - padding: 4 bytes // - padding: 4 bytes
// - modifier: u64 // - modifier: u64
let size = self.0.formats.len() as u32 * 16u32; let size = self.0.formats.len() as u32 * 16u32;
// Create a temporary file for the format table // Create a temporary file for the format table
let mfd = MemfdOptions::default() let mfd = MemfdOptions::default().create("stardustxr-format-table")?;
.create("stardustxr-format-table")
.map_err(|e| waynest::server::Error::Custom(e.to_string()))?;
mfd.as_file().set_len(size as u64)?; mfd.as_file().set_len(size as u64)?;
@@ -96,7 +94,13 @@ impl DmabufFeedback {
} }
impl ZwpLinuxDmabufFeedbackV1 for DmabufFeedback { impl ZwpLinuxDmabufFeedbackV1 for DmabufFeedback {
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { type Connection = crate::wayland::Client;
async fn destroy(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -2,10 +2,11 @@ pub mod buffer_backing;
pub mod buffer_params; pub mod buffer_params;
pub mod feedback; pub mod feedback;
use std::sync::LazyLock; use super::vulkano_data::VULKANO_CONTEXT;
use crate::{
use super::{util::ClientExt, vulkano_data::VULKANO_CONTEXT}; core::registry::Registry,
use crate::core::registry::Registry; wayland::{Client, WaylandError, WaylandResult},
};
use bevy_dmabuf::{ use bevy_dmabuf::{
format_mapping::{drm_fourcc_to_vk_format, vk_format_to_srgb}, format_mapping::{drm_fourcc_to_vk_format, vk_format_to_srgb},
wgpu_init::vulkan_to_wgpu, wgpu_init::vulkan_to_wgpu,
@@ -14,14 +15,10 @@ use buffer_params::BufferParams;
use drm_fourcc::DrmFourcc; use drm_fourcc::DrmFourcc;
use feedback::DmabufFeedback; use feedback::DmabufFeedback;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use std::sync::LazyLock;
use vulkano::format::FormatFeatures; use vulkano::format::FormatFeatures;
use waynest::{ use waynest::ObjectId;
server::{ use waynest_protocols::server::stable::linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1;
Client, Dispatcher, Error, Result,
protocol::stable::linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
},
wire::ObjectId,
};
pub static DMABUF_FORMATS: LazyLock<Vec<(DrmFourcc, u64)>> = LazyLock::new(|| { pub static DMABUF_FORMATS: LazyLock<Vec<(DrmFourcc, u64)>> = LazyLock::new(|| {
let vk = VULKANO_CONTEXT.wait(); let vk = VULKANO_CONTEXT.wait();
@@ -76,7 +73,8 @@ pub static DMABUF_FORMATS: LazyLock<Vec<(DrmFourcc, u64)>> = LazyLock::new(|| {
/// - Coherency for read access in dmabuf data /// - Coherency for read access in dmabuf data
/// - Proper lifetime management of dmabuf file descriptors /// - Proper lifetime management of dmabuf file descriptors
/// - Safe handling of buffer attachments /// - Safe handling of buffer attachments
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Dmabuf { pub struct Dmabuf {
// Track supported formats and modifiers // Track supported formats and modifiers
// formats: Mutex<FxHashSet<DrmFormat>>, // formats: Mutex<FxHashSet<DrmFormat>>,
@@ -88,7 +86,7 @@ pub struct Dmabuf {
impl Dmabuf { impl Dmabuf {
/// Create a new DMA-BUF interface instance /// Create a new DMA-BUF interface instance
pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> Result<Self> { pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> WaylandResult<Self> {
let dmabuf = Self { let dmabuf = Self {
active_params: Registry::new(), active_params: Registry::new(),
version, version,
@@ -122,17 +120,23 @@ impl Dmabuf {
} }
impl ZwpLinuxDmabufV1 for Dmabuf { impl ZwpLinuxDmabufV1 for Dmabuf {
async fn destroy(&self, _client: &mut Client, sender_id: ObjectId) -> Result<()> { type Connection = crate::wayland::Client;
async fn destroy(
&self,
_client: &mut Self::Connection,
sender_id: ObjectId,
) -> WaylandResult<()> {
self.remove_params(sender_id); self.remove_params(sender_id);
Ok(()) Ok(())
} }
async fn create_params( async fn create_params(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
params_id: ObjectId, params_id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
// Create new buffer parameters object // Create new buffer parameters object
let params = client.insert(params_id, BufferParams::new(params_id)); let params = client.insert(params_id, BufferParams::new(params_id));
self.active_params.add_raw(&params); self.active_params.add_raw(&params);
@@ -141,20 +145,16 @@ impl ZwpLinuxDmabufV1 for Dmabuf {
async fn get_default_feedback( async fn get_default_feedback(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
sender_id: ObjectId, sender_id: ObjectId,
id: ObjectId, id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
if self.version < 3 { if self.version < 3 {
client return Err(WaylandError::Fatal {
.protocol_error( object_id: id,
sender_id, code: 71,
id, message: "Can't call get_default_feedback on version < 4 of dmabuf",
71, });
"Can't call get_default_feedback on version < 4 of dmabuf".into(),
)
.await?;
return Err(Error::Custom("Protocol error".into()));
} }
// Create feedback object for default (non-surface-specific) settings // Create feedback object for default (non-surface-specific) settings
let feedback = client.insert(id, DmabufFeedback(client.get::<Dmabuf>(sender_id).unwrap())); let feedback = client.insert(id, DmabufFeedback(client.get::<Dmabuf>(sender_id).unwrap()));
@@ -164,11 +164,11 @@ impl ZwpLinuxDmabufV1 for Dmabuf {
async fn get_surface_feedback( async fn get_surface_feedback(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
sender_id: ObjectId, sender_id: ObjectId,
id: ObjectId, id: ObjectId,
_surface: ObjectId, _surface: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
// Create feedback object for surface-specific settings // Create feedback object for surface-specific settings
// Note: Surface-specific feedback could be optimized based on the surface's // Note: Surface-specific feedback could be optimized based on the surface's
// requirements, but for now we use the same feedback as default // requirements, but for now we use the same feedback as default

View File

@@ -1,4 +1,5 @@
use crate::wayland::{ use crate::wayland::{
Client, WaylandResult,
core::buffer::{Buffer, BufferBacking}, core::buffer::{Buffer, BufferBacking},
dmabuf::{DMABUF_FORMATS, buffer_backing::DmabufBacking}, dmabuf::{DMABUF_FORMATS, buffer_backing::DmabufBacking},
vulkano_data::VULKANO_CONTEXT, vulkano_data::VULKANO_CONTEXT,
@@ -6,17 +7,16 @@ use crate::wayland::{
use bevy_dmabuf::dmatex::{Dmatex, DmatexPlane, Resolution}; use bevy_dmabuf::dmatex::{Dmatex, DmatexPlane, Resolution};
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use std::os::fd::OwnedFd; use std::os::fd::OwnedFd;
use waynest::{ use waynest::ObjectId;
server::{Client, Dispatcher, Result, protocol::mesa::drm::wl_drm::*}, use waynest_protocols::server::mesa::drm::wl_drm::*;
wire::ObjectId,
};
#[derive(Debug, Dispatcher, Default)] #[derive(Debug, waynest_server::RequestDispatcher, Default)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct MesaDrm { pub struct MesaDrm {
version: u32, version: u32,
} }
impl MesaDrm { impl MesaDrm {
pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> Result<MesaDrm> { pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> WaylandResult<MesaDrm> {
let drm = MesaDrm { version }; let drm = MesaDrm { version };
let path = { let path = {
@@ -46,13 +46,20 @@ impl MesaDrm {
} }
} }
impl WlDrm for MesaDrm { impl WlDrm for MesaDrm {
async fn authenticate(&self, client: &mut Client, sender_id: ObjectId, _id: u32) -> Result<()> { type Connection = Client;
async fn authenticate(
&self,
client: &mut Self::Connection,
sender_id: ObjectId,
_id: u32,
) -> WaylandResult<()> {
self.authenticated(client, sender_id).await self.authenticated(client, sender_id).await
} }
async fn create_buffer( async fn create_buffer(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_id: ObjectId, _id: ObjectId,
_name: u32, _name: u32,
@@ -60,14 +67,14 @@ impl WlDrm for MesaDrm {
_height: i32, _height: i32,
_stride: u32, _stride: u32,
_format: u32, _format: u32,
) -> Result<()> { ) -> WaylandResult<()> {
tracing::error!("Tried to create non-prime wl_drm buffer!"); tracing::error!("Tried to create non-prime wl_drm buffer!");
Ok(()) Ok(())
} }
async fn create_planar_buffer( async fn create_planar_buffer(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_id: ObjectId, _id: ObjectId,
_name: u32, _name: u32,
@@ -80,14 +87,14 @@ impl WlDrm for MesaDrm {
_stride1: i32, _stride1: i32,
_offset2: i32, _offset2: i32,
_stride2: i32, _stride2: i32,
) -> Result<()> { ) -> WaylandResult<()> {
tracing::error!("Tried to create non-prime wl_drm buffer!"); tracing::error!("Tried to create non-prime wl_drm buffer!");
Ok(()) Ok(())
} }
async fn create_prime_buffer( async fn create_prime_buffer(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
buffer_id: ObjectId, buffer_id: ObjectId,
name: OwnedFd, name: OwnedFd,
@@ -100,7 +107,7 @@ impl WlDrm for MesaDrm {
_stride1: i32, _stride1: i32,
_offset2: i32, _offset2: i32,
_stride2: i32, _stride2: i32,
) -> Result<()> { ) -> WaylandResult<()> {
// TODO: actual error checking // TODO: actual error checking
let _ = DmabufBacking::new(Dmatex { let _ = DmabufBacking::new(Dmatex {

View File

@@ -9,18 +9,14 @@ mod viewporter;
mod vulkano_data; mod vulkano_data;
mod xdg; mod xdg;
use crate::core::error::ServerError;
use crate::core::registry::OwnedRegistry; use crate::core::registry::OwnedRegistry;
use crate::nodes::drawable::model::ModelNodeSystemSet; use crate::nodes::drawable::model::ModelNodeSystemSet;
use crate::wayland::core::seat::SeatMessage; use crate::wayland::core::seat::SeatMessage;
use crate::wayland::core::surface::Surface; use crate::wayland::core::surface::Surface;
use crate::wayland::presentation::MonotonicTimestamp; use crate::wayland::presentation::MonotonicTimestamp;
use crate::{ use crate::wayland::util::ClientExt;
BevyMaterial, use crate::{BevyMaterial, core::task};
core::{
error::{Result, ServerError},
task,
},
};
use bevy::app::{App, Plugin, Update}; use bevy::app::{App, Plugin, Update};
use bevy::ecs::schedule::IntoScheduleConfigs; use bevy::ecs::schedule::IntoScheduleConfigs;
use bevy::ecs::system::{Local, Res, ResMut}; use bevy::ecs::system::{Local, Res, ResMut};
@@ -37,11 +33,11 @@ use core::{buffer::Buffer, callback::Callback, surface::WL_SURFACE_REGISTRY};
use display::Display; use display::Display;
use mint::Vector2; use mint::Vector2;
use std::fs::File; use std::fs::File;
use std::io::ErrorKind;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::time::Duration; use std::time::Duration;
use std::{ use std::{
fs, io,
io::{self, ErrorKind},
path::PathBuf, path::PathBuf,
sync::{Arc, OnceLock}, sync::{Arc, OnceLock},
}; };
@@ -49,24 +45,37 @@ use tokio::{net::UnixStream, sync::mpsc, task::AbortHandle};
use tokio_stream::StreamExt; use tokio_stream::StreamExt;
use tracing::{debug_span, instrument}; use tracing::{debug_span, instrument};
use vulkano_data::setup_vulkano_context; use vulkano_data::setup_vulkano_context;
use waynest::{ use waynest::ObjectId;
server::{ use waynest_protocols::server::core::wayland::wl_display::WlDisplay;
self, use waynest_server::{Connection, Listener};
protocol::{
core::wayland::{wl_buffer::WlBuffer, wl_callback::WlCallback, wl_display::WlDisplay},
stable::xdg_shell::xdg_toplevel::XdgToplevel,
},
},
wire::{DecodeError, ObjectId},
};
use xdg::toplevel::Toplevel; use xdg::toplevel::Toplevel;
pub static WAYLAND_DISPLAY: OnceLock<PathBuf> = OnceLock::new(); pub static WAYLAND_DISPLAY: OnceLock<PathBuf> = OnceLock::new();
impl From<waynest::server::Error> for ServerError { #[derive(thiserror::Error, Debug)]
fn from(err: waynest::server::Error) -> Self { pub enum WaylandError {
ServerError::WaylandError(err) // #[error("Listener error: {0}")]
} // Listener(#[from] waynest_server::ListenerError),
#[error("I/O error: {0}")]
Io(#[from] io::Error),
#[error("Decode error: {0}")]
DecodeError(#[from] waynest::ProtocolError),
#[error("Client requested unknown global: {0}")]
UnknownGlobal(u32),
#[error("No object found with ID {0}")]
MissingObject(ObjectId),
#[error("Fatal error on object {object_id} with code {code}: {message}")]
Fatal {
object_id: ObjectId,
code: u32,
message: &'static str,
},
#[error("Memfd error: {0}")]
MemfdError(#[from] memfd::Error),
#[error("Dmabuf import error: {0}")]
DmabufImport(#[from] bevy_dmabuf::import::ImportError),
#[error("Server error: {0}")]
Server(#[from] ServerError),
} }
pub fn get_free_wayland_socket_path() -> Option<(PathBuf, File)> { pub fn get_free_wayland_socket_path() -> Option<(PathBuf, File)> {
@@ -93,7 +102,7 @@ pub fn get_free_wayland_socket_path() -> Option<(PathBuf, File)> {
Ok(_) => continue, // Active compositor found - skip Ok(_) => continue, // Active compositor found - skip
Err(e) if e.kind() == ErrorKind::ConnectionRefused => { Err(e) if e.kind() == ErrorKind::ConnectionRefused => {
// Stale socket - safe to remove since we hold the lock // Stale socket - safe to remove since we hold the lock
let _ = fs::remove_file(&socket_path); let _ = std::fs::remove_file(&socket_path);
} }
Err(_) => continue, // Transient error - conservative skip Err(_) => continue, // Transient error - conservative skip
} }
@@ -106,8 +115,10 @@ pub fn get_free_wayland_socket_path() -> Option<(PathBuf, File)> {
None // Exhausted all conventional display numbers None // Exhausted all conventional display numbers
} }
pub type WaylandResult<T, E = WaylandError> = std::result::Result<T, E>;
pub type Client = waynest_server::Connection<WaylandError>;
pub enum Message { pub enum Message {
Disconnect,
Frame(Vec<Arc<Callback>>), Frame(Vec<Arc<Callback>>),
ReleaseBuffer(Arc<Buffer>), ReleaseBuffer(Arc<Buffer>),
CloseToplevel(Arc<Toplevel>), CloseToplevel(Arc<Toplevel>),
@@ -135,26 +146,25 @@ struct WaylandClient {
abort_handle: AbortHandle, abort_handle: AbortHandle,
} }
impl WaylandClient { impl WaylandClient {
pub fn from_stream(socket: UnixStream) -> Result<Self> { pub fn from_stream(socket: UnixStream) -> WaylandResult<Self> {
let pid = socket.peer_cred().ok().and_then(|c| c.pid()); let pid = socket.peer_cred().ok().and_then(|c| c.pid());
let mut client = server::Client::new(socket)?; let mut client = Connection::new(socket)?;
let (message_sink, message_source) = mpsc::unbounded_channel(); let (message_sink, message_source) = mpsc::unbounded_channel();
client.insert(ObjectId::DISPLAY, Display::new(message_sink, pid)); client.insert(ObjectId::DISPLAY, Display::new(message_sink, pid));
let abort_handle = task::new( let abort_handle =
|| "wayland client", tokio::task::spawn(Self::dispatch_loop(client, message_source)).abort_handle();
Self::handle_client_messages(client, message_source),
)?
.abort_handle();
Ok(WaylandClient { abort_handle }) Ok(WaylandClient { abort_handle })
} }
async fn handle_client_messages(
mut client: server::Client, async fn dispatch_loop(
mut client: Client,
mut render_message_rx: mpsc::UnboundedReceiver<Message>, mut render_message_rx: mpsc::UnboundedReceiver<Message>,
) -> Result<()> { ) -> WaylandResult<()> {
loop { loop {
tokio::select! { tokio::select! {
biased;
// send all queued up messages // send all queued up messages
msg = render_message_rx.recv() => { msg = render_message_rx.recv() => {
if let Some(msg) = msg { if let Some(msg) = msg {
@@ -162,49 +172,32 @@ impl WaylandClient {
} }
} }
// handle the next message // handle the next message
msg = client.next_message() => { msg = client.try_next() => {
match msg { if let Some(mut msg) = msg? &&
Ok(Some(mut msg)) => { let Err(e) = client
if let Err(e) = client.handle_message(&mut msg).await { .get_raw(msg.object_id())
tracing::error!("Wayland: Error handling message: {:?}", e); .ok_or(WaylandError::MissingObject(msg.object_id()))?
break; .dispatch_request(&mut client, msg.object_id(), &mut msg)
} .await
} {
Err(e) => { if let WaylandError::Fatal { object_id, code, message } = e {
// wayland clients really aren't nice when disconnecting properly, are they? :p client.display().error(&mut client, ObjectId::DISPLAY, object_id, code, message.to_string()).await?;
if let server::Error::Decode(DecodeError::IoError(e)) = &e && e.kind() == io::ErrorKind::ConnectionReset {
if let Some(pid) = client.get::<Display>(ObjectId::DISPLAY).and_then(|d| d.pid) {
tracing::info!("Wayland: Client with pid: {pid} disconnected from server");
} else {
tracing::info!("Wayland: Unknown client disconnected from server");
}
break;
}
tracing::error!("Wayland: Error reading message: {:?}", e);
break;
}
Ok(None) => {
if let Some(pid) = client.get::<Display>(ObjectId::DISPLAY).and_then(|d| d.pid) {
tracing::info!("Wayland: Client with pid: {pid} disconnected from server");
} else {
tracing::info!("Wayland: Unknown client disconnected from server");
}
// Message stream ended
break;
} }
tracing::error!("Wayland: {e}");
return Err(e);
} }
} }
} };
} }
Ok(())
} }
async fn handle_render_message( async fn handle_render_message(client: &mut Client, message: Message) -> WaylandResult<()> {
client: &mut server::Client, use waynest_protocols::server::core::wayland::wl_buffer::WlBuffer;
message: Message, use waynest_protocols::server::core::wayland::wl_callback::WlCallback;
) -> Result<bool, waynest::server::Error> { use waynest_protocols::server::core::wayland::wl_display::WlDisplay;
use waynest_protocols::server::stable::xdg_shell::xdg_toplevel::XdgToplevel;
match message { match message {
Message::Disconnect => return Ok(true),
Message::Frame(callbacks) => { Message::Frame(callbacks) => {
let now = rustix::time::clock_gettime(rustix::time::ClockId::Monotonic); let now = rustix::time::clock_gettime(rustix::time::ClockId::Monotonic);
let now = Duration::new(now.tv_sec as u64, now.tv_nsec as u32); let now = Duration::new(now.tv_sec as u64, now.tv_nsec as u32);
@@ -251,7 +244,7 @@ impl WaylandClient {
.await?; .await?;
} }
} }
Ok(false) Ok(())
} }
} }
impl Drop for WaylandClient { impl Drop for WaylandClient {
@@ -266,16 +259,15 @@ pub struct Wayland {
abort_handle: AbortHandle, abort_handle: AbortHandle,
} }
impl Wayland { impl Wayland {
pub fn new() -> Result<Self> { pub fn new() -> color_eyre::eyre::Result<Self> {
let (socket_path, _lockfile) = let (socket_path, _lockfile) = get_free_wayland_socket_path().ok_or(WaylandError::Io(
get_free_wayland_socket_path().ok_or(ServerError::WaylandError( std::io::ErrorKind::AddrNotAvailable.into(),
waynest::server::Error::IoError(std::io::ErrorKind::AddrNotAvailable.into()), ))?;
))?;
let _ = WAYLAND_DISPLAY.set(socket_path.clone()); let _ = WAYLAND_DISPLAY.set(socket_path.clone());
let listener = let listener = waynest_server::Listener::new_with_path(&socket_path)?;
server::Listener::new_with_path(&socket_path).map_err(ServerError::WaylandError)?; let _ = WAYLAND_DISPLAY.set(listener.socket_path().to_path_buf());
let abort_handle = let abort_handle =
task::new(|| "wayland loop", Self::handle_wayland_loop(listener))?.abort_handle(); task::new(|| "wayland loop", Self::handle_wayland_loop(listener))?.abort_handle();
@@ -285,7 +277,7 @@ impl Wayland {
abort_handle, abort_handle,
}) })
} }
async fn handle_wayland_loop(mut listener: server::Listener) -> Result<()> { async fn handle_wayland_loop(mut listener: Listener) -> WaylandResult<()> {
let mut clients = Vec::new(); let mut clients = Vec::new();
loop { loop {
if let Ok(Some(stream)) = listener.try_next().await { if let Ok(Some(stream)) = listener.try_next().await {

View File

@@ -1,15 +1,10 @@
use rustix::fs::Timespec; use crate::wayland::WaylandResult;
use waynest::{
server::{
Client, Dispatcher, Result,
protocol::stable::presentation_time::{
wp_presentation::WpPresentation, wp_presentation_feedback::WpPresentationFeedback,
},
},
wire::ObjectId,
};
use crate::wayland::core::surface::Surface; use crate::wayland::core::surface::Surface;
use rustix::fs::Timespec;
use waynest::ObjectId;
use waynest_protocols::server::stable::presentation_time::{
wp_presentation::*, wp_presentation_feedback::*,
};
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct MonotonicTimestamp { pub struct MonotonicTimestamp {
@@ -37,20 +32,23 @@ impl From<Timespec> for MonotonicTimestamp {
} }
} }
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Presentation; pub struct Presentation;
impl WpPresentation for Presentation { impl WpPresentation for Presentation {
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { type Connection = crate::wayland::Client;
async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn feedback( async fn feedback(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
surface: ObjectId, surface: ObjectId,
id: ObjectId, id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
let Some(surface) = client.get::<Surface>(surface) else { let Some(surface) = client.get::<Surface>(surface) else {
tracing::error!("unable to get surface#{surface}"); tracing::error!("unable to get surface#{surface}");
return Ok(()); return Ok(());
@@ -62,6 +60,9 @@ impl WpPresentation for Presentation {
} }
} }
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct PresentationFeedback(pub ObjectId); pub struct PresentationFeedback(pub ObjectId);
impl WpPresentationFeedback for PresentationFeedback {} impl WpPresentationFeedback for PresentationFeedback {
type Connection = crate::wayland::Client;
}

View File

@@ -1,4 +1,6 @@
use crate::wayland::{Client, WaylandResult};
use crate::wayland::{ use crate::wayland::{
WaylandError,
core::{ core::{
compositor::{Compositor, WlCompositor}, compositor::{Compositor, WlCompositor},
data_device::DataDeviceManager, data_device::DataDeviceManager,
@@ -13,20 +15,15 @@ use crate::wayland::{
viewporter::Viewporter, viewporter::Viewporter,
xdg::wm_base::{WmBase, XdgWmBase}, xdg::wm_base::{WmBase, XdgWmBase},
}; };
use waynest::{ use waynest::{NewId, ObjectId};
server::{ use waynest_protocols::server::{
Client, Dispatcher, Error, Result, core::wayland::{wl_data_device_manager::WlDataDeviceManager, wl_registry::*},
protocol::{ mesa::drm::wl_drm::WlDrm,
core::wayland::{wl_data_device_manager::WlDataDeviceManager, wl_registry::*}, stable::{
mesa::drm::wl_drm::WlDrm, linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
stable::{ presentation_time::wp_presentation::WpPresentation,
linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1, viewporter::wp_viewporter::WpViewporter,
presentation_time::wp_presentation::WpPresentation,
viewporter::wp_viewporter::WpViewporter,
},
},
}, },
wire::{NewId, ObjectId},
}; };
struct RegistryGlobals; struct RegistryGlobals;
@@ -43,11 +40,16 @@ impl RegistryGlobals {
pub const VIEWPORTER: u32 = 9; pub const VIEWPORTER: u32 = 9;
} }
#[derive(Debug, Dispatcher, Default)] #[derive(Debug, waynest_server::RequestDispatcher, Default)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Registry; pub struct Registry;
impl Registry { impl Registry {
pub async fn advertise_globals(&self, client: &mut Client, sender_id: ObjectId) -> Result<()> { pub async fn advertise_globals(
&self,
client: &mut Client,
sender_id: ObjectId,
) -> WaylandResult<()> {
self.global( self.global(
client, client,
sender_id, sender_id,
@@ -143,13 +145,15 @@ impl Registry {
} }
impl WlRegistry for Registry { impl WlRegistry for Registry {
type Connection = crate::wayland::Client;
async fn bind( async fn bind(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
name: u32, name: u32,
new_id: NewId, new_id: NewId,
) -> Result<()> { ) -> WaylandResult<()> {
match name { match name {
RegistryGlobals::COMPOSITOR => { RegistryGlobals::COMPOSITOR => {
tracing::info!("Binding compositor"); tracing::info!("Binding compositor");
@@ -217,7 +221,7 @@ impl WlRegistry for Registry {
} }
id => { id => {
tracing::error!(id, "Wayland: failed to bind to registry global"); tracing::error!(id, "Wayland: failed to bind to registry global");
return Err(Error::MissingObject(unsafe { ObjectId::from_raw(name) })); return Err(WaylandError::UnknownGlobal(name));
} }
} }

View File

@@ -1,22 +1,16 @@
#![allow(unused)] #![allow(unused)]
use super::{Message, MessageSink, display::Display}; use super::{Message, MessageSink, display::Display};
use crate::wayland::{Client, WaylandError, WaylandResult};
use std::{fmt::Debug, sync::Arc}; use std::{fmt::Debug, sync::Arc};
use waynest::{ use waynest::ObjectId;
server::{Client, Result, protocol::core::wayland::wl_display::WlDisplay}, use waynest_protocols::server::core::wayland::wl_display::WlDisplay;
wire::ObjectId, use waynest_server::RequestDispatcher;
};
pub trait ClientExt { pub trait ClientExt {
fn message_sink(&self) -> MessageSink; fn message_sink(&self) -> MessageSink;
fn display(&self) -> Arc<Display>; fn display(&self) -> Arc<Display>;
async fn protocol_error( fn try_get<D: RequestDispatcher>(&self, id: ObjectId) -> WaylandResult<Arc<D>>;
&mut self,
sender_id: ObjectId,
object_id: ObjectId,
code: u32,
message: String,
) -> Result<()>;
} }
impl ClientExt for Client { impl ClientExt for Client {
fn message_sink(&self) -> MessageSink { fn message_sink(&self) -> MessageSink {
@@ -30,19 +24,8 @@ impl ClientExt for Client {
self.get::<Display>(ObjectId::DISPLAY).unwrap() self.get::<Display>(ObjectId::DISPLAY).unwrap()
} }
async fn protocol_error( fn try_get<D: RequestDispatcher>(&self, id: ObjectId) -> WaylandResult<Arc<D>> {
&mut self, self.get::<D>(id).ok_or(WaylandError::MissingObject(id))
sender_id: ObjectId,
object_id: ObjectId,
code: u32,
message: String,
) -> Result<()> {
self.display()
.error(self, sender_id, object_id, code, message)
.await?;
let _ = self.message_sink().send(Message::Disconnect);
Ok(())
} }
} }

View File

@@ -1,35 +1,37 @@
use waynest::{ use crate::wayland::WaylandResult;
server::{Client, Dispatcher, Result}, use waynest::Fixed;
wire::{Fixed, ObjectId}, use waynest::ObjectId;
}; pub use waynest_protocols::server::stable::viewporter::wp_viewport::*;
pub use waynest_protocols::server::stable::viewporter::wp_viewporter::*;
pub use waynest::server::protocol::stable::viewporter::wp_viewport::*;
pub use waynest::server::protocol::stable::viewporter::wp_viewporter::*;
// This is a barebones/stub no-op implementation of wp_viewporter to make xwayland apps work // This is a barebones/stub no-op implementation of wp_viewporter to make xwayland apps work
#[derive(Debug, Dispatcher, Default)] #[derive(Debug, waynest_server::RequestDispatcher, Default)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Viewporter; pub struct Viewporter;
impl WpViewporter for Viewporter { impl WpViewporter for Viewporter {
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { type Connection = crate::wayland::Client;
async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn get_viewport( async fn get_viewport(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
id: ObjectId, id: ObjectId,
surface_id: ObjectId, surface_id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
let viewport = Viewport::new(id, surface_id); let viewport = Viewport::new(id, surface_id);
client.insert(id, viewport); client.insert(id, viewport);
Ok(()) Ok(())
} }
} }
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Viewport { pub struct Viewport {
_id: ObjectId, _id: ObjectId,
_surface_id: ObjectId, _surface_id: ObjectId,
@@ -45,29 +47,31 @@ impl Viewport {
} }
impl WpViewport for Viewport { impl WpViewport for Viewport {
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { type Connection = crate::wayland::Client;
async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn set_source( async fn set_source(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_x: Fixed, _x: Fixed,
_y: Fixed, _y: Fixed,
_width: Fixed, _width: Fixed,
_height: Fixed, _height: Fixed,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn set_destination( async fn set_destination(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_width: i32, _width: i32,
_height: i32, _height: i32,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -3,15 +3,15 @@ use super::{
surface::Surface, surface::Surface,
}; };
use crate::nodes::items::panel::SurfaceId; use crate::nodes::items::panel::SurfaceId;
use crate::wayland::WaylandResult;
use parking_lot::Mutex; use parking_lot::Mutex;
use rand::Rng; use rand::Rng;
use std::sync::Arc; use std::sync::Arc;
use waynest::{ use waynest::ObjectId;
server::{Client, Dispatcher, Result, protocol::stable::xdg_shell::xdg_popup::XdgPopup}, use waynest_protocols::server::stable::xdg_shell::xdg_popup::XdgPopup;
wire::ObjectId,
};
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Popup { pub struct Popup {
version: u32, version: u32,
pub surface: Arc<Surface>, pub surface: Arc<Surface>,
@@ -33,25 +33,27 @@ impl Popup {
} }
} }
impl XdgPopup for Popup { impl XdgPopup for Popup {
type Connection = crate::wayland::Client;
/// https://wayland.app/protocols/xdg-shell#xdg_popup:request:grab /// https://wayland.app/protocols/xdg-shell#xdg_popup:request:grab
async fn grab( async fn grab(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_seat: ObjectId, _seat: ObjectId,
_serial: u32, _serial: u32,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
/// https://wayland.app/protocols/xdg-shell#xdg_popup:request:reposition /// https://wayland.app/protocols/xdg-shell#xdg_popup:request:reposition
async fn reposition( async fn reposition(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
sender_id: ObjectId, sender_id: ObjectId,
positioner: ObjectId, positioner: ObjectId,
token: u32, token: u32,
) -> Result<()> { ) -> WaylandResult<()> {
let positioner = client.get::<Positioner>(positioner).unwrap(); let positioner = client.get::<Positioner>(positioner).unwrap();
let positioner_data = positioner.data(); let positioner_data = positioner.data();
*self.positioner_data.lock() = positioner_data; *self.positioner_data.lock() = positioner_data;
@@ -80,7 +82,7 @@ impl XdgPopup for Popup {
} }
/// https://wayland.app/protocols/xdg-shell#xdg_popup:request:destroy /// https://wayland.app/protocols/xdg-shell#xdg_popup:request:destroy
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn destroy(&self, _client: &mut Self::Connection, _sender_id: ObjectId) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -1,15 +1,8 @@
use crate::nodes::items::panel::Geometry; use crate::{nodes::items::panel::Geometry, wayland::WaylandResult};
use mint::Vector2; use mint::Vector2;
use parking_lot::Mutex; use parking_lot::Mutex;
use waynest::{ use waynest::ObjectId;
server::{ use waynest_protocols::server::stable::xdg_shell::xdg_positioner::*;
Client, Dispatcher, Result,
protocol::stable::xdg_shell::xdg_positioner::{
Anchor, ConstraintAdjustment, Gravity, XdgPositioner,
},
},
wire::ObjectId,
};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct PositionerData { pub struct PositionerData {
@@ -133,7 +126,8 @@ impl Default for PositionerData {
} }
} }
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Positioner { pub struct Positioner {
data: Mutex<PositionerData>, data: Mutex<PositionerData>,
} }
@@ -150,13 +144,15 @@ impl Positioner {
} }
} }
impl XdgPositioner for Positioner { impl XdgPositioner for Positioner {
type Connection = crate::wayland::Client;
async fn set_size( async fn set_size(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_width: i32, _width: i32,
_height: i32, _height: i32,
) -> Result<()> { ) -> WaylandResult<()> {
let mut data = self.data.lock(); let mut data = self.data.lock();
data.size = [_width.max(0) as u32, _height.max(0) as u32].into(); data.size = [_width.max(0) as u32, _height.max(0) as u32].into();
data.reactive = true; data.reactive = true;
@@ -165,13 +161,13 @@ impl XdgPositioner for Positioner {
async fn set_anchor_rect( async fn set_anchor_rect(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_x: i32, _x: i32,
_y: i32, _y: i32,
_width: i32, _width: i32,
_height: i32, _height: i32,
) -> Result<()> { ) -> WaylandResult<()> {
let mut data = self.data.lock(); let mut data = self.data.lock();
data.anchor_rect.origin = [_x, _y].into(); data.anchor_rect.origin = [_x, _y].into();
data.anchor_rect.size = [_width.max(0) as u32, _height.max(0) as u32].into(); data.anchor_rect.size = [_width.max(0) as u32, _height.max(0) as u32].into();
@@ -181,10 +177,10 @@ impl XdgPositioner for Positioner {
async fn set_anchor( async fn set_anchor(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_anchor: Anchor, _anchor: Anchor,
) -> Result<()> { ) -> WaylandResult<()> {
let mut data = self.data.lock(); let mut data = self.data.lock();
data.anchor = _anchor; data.anchor = _anchor;
Ok(()) Ok(())
@@ -192,10 +188,10 @@ impl XdgPositioner for Positioner {
async fn set_gravity( async fn set_gravity(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
gravity: Gravity, gravity: Gravity,
) -> Result<()> { ) -> WaylandResult<()> {
let mut data = self.data.lock(); let mut data = self.data.lock();
data.gravity = gravity; data.gravity = gravity;
Ok(()) Ok(())
@@ -203,10 +199,10 @@ impl XdgPositioner for Positioner {
async fn set_constraint_adjustment( async fn set_constraint_adjustment(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_constraint_adjustment: ConstraintAdjustment, _constraint_adjustment: ConstraintAdjustment,
) -> Result<()> { ) -> WaylandResult<()> {
let mut data = self.data.lock(); let mut data = self.data.lock();
data.constraint_adjustment = _constraint_adjustment; data.constraint_adjustment = _constraint_adjustment;
Ok(()) Ok(())
@@ -214,28 +210,32 @@ impl XdgPositioner for Positioner {
async fn set_offset( async fn set_offset(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_x: i32, _x: i32,
_y: i32, _y: i32,
) -> Result<()> { ) -> WaylandResult<()> {
let mut data = self.data.lock(); let mut data = self.data.lock();
data.offset.x += _x; data.offset.x += _x;
data.offset.y += _y; data.offset.y += _y;
Ok(()) Ok(())
} }
async fn set_reactive(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn set_reactive(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn set_parent_size( async fn set_parent_size(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_parent_width: i32, _parent_width: i32,
_parent_height: i32, _parent_height: i32,
) -> Result<()> { ) -> WaylandResult<()> {
let mut data = self.data.lock(); let mut data = self.data.lock();
data.parent_size.x = _parent_width.max(0) as u32; data.parent_size.x = _parent_width.max(0) as u32;
data.parent_size.y = _parent_height.max(0) as u32; data.parent_size.y = _parent_height.max(0) as u32;
@@ -244,14 +244,18 @@ impl XdgPositioner for Positioner {
async fn set_parent_configure( async fn set_parent_configure(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_serial: u32, _serial: u32,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn destroy(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }

View File

@@ -1,17 +1,17 @@
use super::{popup::Popup, positioner::Positioner, toplevel::MappedInner}; use super::{popup::Popup, positioner::Positioner, toplevel::MappedInner};
use crate::nodes::items::panel::{ChildInfo, SurfaceId}; use crate::nodes::items::panel::{ChildInfo, SurfaceId};
use crate::wayland::Message; use crate::wayland::{Client, WaylandError};
use crate::wayland::util::ClientExt; use crate::wayland::{
use crate::wayland::{core::surface::SurfaceRole, display::Display, xdg::toplevel::Toplevel}; Message, WaylandResult, core::surface::SurfaceRole, display::Display, util::ClientExt,
use std::sync::Arc; xdg::toplevel::Toplevel,
use waynest::server::protocol::stable::xdg_shell::xdg_popup::XdgPopup;
pub use waynest::server::protocol::stable::xdg_shell::xdg_surface::*;
use waynest::{
server::{Client, Dispatcher, Result},
wire::ObjectId,
}; };
use std::sync::Arc;
use waynest::ObjectId;
use waynest_protocols::server::stable::xdg_shell::xdg_popup::XdgPopup;
pub use waynest_protocols::server::stable::xdg_shell::xdg_surface::*;
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Surface { pub struct Surface {
id: ObjectId, id: ObjectId,
version: u32, version: u32,
@@ -32,25 +32,31 @@ impl Surface {
} }
} }
pub async fn reconfigure(&self, client: &mut Client) -> Result<()> { pub async fn reconfigure(&self, client: &mut Client) -> WaylandResult<()> {
let serial = client.next_event_serial(); let serial = client.next_event_serial();
self.configure(client, self.id, serial).await self.configure(client, self.id, serial).await
} }
} }
impl XdgSurface for Surface { impl XdgSurface for Surface {
type Connection = crate::wayland::Client;
/// https://wayland.app/protocols/xdg-shell#xdg_surface:request:destroy /// https://wayland.app/protocols/xdg-shell#xdg_surface:request:destroy
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn destroy(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
/// https://wayland.app/protocols/xdg-shell#xdg_surface:request:get_toplevel /// https://wayland.app/protocols/xdg-shell#xdg_surface:request:get_toplevel
async fn get_toplevel( async fn get_toplevel(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
sender_id: ObjectId, sender_id: ObjectId,
toplevel_id: ObjectId, toplevel_id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
let toplevel = client.insert( let toplevel = client.insert(
toplevel_id, toplevel_id,
Toplevel::new( Toplevel::new(
@@ -61,7 +67,7 @@ impl XdgSurface for Surface {
); );
self.wl_surface self.wl_surface
.try_set_role(client, SurfaceRole::XdgToplevel) .try_set_role(SurfaceRole::XdgToplevel, Error::AlreadyConstructed)
.await?; .await?;
let toplevel_weak = Arc::downgrade(&toplevel); let toplevel_weak = Arc::downgrade(&toplevel);
@@ -100,35 +106,29 @@ impl XdgSurface for Surface {
/// https://wayland.app/protocols/xdg-shell#xdg_surface:request:get_popup /// https://wayland.app/protocols/xdg-shell#xdg_surface:request:get_popup
async fn get_popup( async fn get_popup(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
sender_id: ObjectId, sender_id: ObjectId,
popup_id: ObjectId, popup_id: ObjectId,
parent: Option<ObjectId>, parent: Option<ObjectId>,
positioner: ObjectId, positioner: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
self.wl_surface self.wl_surface
.try_set_role(client, SurfaceRole::XdgPopup) .try_set_role(SurfaceRole::XdgPopup, Error::AlreadyConstructed)
.await?; .await?;
let Some(parent) = parent else { let Some(parent) = parent else {
return client return Err(WaylandError::Fatal {
.protocol_error( object_id: popup_id,
sender_id, code: 3,
popup_id, message: "Parent surface does not have an XDG role",
3, // INVALID_POPUP_PARENT });
"Parent surface does not have an XDG role".to_string(),
)
.await;
}; };
let Some(parent) = client.get::<Surface>(parent) else { let Some(parent) = client.get::<Surface>(parent) else {
return client return Err(WaylandError::Fatal {
.protocol_error( object_id: popup_id,
sender_id, code: 3,
popup_id, message: "Parent surface does not exist",
3, // INVALID_POPUP_PARENT });
"Parent surface does not exist".to_string(),
)
.await;
}; };
*self.wl_surface.panel_item.lock() = parent.wl_surface.panel_item.lock().clone(); *self.wl_surface.panel_item.lock() = parent.wl_surface.panel_item.lock().clone();
let positioner = client.get::<Positioner>(positioner).unwrap(); let positioner = client.get::<Positioner>(positioner).unwrap();
@@ -192,13 +192,13 @@ impl XdgSurface for Surface {
/// https://wayland.app/protocols/xdg-shell#xdg_surface:request:set_window_geometry /// https://wayland.app/protocols/xdg-shell#xdg_surface:request:set_window_geometry
async fn set_window_geometry( async fn set_window_geometry(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_x: i32, _x: i32,
_y: i32, _y: i32,
_width: i32, _width: i32,
_height: i32, _height: i32,
) -> Result<()> { ) -> WaylandResult<()> {
// we're gonna delegate literally all the window management // we're gonna delegate literally all the window management
// to 3D stuff sooo we don't care, maximized is the floating state // to 3D stuff sooo we don't care, maximized is the floating state
Ok(()) Ok(())
@@ -207,10 +207,10 @@ impl XdgSurface for Surface {
/// https://wayland.app/protocols/xdg-shell#xdg_surface:request:ack_configure /// https://wayland.app/protocols/xdg-shell#xdg_surface:request:ack_configure
async fn ack_configure( async fn ack_configure(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_serial: u32, _serial: u32,
) -> Result<()> { ) -> WaylandResult<()> {
self.configured self.configured
.store(true, std::sync::atomic::Ordering::SeqCst); .store(true, std::sync::atomic::Ordering::SeqCst);
Ok(()) Ok(())

View File

@@ -4,16 +4,16 @@ use crate::{
Node, Node,
items::panel::{PanelItem, SurfaceId}, items::panel::{PanelItem, SurfaceId},
}, },
wayland::core::{seat::Seat, surface::Surface}, wayland::{
Client, WaylandResult,
core::{seat::Seat, surface::Surface},
},
}; };
use mint::Vector2; use mint::Vector2;
use parking_lot::Mutex; use parking_lot::Mutex;
use std::sync::Arc; use std::sync::Arc;
pub use waynest::server::protocol::stable::xdg_shell::xdg_toplevel::*; use waynest::ObjectId;
use waynest::{ pub use waynest_protocols::server::stable::xdg_shell::xdg_toplevel::*;
server::{Client, Dispatcher, Result},
wire::ObjectId,
};
#[derive(Debug)] #[derive(Debug)]
pub struct MappedInner { pub struct MappedInner {
@@ -54,7 +54,8 @@ impl Default for ToplevelData {
} }
} }
#[derive(Debug, Dispatcher)] #[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct Toplevel { pub struct Toplevel {
pub id: ObjectId, pub id: ObjectId,
xdg_surface: Arc<super::surface::Surface>, xdg_surface: Arc<super::surface::Surface>,
@@ -115,7 +116,7 @@ impl Toplevel {
clamped clamped
} }
pub async fn reconfigure(&self, client: &mut Client) -> Result<()> { pub async fn reconfigure(&self, client: &mut Client) -> WaylandResult<()> {
let data = self.data.lock().clone(); let data = self.data.lock().clone();
// Use the explicitly set size, applying constraints // Use the explicitly set size, applying constraints
@@ -152,12 +153,14 @@ impl Toplevel {
} }
} }
impl XdgToplevel for Toplevel { impl XdgToplevel for Toplevel {
type Connection = crate::wayland::Client;
async fn set_parent( async fn set_parent(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
parent: Option<ObjectId>, parent: Option<ObjectId>,
) -> Result<()> { ) -> WaylandResult<()> {
// Handle case where parent is specified // Handle case where parent is specified
if let Some(parent) = parent { if let Some(parent) = parent {
// Per spec: parent must be another xdg_toplevel surface // Per spec: parent must be another xdg_toplevel surface
@@ -188,64 +191,64 @@ impl XdgToplevel for Toplevel {
async fn set_title( async fn set_title(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
title: String, title: String,
) -> Result<()> { ) -> WaylandResult<()> {
self.data.lock().title.replace(title); self.data.lock().title.replace(title);
Ok(()) Ok(())
} }
async fn set_app_id( async fn set_app_id(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
app_id: String, app_id: String,
) -> Result<()> { ) -> WaylandResult<()> {
self.data.lock().app_id.replace(app_id); self.data.lock().app_id.replace(app_id);
Ok(()) Ok(())
} }
async fn show_window_menu( async fn show_window_menu(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_seat: ObjectId, _seat: ObjectId,
_serial: u32, _serial: u32,
_x: i32, _x: i32,
_y: i32, _y: i32,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn r#move( async fn r#move(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_seat: ObjectId, _seat: ObjectId,
_serial: u32, _serial: u32,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn resize( async fn resize(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_seat: ObjectId, _seat: ObjectId,
_serial: u32, _serial: u32,
_edges: ResizeEdge, _edges: ResizeEdge,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn set_max_size( async fn set_max_size(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
width: i32, width: i32,
height: i32, height: i32,
) -> Result<()> { ) -> WaylandResult<()> {
self.wl_surface().state_lock().pending.max_size = if width == 0 && height == 0 { self.wl_surface().state_lock().pending.max_size = if width == 0 && height == 0 {
None None
} else { } else {
@@ -256,13 +259,12 @@ impl XdgToplevel for Toplevel {
async fn set_min_size( async fn set_min_size(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
width: i32, width: i32,
height: i32, height: i32,
) -> Result<()> { ) -> WaylandResult<()> {
self.xdg_surface.wl_surface.state_lock().pending.min_size = if width == 0 && height == 0 self.xdg_surface.wl_surface.state_lock().pending.min_size = if width == 0 && height == 0 {
{
None None
} else { } else {
Some([width as u32, height as u32].into()) Some([width as u32, height as u32].into())
@@ -270,32 +272,52 @@ impl XdgToplevel for Toplevel {
Ok(()) Ok(())
} }
async fn set_maximized(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn set_maximized(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn unset_maximized(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn unset_maximized(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn set_fullscreen( async fn set_fullscreen(
&self, &self,
_client: &mut Client, _client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
_output: Option<ObjectId>, _output: Option<ObjectId>,
) -> Result<()> { ) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn unset_fullscreen(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn unset_fullscreen(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn set_minimized(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn set_minimized(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { async fn destroy(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
self.mapped.lock().take(); self.mapped.lock().take();
Ok(()) Ok(())
} }

View File

@@ -1,54 +1,51 @@
use super::positioner::Positioner; use super::positioner::Positioner;
use crate::wayland::{core::surface::SurfaceRole, util::ClientExt, xdg::surface::Surface}; use crate::wayland::{WaylandError, WaylandResult, util::ClientExt, xdg::surface::Surface};
pub use waynest::server::protocol::stable::xdg_shell::xdg_wm_base::*;
use waynest::{
server::{Client, Dispatcher, Result},
wire::ObjectId,
};
#[derive(Debug, Dispatcher, Default)] use waynest::ObjectId;
pub use waynest_protocols::server::stable::xdg_shell::xdg_wm_base::*;
#[derive(Debug, waynest_server::RequestDispatcher, Default)]
#[waynest(error = crate::wayland::WaylandError)]
pub struct WmBase { pub struct WmBase {
pub version: u32, pub version: u32,
} }
impl XdgWmBase for WmBase { impl XdgWmBase for WmBase {
async fn destroy(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { type Connection = crate::wayland::Client;
async fn destroy(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
async fn create_positioner( async fn create_positioner(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
_sender_id: ObjectId, _sender_id: ObjectId,
id: ObjectId, id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
client.insert(id, Positioner::default()); client.insert(id, Positioner::default());
Ok(()) Ok(())
} }
async fn get_xdg_surface( async fn get_xdg_surface(
&self, &self,
client: &mut Client, client: &mut Self::Connection,
sender_id: ObjectId, _sender_id: ObjectId,
xdg_surface_id: ObjectId, xdg_surface_id: ObjectId,
wl_surface_id: ObjectId, wl_surface_id: ObjectId,
) -> Result<()> { ) -> WaylandResult<()> {
let wl_surface = client let wl_surface = client.try_get::<crate::wayland::core::surface::Surface>(wl_surface_id)?;
.get::<crate::wayland::core::surface::Surface>(wl_surface_id)
.ok_or(waynest::server::Error::Custom(
"can't get wayland surface id".to_string(),
))?;
match wl_surface.role.get() { match wl_surface.role.get() {
Some(SurfaceRole::XdgToplevel | SurfaceRole::XdgPopup) => (),
None => (), None => (),
_ => { Some(_) => {
client return Err(WaylandError::Fatal {
.protocol_error( object_id: wl_surface_id,
sender_id, code: Error::Role as u32,
xdg_surface_id, message: "Wayland surface has role",
0, });
"invalid surface role".to_string(),
)
.await?
} }
}; };
let xdg_surface = Surface::new(xdg_surface_id, self.version, wl_surface); let xdg_surface = Surface::new(xdg_surface_id, self.version, wl_surface);
@@ -57,7 +54,12 @@ impl XdgWmBase for WmBase {
Ok(()) Ok(())
} }
async fn pong(&self, _client: &mut Client, _sender_id: ObjectId, _serial: u32) -> Result<()> { async fn pong(
&self,
_client: &mut Self::Connection,
_sender_id: ObjectId,
_serial: u32,
) -> WaylandResult<()> {
Ok(()) Ok(())
} }
} }