1
0
Fork 0
forked from wry/wry

autocommit 2022-01-03 18:56:52 CET

This commit is contained in:
Julian Orth 2022-01-03 18:56:52 +01:00
parent fc887b339e
commit 30376c595c
39 changed files with 3157 additions and 309 deletions

35
Cargo.lock generated
View file

@ -39,6 +39,18 @@ dependencies = [
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.72"
@ -191,9 +203,12 @@ version = "0.1.0"
dependencies = [
"ahash",
"anyhow",
"bitflags",
"env_logger",
"futures",
"log",
"num-derive",
"num-traits",
"thiserror",
"uapi",
"waker-fn",
@ -226,6 +241,26 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "num-derive"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.9.0"

View file

@ -20,3 +20,6 @@ log = "0.4.14"
env_logger = "0.9.0"
futures = "0.3.19"
waker-fn = "1.1.0"
num-traits = "0.2.14"
num-derive = "0.3.3"
bitflags = "1.3.2"

View file

@ -91,7 +91,7 @@ impl Acceptor {
if let Err(e) = uapi::listen(fd.raw(), 4096) {
return Err(AcceptorError::ListenFailed(e.into()));
}
let id = global.el.id()?;
let id = global.el.id();
let acc = Rc::new(Acceptor {
_unlinker: unlinker,
id,

View file

@ -1,8 +1,8 @@
pub use crate::async_engine::yield_::Yield;
use crate::event_loop::{EventLoopError, EventLoopRef};
use crate::event_loop::{EventLoop, EventLoopError};
use crate::utils::copyhashmap::CopyHashMap;
use crate::utils::numcell::NumCell;
use crate::wheel::{WheelError, WheelRef};
use crate::wheel::{Wheel, WheelError};
pub use fd::AsyncFd;
use fd::AsyncFdData;
use queue::{DispatchQueue, Dispatcher};
@ -24,21 +24,21 @@ pub enum AsyncError {
}
pub struct AsyncEngine {
wheel: WheelRef,
el: EventLoopRef,
wheel: Rc<Wheel>,
el: Rc<EventLoop>,
queue: Rc<DispatchQueue>,
fds: CopyHashMap<i32, Rc<AsyncFdData>>,
}
impl AsyncEngine {
pub fn new(el: &EventLoopRef, wheel: &WheelRef) -> Result<Self, AsyncError> {
pub fn install(el: &Rc<EventLoop>, wheel: &Rc<Wheel>) -> Result<Rc<Self>, AsyncError> {
let queue = Dispatcher::install(el)?;
Ok(Self {
Ok(Rc::new(Self {
wheel: wheel.clone(),
el: el.clone(),
queue,
fds: CopyHashMap::new(),
})
}))
}
pub fn timeout(&self, ms: u64) -> Result<Timeout, AsyncError> {
@ -46,7 +46,7 @@ impl AsyncEngine {
expired: Cell::new(false),
waker: RefCell::new(None),
});
let id = self.wheel.id()?;
let id = self.wheel.id();
self.wheel.timeout(id, ms, data.clone())?;
Ok(Timeout {
id,
@ -64,7 +64,7 @@ impl AsyncEngine {
afd.ref_count.fetch_add(1);
afd
} else {
let id = self.el.id()?;
let id = self.el.id();
let afd = Rc::new(AsyncFdData {
ref_count: NumCell::new(1),
fd: fd.clone(),
@ -120,7 +120,7 @@ mod yield_ {
}
mod timeout {
use crate::wheel::{WheelDispatcher, WheelId, WheelRef};
use crate::wheel::{Wheel, WheelDispatcher, WheelId};
use std::cell::{Cell, RefCell};
use std::error::Error;
use std::future::Future;
@ -145,7 +145,7 @@ mod timeout {
pub struct Timeout {
pub(super) id: WheelId,
pub(super) wheel: WheelRef,
pub(super) wheel: Rc<Wheel>,
pub(super) data: Rc<TimeoutData>,
}
@ -402,7 +402,7 @@ mod task {
mod queue {
use crate::async_engine::task::Runnable;
use crate::async_engine::AsyncError;
use crate::event_loop::{EventLoopDispatcher, EventLoopId, EventLoopRef};
use crate::event_loop::{EventLoop, EventLoopDispatcher, EventLoopId};
use crate::utils::numcell::NumCell;
use std::cell::{Cell, RefCell};
use std::collections::VecDeque;
@ -416,8 +416,8 @@ mod queue {
}
impl Dispatcher {
pub fn install(el: &EventLoopRef) -> Result<Rc<DispatchQueue>, AsyncError> {
let id = el.id()?;
pub fn install(el: &Rc<EventLoop>) -> Result<Rc<DispatchQueue>, AsyncError> {
let id = el.id();
let queue = Rc::new(DispatchQueue {
id,
el: el.clone(),
@ -462,7 +462,7 @@ mod queue {
pub(super) struct DispatchQueue {
dispatch_scheduled: Cell<bool>,
id: EventLoopId,
el: EventLoopRef,
el: Rc<EventLoop>,
queue: RefCell<VecDeque<Runnable>>,
iteration: NumCell<u64>,
}
@ -484,7 +484,7 @@ mod queue {
mod fd {
use crate::async_engine::{AsyncEngine, AsyncError};
use crate::event_loop::{EventLoopDispatcher, EventLoopError, EventLoopId, EventLoopRef};
use crate::event_loop::{EventLoop, EventLoopDispatcher, EventLoopError, EventLoopId};
use crate::utils::numcell::NumCell;
use std::cell::{Cell, RefCell};
use std::error::Error;
@ -500,7 +500,7 @@ mod fd {
pub(super) ref_count: NumCell<u64>,
pub(super) fd: Rc<OwnedFd>,
pub(super) id: EventLoopId,
pub(super) el: EventLoopRef,
pub(super) el: Rc<EventLoop>,
pub(super) write_registered: Cell<bool>,
pub(super) read_registered: Cell<bool>,
pub(super) readers: Queue,

View file

@ -9,8 +9,12 @@ use crate::ifs::wl_shm::{WlShmError, WlShmObj};
use crate::ifs::wl_shm_pool::{WlShmPool, WlShmPoolError};
use crate::ifs::wl_subcompositor::{WlSubcompositorError, WlSubcompositorObj};
use crate::ifs::wl_surface::wl_subsurface::{WlSubsurface, WlSubsurfaceError};
use crate::ifs::wl_surface::xdg_surface::xdg_popup::XdgPopupError;
use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevelError;
use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError};
use crate::ifs::wl_surface::{WlSurface, WlSurfaceError};
use crate::ifs::xdg_wm_base::XdgWmBaseObj;
use crate::ifs::xdg_positioner::{XdgPositioner, XdgPositionerError};
use crate::ifs::xdg_wm_base::{XdgWmBaseError, XdgWmBaseObj};
use crate::object::{Object, ObjectId, WL_DISPLAY_ID};
use crate::state::State;
use crate::utils::buffd::{BufFdError, MsgFormatter, MsgParser, MsgParserError};
@ -86,6 +90,16 @@ pub enum ClientError {
WlSubsurfaceError(#[source] Box<WlSubsurfaceError>),
#[error("An error occurred in a `wl_subcompositor`")]
WlSubcompositorError(#[source] Box<WlSubcompositorError>),
#[error("An error occurred in a `xdg_surface`")]
XdgSurfaceError(#[source] Box<XdgSurfaceError>),
#[error("An error occurred in a `xdg_positioner`")]
XdgPositionerError(#[source] Box<XdgPositionerError>),
#[error("An error occurred in a `xdg_popup`")]
XdgPopupError(#[source] Box<XdgPopupError>),
#[error("An error occurred in a `xdg_toplevel`")]
XdgToplevelError(#[source] Box<XdgToplevelError>),
#[error("An error occurred in a `xdg_wm_base`")]
XdgWmBaseError(#[source] Box<XdgWmBaseError>),
#[error("Object {0} is not a display")]
NotADisplay(ObjectId),
}
@ -100,6 +114,11 @@ efrom!(ClientError, WlShmPoolError, WlShmPoolError);
efrom!(ClientError, WlRegionError, WlRegionError);
efrom!(ClientError, WlSubsurfaceError, WlSubsurfaceError);
efrom!(ClientError, WlSubcompositorError, WlSubcompositorError);
efrom!(ClientError, XdgSurfaceError, XdgSurfaceError);
efrom!(ClientError, XdgPositionerError, XdgPositionerError);
efrom!(ClientError, XdgWmBaseError, XdgWmBaseError);
efrom!(ClientError, XdgToplevelError, XdgToplevelError);
efrom!(ClientError, XdgPopupError, XdgPopupError);
impl ClientError {
fn peer_closed(&self) -> bool {
@ -162,9 +181,9 @@ impl Clients {
shutdown: Cell::new(Some(send)),
shutdown_sent: Cell::new(false),
});
data.objects
.add_client_object(Rc::new(WlDisplay::new(&data)))
.expect("");
let display = Rc::new(WlDisplay::new(&data));
*data.objects.display.borrow_mut() = Some(display.clone());
data.objects.add_client_object(display).expect("");
let client = ClientHolder {
_handler: global.eng.spawn(tasks::client(data.clone(), recv)),
data,
@ -272,7 +291,10 @@ impl Client {
}
pub fn display(&self) -> Result<Rc<WlDisplay>, ClientError> {
Ok(self.objects.get_obj(WL_DISPLAY_ID)?.into_display()?)
match self.objects.display.borrow_mut().clone() {
Some(d) => Ok(d),
_ => Err(ClientError::NotADisplay(WL_DISPLAY_ID)),
}
}
pub fn parse<'a, R: RequestParser<'a>>(
@ -292,6 +314,14 @@ impl Client {
Ok(res)
}
pub fn protocol_error(&self, obj: &dyn Object, code: u32, message: String) {
if let Ok(d) = self.display() {
self.fatal_event(d.error(obj.id(), code, message));
} else {
self.state.clients.shutdown(self.id);
}
}
pub fn fatal_event(&self, event: Box<dyn EventFormatter>) {
self.events.push(WlEvent::Event(event));
self.state.clients.shutdown(self.id);
@ -407,7 +437,8 @@ simple_add_obj!(WlShmObj);
simple_add_obj!(WlShmPool);
simple_add_obj!(WlSubcompositorObj);
simple_add_obj!(WlSubsurface);
simple_add_obj!(XdgWmBaseObj);
simple_add_obj!(XdgPositioner);
simple_add_obj!(XdgSurface);
macro_rules! dedicated_add_obj {
($ty:ty, $field:ident) => {
@ -429,3 +460,4 @@ macro_rules! dedicated_add_obj {
dedicated_add_obj!(WlRegion, regions);
dedicated_add_obj!(WlSurface, surfaces);
dedicated_add_obj!(XdgWmBaseObj, xdg_wm_bases);

View file

@ -1,4 +1,5 @@
use crate::client::{Client, ClientError};
use crate::ifs::wl_display::WlDisplay;
use crate::ifs::wl_region::WlRegion;
use crate::ifs::wl_registry::WlRegistry;
use crate::ifs::wl_surface::WlSurface;
@ -8,12 +9,15 @@ use ahash::AHashMap;
use std::cell::{RefCell, RefMut};
use std::mem;
use std::rc::Rc;
use crate::ifs::xdg_wm_base::XdgWmBaseObj;
pub struct Objects {
pub display: RefCell<Option<Rc<WlDisplay>>>,
registry: CopyHashMap<ObjectId, Rc<dyn Object>>,
registries: CopyHashMap<ObjectId, Rc<WlRegistry>>,
pub surfaces: CopyHashMap<ObjectId, Rc<WlSurface>>,
pub regions: CopyHashMap<ObjectId, Rc<WlRegion>>,
pub xdg_wm_bases: CopyHashMap<ObjectId, Rc<XdgWmBaseObj>>,
ids: RefCell<Vec<usize>>,
}
@ -23,10 +27,12 @@ const SEG_SIZE: usize = 8 * mem::size_of::<usize>();
impl Objects {
pub fn new() -> Self {
Self {
display: RefCell::new(None),
registry: Default::default(),
registries: Default::default(),
surfaces: Default::default(),
regions: Default::default(),
xdg_wm_bases: Default::default(),
ids: RefCell::new(vec![]),
}
}
@ -38,6 +44,13 @@ impl Objects {
surface.break_loops();
}
}
{
let mut xdg_wm_bases = self.xdg_wm_bases.lock();
for xdg_wm_base in xdg_wm_bases.values_mut() {
xdg_wm_base.break_loops();
}
}
*self.display.borrow_mut() = None;
self.registry.clear();
self.regions.clear();
self.registries.clear();

View file

@ -114,7 +114,10 @@ async fn send(data: Rc<Client>) {
if log::log_enabled!(log::Level::Trace) {
data.log_event(&*e);
}
e.format(&mut MsgFormatter::new(&mut buf));
let mut fds = vec![];
let mut fmt = MsgFormatter::new(&mut buf, &mut fds);
e.format(&mut fmt);
fmt.write_len();
if buf.needs_flush() {
buf.flush().await?;
flush_requested = false;

View file

@ -2,7 +2,7 @@ use crate::utils::copyhashmap::CopyHashMap;
use crate::utils::numcell::NumCell;
use std::cell::{Cell, RefCell};
use std::collections::VecDeque;
use std::rc::{Rc, Weak};
use std::rc::Rc;
use thiserror::Error;
use uapi::{c, Errno, OwnedFd};
@ -39,53 +39,53 @@ struct Entry {
dispatcher: Rc<dyn EventLoopDispatcher>,
}
struct EventLoopData {
pub struct EventLoop {
destroyed: Cell<bool>,
epoll: OwnedFd,
run: Cell<bool>,
next_id: NumCell<u64>,
entries: CopyHashMap<u64, Entry>,
scheduled: RefCell<VecDeque<u64>>,
}
pub struct EventLoop {
data: Rc<EventLoopData>,
}
#[derive(Clone)]
pub struct EventLoopRef {
data: Weak<EventLoopData>,
}
impl EventLoopData {
fn new() -> Result<Self, EventLoopError> {
impl EventLoop {
pub fn new() -> Result<Rc<Self>, EventLoopError> {
let epoll = match uapi::epoll_create1(c::EPOLL_CLOEXEC) {
Ok(e) => e,
Err(e) => return Err(EventLoopError::CreateFailed(e.into())),
};
Ok(Self {
Ok(Rc::new(Self {
destroyed: Cell::new(false),
epoll,
run: Cell::new(true),
next_id: NumCell::new(1),
entries: CopyHashMap::new(),
scheduled: RefCell::new(Default::default()),
})
}))
}
fn id(&self) -> EventLoopId {
fn check_destroyed(&self) -> Result<(), EventLoopError> {
if self.destroyed.get() {
return Err(EventLoopError::Destroyed);
}
Ok(())
}
pub fn id(&self) -> EventLoopId {
EventLoopId(self.next_id.fetch_add(1))
}
fn stop(&self) {
self.run.set(false);
pub fn stop(&self) {
self.destroyed.set(true);
self.entries.clear();
}
fn insert(
pub fn insert(
&self,
id: EventLoopId,
fd: Option<i32>,
events: i32,
dispatcher: Rc<dyn EventLoopDispatcher>,
) -> Result<(), EventLoopError> {
self.check_destroyed()?;
let id = id.0;
if let Some(fd) = fd {
let event = c::epoll_event {
@ -100,7 +100,8 @@ impl EventLoopData {
Ok(())
}
fn modify(&self, id: EventLoopId, events: i32) -> Result<(), EventLoopError> {
pub fn modify(&self, id: EventLoopId, events: i32) -> Result<(), EventLoopError> {
self.check_destroyed()?;
let id = id.0;
let entry = match self.entries.get(&id) {
Some(e) => e,
@ -118,7 +119,8 @@ impl EventLoopData {
Ok(())
}
fn remove(&self, id: EventLoopId) -> Result<(), EventLoopError> {
pub fn remove(&self, id: EventLoopId) -> Result<(), EventLoopError> {
self.check_destroyed()?;
let id = id.0;
let entry = match self.entries.remove(&id) {
Some(e) => e,
@ -132,15 +134,24 @@ impl EventLoopData {
Ok(())
}
fn schedule(&self, id: EventLoopId) {
pub fn schedule(&self, id: EventLoopId) -> Result<(), EventLoopError> {
self.check_destroyed()?;
self.scheduled.borrow_mut().push_back(id.0);
Ok(())
}
fn run(&self) -> Result<(), EventLoopError> {
pub fn run(&self) -> Result<(), EventLoopError> {
let res = self.run_();
self.stop();
res
}
fn run_(&self) -> Result<(), EventLoopError> {
self.check_destroyed()?;
let mut buf = [c::epoll_event { events: 0, u64: 0 }; 16];
while self.run.get() {
while !self.destroyed.get() {
while let Some(id) = self.scheduled.borrow_mut().pop_front() {
if !self.run.get() {
if self.destroyed.get() {
break;
}
if let Some(entry) = self.entries.get(&id) {
@ -155,7 +166,7 @@ impl EventLoopData {
Err(e) => return Err(EventLoopError::WaitFailed(e.into())),
};
for event in &buf[..num] {
if !self.run.get() {
if self.destroyed.get() {
break;
}
let id = event.u64;
@ -177,70 +188,3 @@ impl EventLoopData {
Ok(())
}
}
impl EventLoop {
pub fn new() -> Result<Self, EventLoopError> {
Ok(Self {
data: Rc::new(EventLoopData::new()?),
})
}
pub fn to_ref(&self) -> EventLoopRef {
EventLoopRef {
data: Rc::downgrade(&self.data),
}
}
pub fn run(&self) -> Result<(), EventLoopError> {
self.data.run()
}
}
impl EventLoopRef {
pub fn id(&self) -> Result<EventLoopId, EventLoopError> {
match self.data.upgrade() {
Some(d) => Ok(d.id()),
None => Err(EventLoopError::Destroyed),
}
}
pub fn stop(&self) {
if let Some(d) = self.data.upgrade() {
d.stop();
}
}
pub fn insert(
&self,
id: EventLoopId,
fd: Option<i32>,
events: i32,
dispatcher: Rc<dyn EventLoopDispatcher>,
) -> Result<(), EventLoopError> {
match self.data.upgrade() {
Some(d) => d.insert(id, fd, events, dispatcher),
None => Err(EventLoopError::Destroyed),
}
}
pub fn modify(&self, id: EventLoopId, events: i32) -> Result<(), EventLoopError> {
match self.data.upgrade() {
Some(d) => d.modify(id, events),
None => Err(EventLoopError::Destroyed),
}
}
pub fn remove(&self, id: EventLoopId) -> Result<(), EventLoopError> {
match self.data.upgrade() {
Some(d) => d.remove(id),
None => Err(EventLoopError::Destroyed),
}
}
pub fn schedule(&self, id: EventLoopId) -> Result<(), EventLoopError> {
match self.data.upgrade() {
Some(d) => Ok(d.schedule(id)),
None => Err(EventLoopError::Destroyed),
}
}
}

462
src/format.rs Normal file
View file

@ -0,0 +1,462 @@
use ahash::AHashMap;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Format {
pub id: u32,
pub name: &'static str,
}
pub fn formats() -> AHashMap<u32, &'static Format> {
let mut map = AHashMap::new();
for format in FORMATS {
assert!(map.insert(format.id, format).is_none());
}
map
}
const fn fourcc_code(a: char, b: char, c: char, d: char) -> u32 {
(a as u32) | ((b as u32) << 8) | ((c as u32) << 16) | ((d as u32) << 24)
}
static FORMATS: &[Format] = &[
Format {
id: 0,
name: "argb8888",
},
Format {
id: 1,
name: "xrgb8888",
},
// Format {
// id: fourcc_code('C', '8', ' ', ' '),
// name: "c8",
// },
// Format {
// id: fourcc_code('R', '8', ' ', ' '),
// name: "r8",
// },
// Format {
// id: fourcc_code('R', '1', '6', ' '),
// name: "r16",
// },
// Format {
// id: fourcc_code('R', 'G', '8', '8'),
// name: "rg88",
// },
// Format {
// id: fourcc_code('G', 'R', '8', '8'),
// name: "gr88",
// },
// Format {
// id: fourcc_code('R', 'G', '3', '2'),
// name: "rg1616",
// },
// Format {
// id: fourcc_code('G', 'R', '3', '2'),
// name: "gr1616",
// },
// Format {
// id: fourcc_code('R', 'G', 'B', '8'),
// name: "rgb332",
// },
// Format {
// id: fourcc_code('B', 'G', 'R', '8'),
// name: "bgr233",
// },
// Format {
// id: fourcc_code('X', 'R', '1', '2'),
// name: "xrgb4444",
// },
// Format {
// id: fourcc_code('X', 'B', '1', '2'),
// name: "xbgr4444",
// },
// Format {
// id: fourcc_code('R', 'X', '1', '2'),
// name: "rgbx4444",
// },
// Format {
// id: fourcc_code('B', 'X', '1', '2'),
// name: "bgrx4444",
// },
// Format {
// id: fourcc_code('A', 'R', '1', '2'),
// name: "argb4444",
// },
// Format {
// id: fourcc_code('A', 'B', '1', '2'),
// name: "abgr4444",
// },
// Format {
// id: fourcc_code('R', 'A', '1', '2'),
// name: "rgba4444",
// },
// Format {
// id: fourcc_code('B', 'A', '1', '2'),
// name: "bgra4444",
// },
// Format {
// id: fourcc_code('X', 'R', '1', '5'),
// name: "xrgb1555",
// },
// Format {
// id: fourcc_code('X', 'B', '1', '5'),
// name: "xbgr1555",
// },
// Format {
// id: fourcc_code('R', 'X', '1', '5'),
// name: "rgbx5551",
// },
// Format {
// id: fourcc_code('B', 'X', '1', '5'),
// name: "bgrx5551",
// },
// Format {
// id: fourcc_code('A', 'R', '1', '5'),
// name: "argb1555",
// },
// Format {
// id: fourcc_code('A', 'B', '1', '5'),
// name: "abgr1555",
// },
// Format {
// id: fourcc_code('R', 'A', '1', '5'),
// name: "rgba5551",
// },
// Format {
// id: fourcc_code('B', 'A', '1', '5'),
// name: "bgra5551",
// },
// Format {
// id: fourcc_code('R', 'G', '1', '6'),
// name: "rgb565",
// },
// Format {
// id: fourcc_code('B', 'G', '1', '6'),
// name: "bgr565",
// },
// Format {
// id: fourcc_code('R', 'G', '2', '4'),
// name: "rgb888",
// },
// Format {
// id: fourcc_code('B', 'G', '2', '4'),
// name: "bgr888",
// },
// Format {
// id: fourcc_code('X', 'R', '2', '4'),
// name: "xrgb8888",
// },
// Format {
// id: fourcc_code('X', 'B', '2', '4'),
// name: "xbgr8888",
// },
// Format {
// id: fourcc_code('R', 'X', '2', '4'),
// name: "rgbx8888",
// },
// Format {
// id: fourcc_code('B', 'X', '2', '4'),
// name: "bgrx8888",
// },
// Format {
// id: fourcc_code('A', 'R', '2', '4'),
// name: "argb8888",
// },
// Format {
// id: fourcc_code('A', 'B', '2', '4'),
// name: "abgr8888",
// },
// Format {
// id: fourcc_code('R', 'A', '2', '4'),
// name: "rgba8888",
// },
// Format {
// id: fourcc_code('B', 'A', '2', '4'),
// name: "bgra8888",
// },
// Format {
// id: fourcc_code('X', 'R', '3', '0'),
// name: "xrgb2101010",
// },
// Format {
// id: fourcc_code('X', 'B', '3', '0'),
// name: "xbgr2101010",
// },
// Format {
// id: fourcc_code('R', 'X', '3', '0'),
// name: "rgbx1010102",
// },
// Format {
// id: fourcc_code('B', 'X', '3', '0'),
// name: "bgrx1010102",
// },
// Format {
// id: fourcc_code('A', 'R', '3', '0'),
// name: "argb2101010",
// },
// Format {
// id: fourcc_code('A', 'B', '3', '0'),
// name: "abgr2101010",
// },
// Format {
// id: fourcc_code('R', 'A', '3', '0'),
// name: "rgba1010102",
// },
// Format {
// id: fourcc_code('B', 'A', '3', '0'),
// name: "bgra1010102",
// },
// Format {
// id: fourcc_code('X', 'R', '4', '8'),
// name: "xrgb16161616",
// },
// Format {
// id: fourcc_code('X', 'B', '4', '8'),
// name: "xbgr16161616",
// },
// Format {
// id: fourcc_code('A', 'R', '4', '8'),
// name: "argb16161616",
// },
// Format {
// id: fourcc_code('A', 'B', '4', '8'),
// name: "abgr16161616",
// },
// Format {
// id: fourcc_code('X', 'R', '4', 'H'),
// name: "xrgb16161616f",
// },
// Format {
// id: fourcc_code('X', 'B', '4', 'H'),
// name: "xbgr16161616f",
// },
// Format {
// id: fourcc_code('A', 'R', '4', 'H'),
// name: "argb16161616f",
// },
// Format {
// id: fourcc_code('A', 'B', '4', 'H'),
// name: "abgr16161616f",
// },
// Format {
// id: fourcc_code('A', 'B', '1', '0'),
// name: "axbxgxrx106106106106",
// },
// Format {
// id: fourcc_code('Y', 'U', 'Y', 'V'),
// name: "yuyv",
// },
// Format {
// id: fourcc_code('Y', 'V', 'Y', 'U'),
// name: "yvyu",
// },
// Format {
// id: fourcc_code('U', 'Y', 'V', 'Y'),
// name: "uyvy",
// },
// Format {
// id: fourcc_code('V', 'Y', 'U', 'Y'),
// name: "vyuy",
// },
// Format {
// id: fourcc_code('A', 'Y', 'U', 'V'),
// name: "ayuv",
// },
// Format {
// id: fourcc_code('X', 'Y', 'U', 'V'),
// name: "xyuv8888",
// },
// Format {
// id: fourcc_code('V', 'U', '2', '4'),
// name: "vuy888",
// },
// Format {
// id: fourcc_code('V', 'U', '3', '0'),
// name: "vuy101010",
// },
// Format {
// id: fourcc_code('Y', '2', '1', '0'),
// name: "y210",
// },
// Format {
// id: fourcc_code('Y', '2', '1', '2'),
// name: "y212",
// },
// Format {
// id: fourcc_code('Y', '2', '1', '6'),
// name: "y216",
// },
// Format {
// id: fourcc_code('Y', '4', '1', '0'),
// name: "y410",
// },
// Format {
// id: fourcc_code('Y', '4', '1', '2'),
// name: "y412",
// },
// Format {
// id: fourcc_code('Y', '4', '1', '6'),
// name: "y416",
// },
// Format {
// id: fourcc_code('X', 'V', '3', '0'),
// name: "xvyu2101010",
// },
// Format {
// id: fourcc_code('X', 'V', '3', '6'),
// name: "xvyu12_16161616",
// },
// Format {
// id: fourcc_code('X', 'V', '4', '8'),
// name: "xvyu16161616",
// },
// Format {
// id: fourcc_code('Y', '0', 'L', '0'),
// name: "y0l0",
// },
// Format {
// id: fourcc_code('X', '0', 'L', '0'),
// name: "x0l0",
// },
// Format {
// id: fourcc_code('Y', '0', 'L', '2'),
// name: "y0l2",
// },
// Format {
// id: fourcc_code('X', '0', 'L', '2'),
// name: "x0l2",
// },
// Format {
// id: fourcc_code('Y', 'U', '0', '8'),
// name: "yuv420_8bit",
// },
// Format {
// id: fourcc_code('Y', 'U', '1', '0'),
// name: "yuv420_10bit",
// },
// Format {
// id: fourcc_code('X', 'R', 'A', '8'),
// name: "xrgb8888_a8",
// },
// Format {
// id: fourcc_code('X', 'B', 'A', '8'),
// name: "xbgr8888_a8",
// },
// Format {
// id: fourcc_code('R', 'X', 'A', '8'),
// name: "rgbx8888_a8",
// },
// Format {
// id: fourcc_code('B', 'X', 'A', '8'),
// name: "bgrx8888_a8",
// },
// Format {
// id: fourcc_code('R', '8', 'A', '8'),
// name: "rgb888_a8",
// },
// Format {
// id: fourcc_code('B', '8', 'A', '8'),
// name: "bgr888_a8",
// },
// Format {
// id: fourcc_code('R', '5', 'A', '8'),
// name: "rgb565_a8",
// },
// Format {
// id: fourcc_code('B', '5', 'A', '8'),
// name: "bgr565_a8",
// },
// Format {
// id: fourcc_code('N', 'V', '1', '2'),
// name: "nv12",
// },
// Format {
// id: fourcc_code('N', 'V', '2', '1'),
// name: "nv21",
// },
// Format {
// id: fourcc_code('N', 'V', '1', '6'),
// name: "nv16",
// },
// Format {
// id: fourcc_code('N', 'V', '6', '1'),
// name: "nv61",
// },
// Format {
// id: fourcc_code('N', 'V', '2', '4'),
// name: "nv24",
// },
// Format {
// id: fourcc_code('N', 'V', '4', '2'),
// name: "nv42",
// },
// Format {
// id: fourcc_code('N', 'V', '1', '5'),
// name: "nv15",
// },
// Format {
// id: fourcc_code('P', '2', '1', '0'),
// name: "p210",
// },
// Format {
// id: fourcc_code('P', '0', '1', '0'),
// name: "p010",
// },
// Format {
// id: fourcc_code('P', '0', '1', '2'),
// name: "p012",
// },
// Format {
// id: fourcc_code('P', '0', '1', '6'),
// name: "p016",
// },
// Format {
// id: fourcc_code('Q', '4', '1', '0'),
// name: "q410",
// },
// Format {
// id: fourcc_code('Q', '4', '0', '1'),
// name: "q401",
// },
// Format {
// id: fourcc_code('Y', 'U', 'V', '9'),
// name: "yuv410",
// },
// Format {
// id: fourcc_code('Y', 'V', 'U', '9'),
// name: "yvu410",
// },
// Format {
// id: fourcc_code('Y', 'U', '1', '1'),
// name: "yuv411",
// },
// Format {
// id: fourcc_code('Y', 'V', '1', '1'),
// name: "yvu411",
// },
// Format {
// id: fourcc_code('Y', 'U', '1', '2'),
// name: "yuv420",
// },
// Format {
// id: fourcc_code('Y', 'V', '1', '2'),
// name: "yvu420",
// },
// Format {
// id: fourcc_code('Y', 'U', '1', '6'),
// name: "yuv422",
// },
// Format {
// id: fourcc_code('Y', 'V', '1', '6'),
// name: "yvu422",
// },
// Format {
// id: fourcc_code('Y', 'U', '2', '4'),
// name: "yuv444",
// },
// Format {
// id: fourcc_code('Y', 'V', '2', '4'),
// name: "yvu444",
// },
];

View file

@ -7,4 +7,5 @@ pub mod wl_shm;
pub mod wl_shm_pool;
pub mod wl_subcompositor;
pub mod wl_surface;
pub mod xdg_positioner;
pub mod xdg_wm_base;

View file

@ -1,6 +1,6 @@
mod types;
use crate::client::{AddObj, Client, ClientError, DynEventFormatter};
use crate::client::{AddObj, Client, DynEventFormatter};
use crate::ifs::wl_callback::WlCallback;
use crate::ifs::wl_registry::WlRegistry;
use crate::object::{Interface, Object, ObjectId, WL_DISPLAY_ID};
@ -64,7 +64,7 @@ impl WlDisplay {
Ok(())
}
fn error(
pub fn error(
self: &Rc<Self>,
object_id: ObjectId,
code: u32,
@ -120,8 +120,4 @@ impl Object for WlDisplay {
fn num_requests(&self) -> u32 {
GET_REGISTRY + 1
}
fn into_display(self: Rc<Self>) -> Result<Rc<WlDisplay>, ClientError> {
Ok(self)
}
}

View file

@ -39,7 +39,7 @@ impl WlShmGlobal {
client: client.clone(),
});
client.add_client_obj(&obj)?;
for &format in Format::formats() {
for &format in client.state.formats.values() {
client
.event(Box::new(FormatE {
obj: obj.clone(),
@ -80,25 +80,6 @@ impl WlShmObj {
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Format {
Argb8888,
Xrgb8888,
}
impl Format {
fn uint(self) -> u32 {
match self {
Format::Argb8888 => 0,
Format::Xrgb8888 => 1,
}
}
fn formats() -> &'static [Format] {
&[Format::Argb8888, Format::Xrgb8888]
}
}
bind!(WlShmGlobal);
impl Global for WlShmGlobal {

View file

@ -1,5 +1,6 @@
use crate::client::{ClientError, EventFormatter, RequestParser};
use crate::ifs::wl_shm::{Format, WlShmObj, FORMAT};
use crate::format::Format;
use crate::ifs::wl_shm::{WlShmObj, FORMAT};
use crate::ifs::wl_shm_pool::WlShmPoolError;
use crate::object::{Object, ObjectId};
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
@ -60,11 +61,11 @@ impl Debug for CreatePool {
pub(super) struct FormatE {
pub obj: Rc<WlShmObj>,
pub format: Format,
pub format: &'static Format,
}
impl EventFormatter for FormatE {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, FORMAT).uint(self.format.uint());
fmt.header(self.obj.id, FORMAT).uint(self.format.id);
}
fn obj(&self) -> &dyn Object {
&*self.obj
@ -72,6 +73,10 @@ impl EventFormatter for FormatE {
}
impl Debug for FormatE {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "format(format: {:?})", self.format)
write!(
f,
"format(format: \"{}\" (0x{:x}))",
self.format.name, self.format.id
)
}
}

View file

@ -36,26 +36,26 @@ impl WlShmPool {
}
async fn create_buffer(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateBufferError> {
let create: CreateBuffer = self.client.parse(self, parser)?;
let req: CreateBuffer = self.client.parse(self, parser)?;
Ok(())
}
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _destroy: Destroy = self.client.parse(self, parser)?;
let _req: Destroy = self.client.parse(self, parser)?;
self.client.remove_obj(self).await?;
Ok(())
}
async fn resize(&self, parser: MsgParser<'_, '_>) -> Result<(), ResizeError> {
let resize: Resize = self.client.parse(self, parser)?;
let req: Resize = self.client.parse(self, parser)?;
let mut mem = self.mem.borrow_mut();
if resize.size < 0 {
if req.size < 0 {
return Err(ResizeError::NegativeSize);
}
if (resize.size as usize) < mem.len() {
if (req.size as usize) < mem.len() {
return Err(ResizeError::CannotShrink);
}
*mem = Rc::new(ClientMem::new(self.fd.raw(), resize.size as usize)?);
*mem = Rc::new(ClientMem::new(self.fd.raw(), req.size as usize)?);
Ok(())
}

View file

@ -55,9 +55,9 @@ impl WlSubcompositorObj {
let req: GetSubsurface = self.client.parse(self, parser)?;
let surface = self.client.get_surface(req.surface)?;
let parent = self.client.get_surface(req.parent)?;
let subsurface = Rc::new(WlSubsurface::new(req.id, &surface));
let subsurface = Rc::new(WlSubsurface::new(req.id, &surface, &parent));
self.client.add_client_obj(&subsurface)?;
subsurface.install(&parent)?;
subsurface.install()?;
Ok(())
}

View file

@ -1,15 +1,18 @@
mod types;
pub mod wl_subsurface;
pub mod xdg_surface;
use crate::client::{Client, RequestParser};
use crate::client::{AddObj, Client, RequestParser};
use crate::ifs::wl_surface::wl_subsurface::WlSubsurface;
use crate::object::{Interface, Object, ObjectId};
use crate::pixman::Region;
use crate::utils::buffd::{MsgParser, MsgParserError};
use crate::utils::linkedlist::{LinkedList, Node};
use ahash::AHashMap;
use std::cell::{Cell, RefCell};
use std::rc::Rc;
pub use types::*;
use crate::ifs::wl_surface::xdg_surface::XdgSurface;
const DESTROY: u32 = 0;
const ATTACH: u32 = 1;
@ -30,18 +33,41 @@ const INVALID_TRANSFORM: u32 = 1;
const INVALID_SIZE: u32 = 2;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SurfaceType {
pub enum SurfaceRole {
None,
Subsurface,
XdgSurface,
}
impl SurfaceRole {
fn name(self) -> &'static str {
match self {
SurfaceRole::None => "none",
SurfaceRole::Subsurface => "subsurface",
SurfaceRole::XdgSurface => "xdg_surface",
}
}
}
pub struct WlSurface {
id: ObjectId,
client: Rc<Client>,
ty: Cell<SurfaceType>,
role: Cell<SurfaceRole>,
pending: PendingState,
children: RefCell<Option<Box<ParentData>>>,
subsurface_data: RefCell<Option<Box<SubsurfaceData>>>,
role_data: RefCell<RoleData>,
}
enum RoleData {
None,
Subsurface(Box<SubsurfaceData>),
XdgSurface(Box<XdgSurfaceData>),
}
impl RoleData {
fn is_some(&self) -> bool {
!matches!(self, RoleData::None)
}
}
#[derive(Default)]
@ -50,18 +76,52 @@ struct PendingState {
input_region: Cell<Option<Region>>,
}
struct XdgSurfaceData {
xdg_surface: Rc<XdgSurface>,
role: XdgSurfaceRole,
}
enum XdgSurfaceRole {
None,
Popup(XdgPopupData),
Toplevel(XdgToplevelData),
}
struct XdgPopupData {
}
struct XdgToplevelData {
}
struct SubsurfaceData {
subsurface: Rc<WlSubsurface>,
parent: Rc<WlSurface>,
x: i32,
y: i32,
sync_requested: bool,
sync_ancestor: bool,
pending: bool,
node: Node<StackElement>,
depth: u32,
pending: PendingSubsurfaceData,
}
#[derive(Default)]
struct PendingSubsurfaceData {
node: Option<Node<StackElement>>,
position: Option<(i32, i32)>,
}
#[derive(Default)]
struct ParentData {
subsurfaces: AHashMap<ObjectId, Rc<WlSurface>>,
pending_subsurfaces: AHashMap<ObjectId, Rc<WlSurface>>,
below: LinkedList<StackElement>,
above: LinkedList<StackElement>,
}
struct StackElement {
pending: Cell<bool>,
surface: Rc<WlSurface>,
}
impl WlSurface {
@ -69,26 +129,26 @@ impl WlSurface {
Self {
id,
client: client.clone(),
ty: Cell::new(SurfaceType::None),
role: Cell::new(SurfaceRole::None),
pending: Default::default(),
children: Default::default(),
subsurface_data: Default::default(),
role_data: RefCell::new(RoleData::None),
}
}
pub fn break_loops(&self) {
*self.children.borrow_mut() = None;
*self.subsurface_data.borrow_mut() = None;
*self.role_data.borrow_mut() = RoleData::None;
}
pub fn get_root(self: &Rc<Self>) -> Rc<WlSurface> {
let mut root = self.clone();
loop {
let tmp = root;
let data = tmp.subsurface_data.borrow();
match data.as_ref() {
Some(d) => root = d.parent.clone(),
None => {
let data = tmp.role_data.borrow();
match &*data {
RoleData::Subsurface(d) => root = d.subsurface.parent.clone(),
_ => {
drop(data);
return tmp;
}
@ -104,22 +164,25 @@ impl WlSurface {
}
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let destroy: Destroy = self.parse(parser)?;
let _req: Destroy = self.parse(parser)?;
*self.children.borrow_mut() = None;
*self.role_data.borrow_mut() = RoleData::None;
self.client.remove_obj(self).await?;
Ok(())
}
async fn attach(&self, parser: MsgParser<'_, '_>) -> Result<(), AttachError> {
let attach: Attach = self.parse(parser)?;
let req: Attach = self.parse(parser)?;
Ok(())
}
async fn damage(&self, parser: MsgParser<'_, '_>) -> Result<(), DamageError> {
let damage: Damage = self.parse(parser)?;
let req: Damage = self.parse(parser)?;
Ok(())
}
async fn frame(&self, parser: MsgParser<'_, '_>) -> Result<(), FrameError> {
let frame: Frame = self.parse(parser)?;
let req: Frame = self.parse(parser)?;
Ok(())
}
@ -134,14 +197,14 @@ impl WlSurface {
}
async fn set_input_region(&self, parser: MsgParser<'_, '_>) -> Result<(), SetInputRegionError> {
let region: SetInputRegion = self.parse(parser)?;
let region = self.client.get_region(region.region)?;
let req: SetInputRegion = self.parse(parser)?;
let region = self.client.get_region(req.region)?;
self.pending.input_region.set(Some(region.region()));
Ok(())
}
async fn commit(&self, parser: MsgParser<'_, '_>) -> Result<(), CommitError> {
let commit: Commit = self.parse(parser)?;
let req: Commit = self.parse(parser)?;
Ok(())
}
@ -149,17 +212,17 @@ impl WlSurface {
&self,
parser: MsgParser<'_, '_>,
) -> Result<(), SetBufferTransformError> {
let transform: SetBufferTransform = self.parse(parser)?;
let req: SetBufferTransform = self.parse(parser)?;
Ok(())
}
async fn set_buffer_scale(&self, parser: MsgParser<'_, '_>) -> Result<(), SetBufferScaleError> {
let scale: SetBufferScale = self.parse(parser)?;
let req: SetBufferScale = self.parse(parser)?;
Ok(())
}
async fn damage_buffer(&self, parser: MsgParser<'_, '_>) -> Result<(), DamageBufferError> {
let damage: DamageBuffer = self.parse(parser)?;
let req: DamageBuffer = self.parse(parser)?;
Ok(())
}

View file

@ -46,8 +46,11 @@ efrom!(WlSurfaceError, DamageBufferError, DamageBufferError);
pub enum DestroyError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(DestroyError, ParseFailed, MsgParserError);
efrom!(DestroyError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum AttachError {

View file

@ -1,8 +1,10 @@
mod types;
use crate::ifs::wl_surface::{SubsurfaceData, SurfaceType, WlSurface};
use crate::client::AddObj;
use crate::ifs::wl_surface::{RoleData, StackElement, SubsurfaceData, SurfaceRole, WlSurface};
use crate::object::{Interface, Object, ObjectId};
use crate::utils::buffd::MsgParser;
use std::cell::Cell;
use std::rc::Rc;
pub use types::*;
@ -15,85 +17,211 @@ const SET_DESYNC: u32 = 5;
const BAD_SURFACE: u32 = 0;
const MAX_SUBSURFACE_DEPTH: u32 = 100;
pub struct WlSubsurface {
id: ObjectId,
surface: Rc<WlSurface>,
pub(super) parent: Rc<WlSurface>,
}
fn update_children_sync(surface: &Rc<WlSurface>, sync: bool) -> Result<(), WlSubsurfaceError> {
let children = surface.children.borrow();
if let Some(children) = &*children {
for child in children.subsurfaces.values() {
let mut data = child.role_data.borrow_mut();
if let RoleData::Subsurface(data) = &mut *data {
let was_sync = data.sync_ancestor || data.sync_requested;
data.sync_ancestor = sync;
let is_sync = data.sync_ancestor || data.sync_requested;
if was_sync != is_sync {
update_children_sync(child, sync);
}
}
}
}
Ok(())
}
fn update_children_attach(
surface: &Rc<WlSurface>,
sync: bool,
depth: u32,
) -> Result<(), WlSubsurfaceError> {
let children = surface.children.borrow();
if let Some(children) = &*children {
for child in children.subsurfaces.values() {
let mut data = child.role_data.borrow_mut();
if let RoleData::Subsurface(data) = &mut *data {
data.depth = depth + 1;
if data.depth > MAX_SUBSURFACE_DEPTH {
return Err(WlSubsurfaceError::MaxDepthExceeded);
}
data.sync_ancestor = sync;
let sync = data.sync_ancestor || data.sync_requested;
update_children_attach(child, sync, depth + 1);
}
}
}
Ok(())
}
impl WlSubsurface {
pub fn new(id: ObjectId, surface: &Rc<WlSurface>) -> Self {
pub fn new(id: ObjectId, surface: &Rc<WlSurface>, parent: &Rc<WlSurface>) -> Self {
Self {
id,
surface: surface.clone(),
parent: parent.clone(),
}
}
pub fn install(self: &Rc<Self>, parent: &Rc<WlSurface>) -> Result<(), WlSubsurfaceError> {
let old_ty = self.surface.ty.get();
if !matches!(old_ty, SurfaceType::None | SurfaceType::Subsurface) {
return Err(WlSubsurfaceError::IncompatibleType(self.surface.id, old_ty));
}
self.surface.ty.set(SurfaceType::Subsurface);
let mut data = self.surface.subsurface_data.borrow_mut();
if data.is_some() {
return Err(WlSubsurfaceError::AlreadyAttached(self.surface.id));
}
if self.surface.id == parent.id {
pub fn install(self: &Rc<Self>) -> Result<(), WlSubsurfaceError> {
if self.surface.id == self.parent.id {
return Err(WlSubsurfaceError::OwnParent(self.surface.id));
}
if self.surface.id == parent.get_root().id {
return Err(WlSubsurfaceError::Ancestor(self.surface.id, parent.id));
let old_ty = self.surface.role.get();
if !matches!(old_ty, SurfaceRole::None | SurfaceRole::Subsurface) {
return Err(WlSubsurfaceError::IncompatibleType(self.surface.id, old_ty));
}
self.surface.role.set(SurfaceRole::Subsurface);
let mut data = self.surface.role_data.borrow_mut();
if matches!(*data, RoleData::Subsurface(_)) {
return Err(WlSubsurfaceError::AlreadyAttached(self.surface.id));
}
if self.surface.id == self.parent.get_root().id {
return Err(WlSubsurfaceError::Ancestor(self.surface.id, self.parent.id));
}
let mut sync_ancestor = false;
let mut depth = 1;
{
let data = parent.subsurface_data.borrow();
if let Some(data) = data.as_ref() {
let data = self.parent.role_data.borrow();
if let RoleData::Subsurface(data) = &*data {
sync_ancestor = data.sync_requested || data.sync_ancestor;
depth = data.depth + 1;
if depth >= MAX_SUBSURFACE_DEPTH {
return Err(WlSubsurfaceError::MaxDepthExceeded);
}
}
}
*data = Some(Box::new(SubsurfaceData {
let node = {
let mut data = self.parent.children.borrow_mut();
let data = data.get_or_insert_with(|| Default::default());
data.subsurfaces
.insert(self.surface.id, self.surface.clone());
data.above.prepend(StackElement {
pending: Cell::new(true),
surface: self.surface.clone(),
})
};
*data = RoleData::Subsurface(Box::new(SubsurfaceData {
subsurface: self.clone(),
parent: parent.clone(),
x: 0,
y: 0,
sync_requested: false,
sync_ancestor,
pending: true,
depth,
node,
pending: Default::default(),
}));
{
let mut data = parent.children.borrow_mut();
let data = data.get_or_insert_with(|| Default::default());
data.pending_subsurfaces
.insert(self.surface.id, self.surface.clone());
}
update_children_attach(&self.surface, sync_ancestor, depth)?;
Ok(())
}
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.surface.client.parse(self, parser)?;
*self.surface.role_data.borrow_mut() = RoleData::None;
{
let mut children = self.parent.children.borrow_mut();
if let Some(children) = &mut *children {
children.subsurfaces.remove(&self.surface.id);
}
}
self.surface.client.remove_obj(self).await?;
Ok(())
}
async fn set_position(&self, parser: MsgParser<'_, '_>) -> Result<(), SetPositionError> {
let req: SetPosition = self.surface.client.parse(self, parser)?;
let mut data = self.surface.role_data.borrow_mut();
if let RoleData::Subsurface(data) = &mut *data {
data.pending.position = Some((req.x, req.y));
}
Ok(())
}
fn place(&self, sibling: ObjectId, above: bool) -> Result<(), PlacementError> {
if sibling == self.surface.id {
return Err(PlacementError::AboveSelf(sibling));
}
let mut data = self.surface.role_data.borrow_mut();
let pdata = self.parent.children.borrow();
if let (RoleData::Subsurface(data), Some(pdata)) = (&mut *data, &*pdata) {
let element = StackElement {
pending: Cell::new(true),
surface: self.surface.clone(),
};
if sibling == self.parent.id {
let node = match above {
true => pdata.above.prepend(element),
_ => pdata.below.append(element),
};
data.pending.node = Some(node);
} else {
let sibling = match pdata.subsurfaces.get(&sibling) {
Some(s) => s,
_ => return Err(PlacementError::NotASibling(sibling, self.surface.id)),
};
let sdata = sibling.role_data.borrow();
if let RoleData::Subsurface(p) = &*sdata {
let node = match &p.pending.node {
Some(n) => n,
_ => &p.node,
};
let node = match above {
true => node.append(element),
_ => node.prepend(element),
};
data.pending.node = Some(node);
}
}
}
Ok(())
}
async fn place_above(&self, parser: MsgParser<'_, '_>) -> Result<(), PlaceAboveError> {
let req: PlaceAbove = self.surface.client.parse(self, parser)?;
self.place(req.sibling, true)?;
Ok(())
}
async fn place_below(&self, parser: MsgParser<'_, '_>) -> Result<(), PlaceBelowError> {
let req: PlaceBelow = self.surface.client.parse(self, parser)?;
self.place(req.sibling, false)?;
Ok(())
}
fn update_sync(&self, sync: bool) {
let mut data = self.surface.role_data.borrow_mut();
if let RoleData::Subsurface(data) = &mut *data {
let was_sync = data.sync_requested || data.sync_ancestor;
data.sync_requested = sync;
let is_sync = data.sync_requested || data.sync_ancestor;
if was_sync != is_sync {
update_children_sync(&self.surface, is_sync);
}
}
}
async fn set_sync(&self, parser: MsgParser<'_, '_>) -> Result<(), SetSyncError> {
let _req: SetSync = self.surface.client.parse(self, parser)?;
self.update_sync(true);
Ok(())
}
async fn set_desync(&self, parser: MsgParser<'_, '_>) -> Result<(), SetDesyncError> {
let _req: SetDesync = self.surface.client.parse(self, parser)?;
self.update_sync(false);
Ok(())
}

View file

@ -1,5 +1,5 @@
use crate::client::{RequestParser};
use crate::ifs::wl_surface::SurfaceType;
use crate::client::{ClientError, RequestParser};
use crate::ifs::wl_surface::SurfaceRole;
use crate::object::ObjectId;
use crate::utils::buffd::{MsgParser, MsgParserError};
use std::fmt::{Debug, Formatter};
@ -20,21 +20,26 @@ pub enum WlSubsurfaceError {
#[error("Could not process `set_desync` request")]
SetDesync(#[from] SetDesyncError),
#[error("Surface {0} cannot be assigned the role `Subsurface` because it already has the role `{1:?}`")]
IncompatibleType(ObjectId, SurfaceType),
IncompatibleType(ObjectId, SurfaceRole),
#[error("Surface {0} already has an attached `wl_subsurface`")]
AlreadyAttached(ObjectId),
#[error("Surface {0} cannot be made its own parent")]
OwnParent(ObjectId),
#[error("Surface {0} cannot be made a subsurface of {1} because it's an ancestor of {1}")]
Ancestor(ObjectId, ObjectId),
#[error("Subsurfaces cannot be nested deeper than 100 levels")]
MaxDepthExceeded,
}
#[derive(Debug, Error)]
pub enum DestroyError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(DestroyError, ParseFailed, MsgParserError);
efrom!(DestroyError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum SetPositionError {
@ -47,13 +52,25 @@ efrom!(SetPositionError, ParseFailed, MsgParserError);
pub enum PlaceAboveError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
PlacementError(#[from] PlacementError),
}
efrom!(PlaceAboveError, ParseFailed, MsgParserError);
#[derive(Debug, Error)]
pub enum PlacementError {
#[error("Cannot place {0} above/below itself")]
AboveSelf(ObjectId),
#[error("{0} is not a sibling of {1}")]
NotASibling(ObjectId, ObjectId),
}
#[derive(Debug, Error)]
pub enum PlaceBelowError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
PlacementError(#[from] PlacementError),
}
efrom!(PlaceBelowError, ParseFailed, MsgParserError);

View file

@ -0,0 +1,119 @@
mod types;
pub mod xdg_popup;
pub mod xdg_toplevel;
use crate::ifs::wl_surface::{RoleData, SurfaceRole, WlSurface, XdgSurfaceData};
use crate::object::{Interface, Object, ObjectId};
use crate::utils::buffd::MsgParser;
use std::rc::Rc;
pub use types::*;
use crate::client::AddObj;
use crate::ifs::xdg_wm_base::XdgWmBaseObj;
const DESTROY: u32 = 0;
const GET_TOPLEVEL: u32 = 1;
const GET_POPUP: u32 = 2;
const SET_WINDOW_GEOMETRY: u32 = 3;
const ACK_CONFIGURE: u32 = 4;
const CONFIGURE: u32 = 0;
const NOT_CONSTRUCTED: u32 = 1;
const ALREADY_CONSTRUCTED: u32 = 2;
const UNCONFIGURED_BUFFER: u32 = 3;
pub struct XdgSurface {
id: ObjectId,
wm_base: Rc<XdgWmBaseObj>,
surface: Rc<WlSurface>,
version: u32,
}
impl XdgSurface {
pub fn new(wm_base: &Rc<XdgWmBaseObj>, id: ObjectId, surface: &Rc<WlSurface>, version: u32) -> Self {
Self {
id,
wm_base: wm_base.clone(),
surface: surface.clone(),
version,
}
}
pub fn install(self: &Rc<Self>) -> Result<(), XdgSurfaceError> {
let old_role = self.surface.role.get();
if !matches!(old_role, SurfaceRole::None | SurfaceRole::XdgSurface) {
return Err(XdgSurfaceError::IncompatibleRole(self.surface.id, old_role));
}
let mut data = self.surface.role_data.borrow_mut();
if data.is_some() {
return Err(XdgSurfaceError::AlreadyAttached(self.surface.id));
}
*data = RoleData::XdgSurface(Box::new(XdgSurfaceData {
xdg_surface: self.clone(),
}));
Ok(())
}
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.surface.client.parse(self, parser)?;
*self.surface.role_data.borrow_mut() = RoleData::None;
self.wm_base.surfaces.remove(&self.id);
self.surface.client.remove_obj(self).await?;
Ok(())
}
async fn get_toplevel(&self, parser: MsgParser<'_, '_>) -> Result<(), GetToplevelError> {
let _req: GetToplevel = self.surface.client.parse(self, parser)?;
Ok(())
}
async fn get_popup(&self, parser: MsgParser<'_, '_>) -> Result<(), GetPopupError> {
let _req: GetPopup = self.surface.client.parse(self, parser)?;
Ok(())
}
async fn set_window_geometry(
&self,
parser: MsgParser<'_, '_>,
) -> Result<(), SetWindowGeometryError> {
let _req: SetWindowGeometry = self.surface.client.parse(self, parser)?;
Ok(())
}
async fn ack_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), AckConfigureError> {
let _req: AckConfigure = self.surface.client.parse(self, parser)?;
Ok(())
}
async fn handle_request_(
&self,
request: u32,
parser: MsgParser<'_, '_>,
) -> Result<(), XdgSurfaceError> {
match request {
DESTROY => self.destroy(parser).await?,
GET_TOPLEVEL => self.get_toplevel(parser).await?,
GET_POPUP => self.get_popup(parser).await?,
SET_WINDOW_GEOMETRY => self.set_window_geometry(parser).await?,
ACK_CONFIGURE => self.ack_configure(parser).await?,
_ => unreachable!(),
}
Ok(())
}
}
handle_request!(XdgSurface);
impl Object for XdgSurface {
fn id(&self) -> ObjectId {
self.id
}
fn interface(&self) -> Interface {
Interface::XdgSurface
}
fn num_requests(&self) -> u32 {
ACK_CONFIGURE + 1
}
}

View file

@ -0,0 +1,189 @@
use crate::client::{ClientError, EventFormatter, RequestParser};
use crate::ifs::wl_surface::xdg_surface::{XdgSurface, CONFIGURE};
use crate::object::{Object, ObjectId};
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
use std::fmt::{Debug, Formatter};
use std::rc::Rc;
use thiserror::Error;
use crate::ifs::wl_surface::SurfaceRole;
#[derive(Debug, Error)]
pub enum XdgSurfaceError {
#[error("Could not process `destroy` request")]
DestroyError(#[from] DestroyError),
#[error("Could not process `get_toplevel` request")]
GetToplevelError(#[from] GetToplevelError),
#[error("Could not process `get_popup` request")]
GetPopupError(#[from] GetPopupError),
#[error("Could not process `set_window_geometry` request")]
SetWindowGeometryError(#[from] SetWindowGeometryError),
#[error("Could not process `ack_configure` request")]
AckConfigureError(#[from] AckConfigureError),
#[error("Surface {0} cannot be turned into a xdg_surface because it already has the role {}", .1.name())]
IncompatibleRole(ObjectId, SurfaceRole),
#[error("Surface {0} cannot be turned into a xdg_surface because it already has an attached xdg_surface")]
AlreadyAttached(ObjectId),
}
#[derive(Debug, Error)]
pub enum DestroyError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(DestroyError, ParseFailed, MsgParserError);
efrom!(DestroyError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum GetToplevelError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(GetToplevelError, ParseFailed, MsgParserError);
efrom!(GetToplevelError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum GetPopupError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(GetPopupError, ParseFailed, MsgParserError);
efrom!(GetPopupError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum SetWindowGeometryError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(SetWindowGeometryError, ParseFailed, MsgParserError);
efrom!(SetWindowGeometryError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum AckConfigureError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(AckConfigureError, ParseFailed, MsgParserError);
efrom!(AckConfigureError, ClientError, ClientError);
pub(super) struct Destroy;
impl RequestParser<'_> for Destroy {
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self)
}
}
impl Debug for Destroy {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "destroy()")
}
}
pub(super) struct GetToplevel {
pub id: ObjectId,
}
impl RequestParser<'_> for GetToplevel {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
id: parser.object()?,
})
}
}
impl Debug for GetToplevel {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "get_toplevel(id: {})", self.id)
}
}
pub(super) struct GetPopup {
pub id: ObjectId,
pub parent: ObjectId,
pub positioner: ObjectId,
}
impl RequestParser<'_> for GetPopup {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
id: parser.object()?,
parent: parser.object()?,
positioner: parser.object()?,
})
}
}
impl Debug for GetPopup {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"get_popup(id: {}, parent: {}, positioner: {})",
self.id, self.parent, self.positioner
)
}
}
pub(super) struct SetWindowGeometry {
pub x: i32,
pub y: i32,
pub width: i32,
pub height: i32,
}
impl RequestParser<'_> for SetWindowGeometry {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
x: parser.int()?,
y: parser.int()?,
width: parser.int()?,
height: parser.int()?,
})
}
}
impl Debug for SetWindowGeometry {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"set_window_geometry(x: {}, y: {}, width: {}, height: {})",
self.x, self.y, self.width, self.height
)
}
}
pub(super) struct AckConfigure {
pub serial: u32,
}
impl RequestParser<'_> for AckConfigure {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
serial: parser.uint()?,
})
}
}
impl Debug for AckConfigure {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "ack_configure(serial: {})", self.serial)
}
}
pub(super) struct Configure {
pub obj: Rc<XdgSurface>,
pub serial: u32,
}
impl EventFormatter for Configure {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, CONFIGURE).uint(self.serial);
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Configure {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "configure(serial: {})", self.serial)
}
}

View file

@ -0,0 +1,78 @@
mod types;
use crate::ifs::wl_surface::xdg_surface::XdgSurface;
use crate::object::{Interface, Object, ObjectId};
use crate::utils::buffd::MsgParser;
use std::rc::Rc;
pub use types::*;
const DESTROY: u32 = 0;
const GRAB: u32 = 1;
const REPOSITION: u32 = 2;
const CONFIGURE: u32 = 0;
const POPUP_DONE: u32 = 1;
const REPOSITIONED: u32 = 2;
const INVALID_GRAB: u32 = 1;
pub struct XdgPopup {
id: ObjectId,
surface: Rc<XdgSurface>,
version: u32,
}
impl XdgPopup {
pub fn new(id: ObjectId, surface: &Rc<XdgSurface>, version: u32) -> Self {
Self {
id,
surface: surface.clone(),
version,
}
}
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn grab(&self, parser: MsgParser<'_, '_>) -> Result<(), GrabError> {
let _req: Grab = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn reposition(&self, parser: MsgParser<'_, '_>) -> Result<(), RepositionError> {
let _req: Reposition = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn handle_request_(
&self,
request: u32,
parser: MsgParser<'_, '_>,
) -> Result<(), XdgPopupError> {
match request {
DESTROY => self.destroy(parser).await?,
GRAB => self.grab(parser).await?,
REPOSITION => self.reposition(parser).await?,
_ => unreachable!(),
}
Ok(())
}
}
handle_request!(XdgPopup);
impl Object for XdgPopup {
fn id(&self) -> ObjectId {
self.id
}
fn interface(&self) -> Interface {
Interface::XdgPopup
}
fn num_requests(&self) -> u32 {
REPOSITION + 1
}
}

View file

@ -0,0 +1,168 @@
use crate::client::{ClientError, EventFormatter, RequestParser};
use crate::ifs::wl_surface::xdg_surface::xdg_popup::{
XdgPopup, CONFIGURE, POPUP_DONE, REPOSITIONED,
};
use crate::object::{Object, ObjectId};
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
use std::fmt::{Debug, Formatter};
use std::rc::Rc;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum XdgPopupError {
#[error("Could not process `destroy` request")]
DestroyError(#[from] DestroyError),
#[error("Could not process `grab` request")]
GrabError(#[from] GrabError),
#[error("Could not process `reposition` request")]
RepositionError(#[from] RepositionError),
}
#[derive(Debug, Error)]
pub enum DestroyError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(DestroyError, ParseFailed, MsgParserError);
efrom!(DestroyError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum GrabError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(GrabError, ParseFailed, MsgParserError);
efrom!(GrabError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum RepositionError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(RepositionError, ParseFailed, MsgParserError);
efrom!(RepositionError, ClientError, ClientError);
pub(super) struct Destroy;
impl RequestParser<'_> for Destroy {
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self)
}
}
impl Debug for Destroy {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "destroy()")
}
}
pub(super) struct Grab {
pub seat: ObjectId,
pub serial: u32,
}
impl RequestParser<'_> for Grab {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
seat: parser.object()?,
serial: parser.uint()?,
})
}
}
impl Debug for Grab {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "grab(seat: {}, serial: {})", self.seat, self.serial)
}
}
pub(super) struct Reposition {
pub positioner: ObjectId,
pub token: u32,
}
impl RequestParser<'_> for Reposition {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
positioner: parser.object()?,
token: parser.uint()?,
})
}
}
impl Debug for Reposition {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"reposition(positioner: {}, token: {})",
self.positioner, self.token,
)
}
}
pub(super) struct Configure {
pub obj: Rc<XdgPopup>,
pub x: i32,
pub y: i32,
pub width: i32,
pub height: i32,
}
impl EventFormatter for Configure {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, CONFIGURE)
.int(self.x)
.int(self.y)
.int(self.width)
.int(self.height);
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Configure {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"configure(x: {}, y: {}, width: {}, height: {})",
self.x, self.y, self.width, self.height
)
}
}
pub(super) struct PopupDone {
pub obj: Rc<XdgPopup>,
}
impl EventFormatter for PopupDone {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, POPUP_DONE);
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for PopupDone {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "popup_done()")
}
}
pub(super) struct Repositioned {
pub obj: Rc<XdgPopup>,
pub token: u32,
}
impl EventFormatter for Repositioned {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, REPOSITIONED).uint(self.token);
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Repositioned {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "repositioned(token: {})", self.token)
}
}

View file

@ -0,0 +1,178 @@
mod types;
use crate::ifs::wl_surface::xdg_surface::XdgSurface;
use crate::object::{Interface, Object, ObjectId};
use crate::utils::buffd::MsgParser;
use num_derive::FromPrimitive;
use std::rc::Rc;
pub use types::*;
const DESTROY: u32 = 0;
const SET_PARENT: u32 = 1;
const SET_TITLE: u32 = 2;
const SET_APP_ID: u32 = 3;
const SHOW_WINDOW_MENU: u32 = 4;
const MOVE: u32 = 5;
const RESIZE: u32 = 6;
const SET_MAX_SIZE: u32 = 7;
const SET_MIN_SIZE: u32 = 8;
const SET_MAXIMIZED: u32 = 9;
const UNSET_MAXIMIZED: u32 = 10;
const SET_FULLSCREEN: u32 = 11;
const UNSET_FULLSCREEN: u32 = 12;
const SET_MINIMIZED: u32 = 13;
const CONFIGURE: u32 = 0;
const CLOSE: u32 = 1;
#[derive(Copy, Clone, Debug, FromPrimitive)]
pub enum ResizeEdge {
None = 0,
Top = 1,
Bottom = 2,
Left = 4,
TopLeft = 5,
BottomLeft = 6,
Right = 8,
TopRight = 9,
BottomRight = 10,
}
const STATE_MAXIMIZED: u32 = 1;
const STATE_FULLSCREEN: u32 = 2;
const STATE_RESIZING: u32 = 3;
const STATE_ACTIVATED: u32 = 4;
const STATE_TILED_LEFT: u32 = 5;
const STATE_TILED_RIGHT: u32 = 6;
const STATE_TILED_TOP: u32 = 7;
const STATE_TILED_BOTTOM: u32 = 8;
pub struct XdgToplevel {
id: ObjectId,
surface: Rc<XdgSurface>,
version: u32,
}
impl XdgToplevel {
pub fn new(id: ObjectId, surface: &Rc<XdgSurface>, version: u32) -> Self {
Self {
id,
surface: surface.clone(),
version,
}
}
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn set_parent(&self, parser: MsgParser<'_, '_>) -> Result<(), SetParentError> {
let _req: SetParent = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn set_title(&self, parser: MsgParser<'_, '_>) -> Result<(), SetTitleError> {
let _req: SetTitle = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn set_app_id(&self, parser: MsgParser<'_, '_>) -> Result<(), SetAppIdError> {
let _req: SetAppId = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn show_window_menu(&self, parser: MsgParser<'_, '_>) -> Result<(), ShowWindowMenuError> {
let _req: ShowWindowMenu = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn move_(&self, parser: MsgParser<'_, '_>) -> Result<(), MoveError> {
let _req: Move = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn resize(&self, parser: MsgParser<'_, '_>) -> Result<(), ResizeError> {
let _req: Resize = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn set_max_size(&self, parser: MsgParser<'_, '_>) -> Result<(), SetMaxSizeError> {
let _req: SetMaxSize = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn set_min_size(&self, parser: MsgParser<'_, '_>) -> Result<(), SetMinSizeError> {
let _req: SetMinSize = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn set_maximized(&self, parser: MsgParser<'_, '_>) -> Result<(), SetMaximizedError> {
let _req: SetMaximized = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn unset_maximized(&self, parser: MsgParser<'_, '_>) -> Result<(), UnsetMaximizedError> {
let _req: UnsetMaximized = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn set_fullscreen(&self, parser: MsgParser<'_, '_>) -> Result<(), SetFullscreenError> {
let _req: SetFullscreen = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn unset_fullscreen(
&self,
parser: MsgParser<'_, '_>,
) -> Result<(), UnsetFullscreenError> {
let _req: UnsetFullscreen = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn set_minimized(&self, parser: MsgParser<'_, '_>) -> Result<(), SetMinimizedError> {
let _req: SetMinimized = self.surface.surface.client.parse(self, parser)?;
Ok(())
}
async fn handle_request_(
&self,
request: u32,
parser: MsgParser<'_, '_>,
) -> Result<(), XdgToplevelError> {
match request {
DESTROY => self.destroy(parser).await?,
SET_PARENT => self.set_parent(parser).await?,
SET_TITLE => self.set_title(parser).await?,
SET_APP_ID => self.set_app_id(parser).await?,
SHOW_WINDOW_MENU => self.show_window_menu(parser).await?,
MOVE => self.move_(parser).await?,
RESIZE => self.resize(parser).await?,
SET_MAX_SIZE => self.set_max_size(parser).await?,
SET_MIN_SIZE => self.set_min_size(parser).await?,
SET_MAXIMIZED => self.set_maximized(parser).await?,
UNSET_MAXIMIZED => self.unset_maximized(parser).await?,
SET_FULLSCREEN => self.set_fullscreen(parser).await?,
UNSET_FULLSCREEN => self.unset_fullscreen(parser).await?,
SET_MINIMIZED => self.set_minimized(parser).await?,
_ => unreachable!(),
}
Ok(())
}
}
handle_request!(XdgToplevel);
impl Object for XdgToplevel {
fn id(&self) -> ObjectId {
self.id
}
fn interface(&self) -> Interface {
Interface::XdgToplevel
}
fn num_requests(&self) -> u32 {
SET_MINIMIZED + 1
}
}

View file

@ -0,0 +1,433 @@
use super::CONFIGURE;
use crate::client::{ClientError, EventFormatter, RequestParser};
use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::{XdgToplevel, CLOSE};
use crate::object::{Object, ObjectId};
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
use std::fmt::{Debug, Formatter};
use std::rc::Rc;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum XdgToplevelError {
#[error("Could not process `destroy` request")]
DestroyError(#[from] DestroyError),
#[error("Could not process `set_parent` request")]
SetParentError(#[from] SetParentError),
#[error("Could not process `set_title` request")]
SetTitleError(#[from] SetTitleError),
#[error("Could not process `set_app_id` request")]
SetAppIdError(#[from] SetAppIdError),
#[error("Could not process `show_window_menu` request")]
ShowWindowMenuError(#[from] ShowWindowMenuError),
#[error("Could not process `move` request")]
MoveError(#[from] MoveError),
#[error("Could not process `resize` request")]
ResizeError(#[from] ResizeError),
#[error("Could not process `set_max_size` request")]
SetMaxSizeError(#[from] SetMaxSizeError),
#[error("Could not process `set_min_size` request")]
SetMinSizeError(#[from] SetMinSizeError),
#[error("Could not process `set_maximized` request")]
SetMaximizedError(#[from] SetMaximizedError),
#[error("Could not process `unset_maximized` request")]
UnsetMaximizedError(#[from] UnsetMaximizedError),
#[error("Could not process `set_fullscreen` request")]
SetFullscreenError(#[from] SetFullscreenError),
#[error("Could not process `unset_fullscreen` request")]
UnsetFullscreenError(#[from] UnsetFullscreenError),
#[error("Could not process `set_minimized` request")]
SetMinimizedError(#[from] SetMinimizedError),
}
#[derive(Debug, Error)]
pub enum DestroyError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(DestroyError, ParseFailed, MsgParserError);
efrom!(DestroyError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum SetParentError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(SetParentError, ParseFailed, MsgParserError);
efrom!(SetParentError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum SetTitleError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(SetTitleError, ParseFailed, MsgParserError);
efrom!(SetTitleError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum SetAppIdError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(SetAppIdError, ParseFailed, MsgParserError);
efrom!(SetAppIdError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum ShowWindowMenuError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(ShowWindowMenuError, ParseFailed, MsgParserError);
efrom!(ShowWindowMenuError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum MoveError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(MoveError, ParseFailed, MsgParserError);
efrom!(MoveError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum ResizeError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(ResizeError, ParseFailed, MsgParserError);
efrom!(ResizeError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum SetMaxSizeError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(SetMaxSizeError, ParseFailed, MsgParserError);
efrom!(SetMaxSizeError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum SetMinSizeError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(SetMinSizeError, ParseFailed, MsgParserError);
efrom!(SetMinSizeError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum SetMaximizedError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(SetMaximizedError, ParseFailed, MsgParserError);
efrom!(SetMaximizedError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum UnsetMaximizedError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(UnsetMaximizedError, ParseFailed, MsgParserError);
efrom!(UnsetMaximizedError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum SetFullscreenError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(SetFullscreenError, ParseFailed, MsgParserError);
efrom!(SetFullscreenError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum UnsetFullscreenError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(UnsetFullscreenError, ParseFailed, MsgParserError);
efrom!(UnsetFullscreenError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum SetMinimizedError {
#[error("Parsing failed")]
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(SetMinimizedError, ParseFailed, MsgParserError);
efrom!(SetMinimizedError, ClientError, ClientError);
pub(super) struct Destroy;
impl RequestParser<'_> for Destroy {
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self)
}
}
impl Debug for Destroy {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "destroy()")
}
}
pub(super) struct SetParent {
pub parent: ObjectId,
}
impl RequestParser<'_> for SetParent {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self { parent: parser.object()? })
}
}
impl Debug for SetParent {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "set_parent(parent: {})", self.parent)
}
}
pub(super) struct SetTitle<'a> {
pub title: &'a str,
}
impl<'a> RequestParser<'a> for SetTitle<'a> {
fn parse(parser: &mut MsgParser<'_, 'a>) -> Result<Self, MsgParserError> {
Ok(Self { title: parser.string()? })
}
}
impl<'a> Debug for SetTitle<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "set_title(title: {:?})", self.title)
}
}
pub(super) struct SetAppId<'a> {
pub app_id: &'a str,
}
impl<'a> RequestParser<'a> for SetAppId<'a> {
fn parse(parser: &mut MsgParser<'_, 'a>) -> Result<Self, MsgParserError> {
Ok(Self { app_id: parser.string()? })
}
}
impl<'a> Debug for SetAppId<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "set_app_id(app_id: {:?})", self.app_id)
}
}
pub(super) struct ShowWindowMenu {
pub seat: ObjectId,
pub serial: u32,
pub x: i32,
pub y: i32,
}
impl RequestParser<'_> for ShowWindowMenu {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
seat: parser.object()?,
serial: parser.uint()?,
x: parser.int()?,
y: parser.int()?,
})
}
}
impl Debug for ShowWindowMenu {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "show_window_menu(seat: {}, serial: {}, x: {}, y: {})", self.seat, self.serial, self.x, self.y)
}
}
pub(super) struct Move {
pub seat: ObjectId,
pub serial: u32,
}
impl RequestParser<'_> for Move {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self { seat: parser.object()?, serial: parser.uint()? })
}
}
impl Debug for Move {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "move(seat: {}, serial: {})", self.seat, self.serial)
}
}
pub(super) struct Resize {
pub seat: ObjectId,
pub serial: u32,
pub edges: u32,
}
impl RequestParser<'_> for Resize {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
seat: parser.object()?,
serial: parser.uint()?,
edges: parser.uint()?,
})
}
}
impl Debug for Resize {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "resize(seat: {}, serial: {}, edges: {})", self.seat, self.serial, self.edges)
}
}
pub(super) struct SetMaxSize {
pub width: i32,
pub height: i32,
}
impl RequestParser<'_> for SetMaxSize {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self { width: parser.int()?, height: parser.int()? })
}
}
impl Debug for SetMaxSize {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "set_max_size(width: {}, height: {})", self.width, self.height)
}
}
pub(super) struct SetMinSize {
pub width: i32,
pub height: i32,
}
impl RequestParser<'_> for SetMinSize {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self { width: parser.int()?, height: parser.int()? })
}
}
impl Debug for SetMinSize {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "set_min_size(width: {}, height: {})", self.width, self.height)
}
}
pub(super) struct SetMaximized;
impl RequestParser<'_> for SetMaximized {
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self)
}
}
impl Debug for SetMaximized {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "set_maximized()")
}
}
pub(super) struct UnsetMaximized;
impl RequestParser<'_> for UnsetMaximized {
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self)
}
}
impl Debug for UnsetMaximized {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "unset_maximized()")
}
}
pub(super) struct SetFullscreen {
pub output: ObjectId,
}
impl RequestParser<'_> for SetFullscreen {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self { output: parser.object()? })
}
}
impl Debug for SetFullscreen {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "set_fullscreen(output: {})", self.output)
}
}
pub(super) struct UnsetFullscreen;
impl RequestParser<'_> for UnsetFullscreen {
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self)
}
}
impl Debug for UnsetFullscreen {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "unset_fullscreen()")
}
}
pub(super) struct SetMinimized;
impl RequestParser<'_> for SetMinimized {
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self)
}
}
impl Debug for SetMinimized {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "set_minimized()")
}
}
pub(super) struct Configure {
pub obj: Rc<XdgToplevel>,
pub width: i32,
pub height: i32,
pub states: Vec<u32>,
}
impl EventFormatter for Configure {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, CONFIGURE)
.int(self.width)
.int(self.height)
.array(|fmt| {
for &state in &self.states {
fmt.uint(state);
}
});
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Configure {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"configure(width: {}, height: {}, states: {:?})",
self.width, self.height, self.states
)
}
}
pub(super) struct Close {
pub obj: Rc<XdgToplevel>,
}
impl EventFormatter for Close {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, CLOSE);
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Close {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "close()")
}
}

View file

@ -0,0 +1,269 @@
mod types;
use crate::client::{AddObj, Client};
use crate::object::{Interface, Object, ObjectId};
use crate::utils::buffd::MsgParser;
use bitflags::bitflags;
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
use std::cell::RefCell;
use std::rc::Rc;
pub use types::*;
const DESTROY: u32 = 0;
const SET_SIZE: u32 = 1;
const SET_ANCHOR_RECT: u32 = 2;
const SET_ANCHOR: u32 = 3;
const SET_GRAVITY: u32 = 4;
const SET_CONSTRAINT_ADJUSTMENT: u32 = 5;
const SET_OFFSET: u32 = 6;
const SET_REACTIVE: u32 = 7;
const SET_PARENT_SIZE: u32 = 8;
const SET_PARENT_CONFIGURE: u32 = 9;
const INVALID_INPUT: u32 = 0;
#[derive(Debug, Eq, PartialEq, Copy, Clone, FromPrimitive)]
pub enum Anchor {
None = 0,
Top = 1,
Bottom = 2,
Left = 3,
Right = 4,
TopLeft = 5,
BottomLeft = 6,
TopRight = 7,
BottomRight = 8,
}
impl Default for Anchor {
fn default() -> Self {
Self::None
}
}
#[derive(Debug, Eq, PartialEq, Copy, Clone, FromPrimitive)]
pub enum Gravity {
None = 0,
Top = 1,
Bottom = 2,
Left = 3,
Right = 4,
TopLeft = 5,
BottomLeft = 6,
TopRight = 7,
BottomRight = 8,
}
impl Default for Gravity {
fn default() -> Self {
Self::None
}
}
bitflags! {
#[derive(Default)]
pub struct CA: u32 {
const NONE = 0;
const SLIDE_X = 1;
const SLIDE_Y = 2;
const FLIP_X = 4;
const FLIP_Y = 8;
const RESIZE_X = 16;
const RESIZE_Y = 32;
}
}
pub struct XdgPositioner {
id: ObjectId,
client: Rc<Client>,
version: u32,
position: RefCell<XdgPositioned>,
}
#[derive(Copy, Clone, Debug, Default)]
pub struct XdgPositioned {
pub size_width: u32,
pub size_height: u32,
pub ar_x: i32,
pub ar_y: i32,
pub ar_width: u32,
pub ar_height: u32,
pub anchor: Anchor,
pub gravity: Gravity,
pub ca: CA,
pub off_x: i32,
pub off_y: i32,
pub reactive: bool,
pub parent_width: u32,
pub parent_height: u32,
pub parent_serial: u32,
}
impl XdgPositioner {
pub fn new(id: ObjectId, client: &Rc<Client>, version: u32) -> Self {
Self {
id,
client: client.clone(),
version,
position: RefCell::new(Default::default()),
}
}
pub fn clone(&self) -> Box<XdgPositioned> {
Box::new(*self.position.borrow())
}
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.client.parse(self, parser)?;
self.client.remove_obj(self).await?;
Ok(())
}
async fn set_size(&self, parser: MsgParser<'_, '_>) -> Result<(), SetSizeError> {
let req: SetSize = self.client.parse(self, parser)?;
if req.width <= 0 || req.height <= 0 {
self.client.protocol_error(
self,
INVALID_INPUT,
format!("Cannot set a non-positive size"),
);
return Err(SetSizeError::NonPositiveSize);
}
let mut position = self.position.borrow_mut();
position.size_width = req.width as u32;
position.size_height = req.height as u32;
Ok(())
}
async fn set_anchor_rect(&self, parser: MsgParser<'_, '_>) -> Result<(), SetAnchorRectError> {
let req: SetAnchorRect = self.client.parse(self, parser)?;
if req.width < 0 || req.height < 0 {
self.client.protocol_error(
self,
INVALID_INPUT,
format!("Cannot set an anchor rect with negative size"),
);
return Err(SetAnchorRectError::NegativeAnchorRect);
}
let mut position = self.position.borrow_mut();
position.ar_x = req.x;
position.ar_y = req.y;
position.ar_width = req.width as u32;
position.ar_height = req.height as u32;
Ok(())
}
async fn set_anchor(&self, parser: MsgParser<'_, '_>) -> Result<(), SetAnchorError> {
let req: SetAnchor = self.client.parse(self, parser)?;
let anchor = match Anchor::from_u32(req.anchor) {
Some(a) => a,
_ => return Err(SetAnchorError::UnknownAnchor(req.anchor)),
};
self.position.borrow_mut().anchor = anchor;
Ok(())
}
async fn set_gravity(&self, parser: MsgParser<'_, '_>) -> Result<(), SetGravityError> {
let req: SetGravity = self.client.parse(self, parser)?;
let gravity = match Gravity::from_u32(req.gravity) {
Some(a) => a,
_ => return Err(SetGravityError::UnknownGravity(req.gravity)),
};
self.position.borrow_mut().gravity = gravity;
Ok(())
}
async fn set_constraint_adjustment(
&self,
parser: MsgParser<'_, '_>,
) -> Result<(), SetConstraintAdjustmentError> {
let req: SetConstraintAdjustment = self.client.parse(self, parser)?;
let ca = match CA::from_bits(req.constraint_adjustment) {
Some(c) => c,
_ => {
return Err(SetConstraintAdjustmentError::UnknownCa(
req.constraint_adjustment,
))
}
};
self.position.borrow_mut().ca = ca;
Ok(())
}
async fn set_offset(&self, parser: MsgParser<'_, '_>) -> Result<(), SetOffsetError> {
let req: SetOffset = self.client.parse(self, parser)?;
let mut position = self.position.borrow_mut();
position.off_x = req.x;
position.off_y = req.y;
Ok(())
}
async fn set_reactive(&self, parser: MsgParser<'_, '_>) -> Result<(), SetReactiveError> {
let _req: SetReactive = self.client.parse(self, parser)?;
self.position.borrow_mut().reactive = true;
Ok(())
}
async fn set_parent_size(&self, parser: MsgParser<'_, '_>) -> Result<(), SetParentSizeError> {
let req: SetParentSize = self.client.parse(self, parser)?;
if req.parent_width < 0 || req.parent_height < 0 {
self.client.protocol_error(
self,
INVALID_INPUT,
format!("Cannot set a negative parent size"),
);
return Err(SetParentSizeError::NegativeParentSize);
}
let mut position = self.position.borrow_mut();
position.parent_width = req.parent_width as u32;
position.parent_height = req.parent_height as u32;
Ok(())
}
async fn set_parent_configure(
&self,
parser: MsgParser<'_, '_>,
) -> Result<(), SetParentConfigureError> {
let req: SetParentConfigure = self.client.parse(self, parser)?;
self.position.borrow_mut().parent_serial = req.serial;
Ok(())
}
async fn handle_request_(
&self,
request: u32,
parser: MsgParser<'_, '_>,
) -> Result<(), XdgPositionerError> {
match request {
DESTROY => self.destroy(parser).await?,
SET_SIZE => self.set_size(parser).await?,
SET_ANCHOR_RECT => self.set_anchor_rect(parser).await?,
SET_ANCHOR => self.set_anchor(parser).await?,
SET_GRAVITY => self.set_gravity(parser).await?,
SET_CONSTRAINT_ADJUSTMENT => self.set_constraint_adjustment(parser).await?,
SET_OFFSET => self.set_offset(parser).await?,
SET_REACTIVE => self.set_reactive(parser).await?,
SET_PARENT_SIZE => self.set_parent_size(parser).await?,
SET_PARENT_CONFIGURE => self.set_parent_configure(parser).await?,
_ => unreachable!(),
}
Ok(())
}
}
handle_request!(XdgPositioner);
impl Object for XdgPositioner {
fn id(&self) -> ObjectId {
self.id
}
fn interface(&self) -> Interface {
Interface::XdgPositioner
}
fn num_requests(&self) -> u32 {
SET_PARENT_CONFIGURE + 1
}
}

View file

@ -0,0 +1,293 @@
use crate::client::{ClientError, RequestParser};
use crate::utils::buffd::{MsgParser, MsgParserError};
use std::fmt::{Debug, Formatter};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum XdgPositionerError {
#[error("Could not process a `destroy` request")]
DestroyError(#[from] DestroyError),
#[error("Could not process a `set_size` request")]
SetSizeError(#[from] SetSizeError),
#[error("Could not process a `set_anchor_rect` request")]
SetAnchorRectError(#[from] SetAnchorRectError),
#[error("Could not process a `set_anchor` request")]
SetAnchorError(#[from] SetAnchorError),
#[error("Could not process a `set_gravity` request")]
SetGravityError(#[from] SetGravityError),
#[error("Could not process a `set_constraint_adjustment` request")]
SetConstraintAdjustmentError(#[from] SetConstraintAdjustmentError),
#[error("Could not process a `set_offset` request")]
SetOffsetError(#[from] SetOffsetError),
#[error("Could not process a `set_reactive` request")]
SetReactiveError(#[from] SetReactiveError),
#[error("Could not process a `set_parent_size` request")]
SetParentSizeError(#[from] SetParentSizeError),
#[error("Could not process a `set_parent_configure` request")]
SetParentConfigureError(#[from] SetParentConfigureError),
}
#[derive(Debug, Error)]
pub enum DestroyError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(DestroyError, ParseError, MsgParserError);
efrom!(DestroyError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum SetSizeError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error("Cannot set a non-positive size")]
NonPositiveSize,
}
efrom!(SetSizeError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum SetAnchorRectError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error("Cannot set an anchor rect with a negative size")]
NegativeAnchorRect,
}
efrom!(SetAnchorRectError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum SetAnchorError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error("Unknown anchor {0}")]
UnknownAnchor(u32),
}
efrom!(SetAnchorError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum SetGravityError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error("Unknown gravity {0}")]
UnknownGravity(u32),
}
efrom!(SetGravityError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum SetConstraintAdjustmentError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error("Unknown constraint adjustment {0}")]
UnknownCa(u32),
}
efrom!(SetConstraintAdjustmentError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum SetOffsetError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
}
efrom!(SetOffsetError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum SetReactiveError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
}
efrom!(SetReactiveError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum SetParentSizeError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error("Cannot set a negative parent size")]
NegativeParentSize,
}
efrom!(SetParentSizeError, ParseError, MsgParserError);
#[derive(Debug, Error)]
pub enum SetParentConfigureError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
}
efrom!(SetParentConfigureError, ParseError, MsgParserError);
pub(super) struct Destroy;
impl RequestParser<'_> for Destroy {
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self)
}
}
impl Debug for Destroy {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "destroy()")
}
}
pub(super) struct SetSize {
pub width: i32,
pub height: i32,
}
impl RequestParser<'_> for SetSize {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
width: parser.int()?,
height: parser.int()?,
})
}
}
impl Debug for SetSize {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"set_size(width: {}, height: {})",
self.width, self.height
)
}
}
pub(super) struct SetAnchorRect {
pub x: i32,
pub y: i32,
pub width: i32,
pub height: i32,
}
impl RequestParser<'_> for SetAnchorRect {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
x: parser.int()?,
y: parser.int()?,
width: parser.int()?,
height: parser.int()?,
})
}
}
impl Debug for SetAnchorRect {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"set_anchor_rect(x: {}, y: {}, width: {}, height: {})",
self.x, self.y, self.width, self.height
)
}
}
pub(super) struct SetAnchor {
pub anchor: u32,
}
impl RequestParser<'_> for SetAnchor {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
anchor: parser.uint()?,
})
}
}
impl Debug for SetAnchor {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "set_anchor(anchor: {})", self.anchor)
}
}
pub(super) struct SetGravity {
pub gravity: u32,
}
impl RequestParser<'_> for SetGravity {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
gravity: parser.uint()?,
})
}
}
impl Debug for SetGravity {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "set_gravity(gravity: {})", self.gravity)
}
}
pub(super) struct SetConstraintAdjustment {
pub constraint_adjustment: u32,
}
impl RequestParser<'_> for SetConstraintAdjustment {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
constraint_adjustment: parser.uint()?,
})
}
}
impl Debug for SetConstraintAdjustment {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"set_constraint_adjustment(constraint_adjustment: {})",
self.constraint_adjustment
)
}
}
pub(super) struct SetOffset {
pub x: i32,
pub y: i32,
}
impl RequestParser<'_> for SetOffset {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
x: parser.int()?,
y: parser.int()?,
})
}
}
impl Debug for SetOffset {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "set_offset(x: {}, y: {})", self.x, self.y)
}
}
pub(super) struct SetReactive;
impl RequestParser<'_> for SetReactive {
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self)
}
}
impl Debug for SetReactive {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "set_reactive()")
}
}
pub(super) struct SetParentSize {
pub parent_width: i32,
pub parent_height: i32,
}
impl RequestParser<'_> for SetParentSize {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
parent_width: parser.int()?,
parent_height: parser.int()?,
})
}
}
impl Debug for SetParentSize {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"set_parent_size(parent_width: {}, parent_height: {})",
self.parent_width, self.parent_height
)
}
}
pub(super) struct SetParentConfigure {
pub serial: u32,
}
impl RequestParser<'_> for SetParentConfigure {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
serial: parser.uint()?,
})
}
}
impl Debug for SetParentConfigure {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "set_parent_configure(serial: {})", self.serial)
}
}

View file

@ -1,12 +1,29 @@
mod types;
use crate::client::{AddObj, Client, ClientError};
use crate::client::{AddObj, Client};
use crate::globals::{Global, GlobalName};
use crate::ifs::wl_surface::xdg_surface::XdgSurface;
use crate::ifs::xdg_positioner::XdgPositioner;
use crate::object::{Interface, Object, ObjectId};
use crate::utils::buffd::MsgParser;
use crate::utils::copyhashmap::CopyHashMap;
use std::rc::Rc;
pub use types::*;
const DESTROY: u32 = 0;
const CREATE_POSITIONER: u32 = 1;
const GET_XDG_SURFACE: u32 = 2;
const PONG: u32 = 3;
const PING: u32 = 0;
const ROLE: u32 = 0;
const DEFUNCT_SURFACES: u32 = 1;
const NOT_THE_TOPMOST_POPUP: u32 = 2;
const INVALID_POPUP_PARENT: u32 = 3;
const INVALID_SURFACE_STATE: u32 = 4;
const INVALID_POSITIONER: u32 = 5;
pub struct XdgWmBaseGlobal {
name: GlobalName,
}
@ -14,7 +31,9 @@ pub struct XdgWmBaseGlobal {
pub struct XdgWmBaseObj {
global: Rc<XdgWmBaseGlobal>,
id: ObjectId,
client: Rc<Client>,
version: u32,
pub(super) surfaces: CopyHashMap<ObjectId, Rc<XdgSurface>>,
}
impl XdgWmBaseGlobal {
@ -25,13 +44,15 @@ impl XdgWmBaseGlobal {
async fn bind_(
self: Rc<Self>,
id: ObjectId,
client: &Client,
client: &Rc<Client>,
version: u32,
) -> Result<(), XdgWmBaseError> {
let obj = Rc::new(XdgWmBaseObj {
global: self,
id,
client: client.clone(),
version,
surfaces: Default::default(),
});
client.add_client_obj(&obj)?;
Ok(())
@ -39,12 +60,65 @@ impl XdgWmBaseGlobal {
}
impl XdgWmBaseObj {
async fn handle_request_(
pub fn break_loops(&self) {
self.surfaces.clear();
}
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.client.parse(self, parser)?;
if !self.surfaces.is_empty() {
self.client.protocol_error(
self,
DEFUNCT_SURFACES,
format!(
"Cannot destroy xdg_wm_base object {} before destroying its surfaces",
self.id
),
);
return Err(DestroyError::DefunctSurfaces);
}
self.client.remove_obj(self).await?;
Ok(())
}
async fn create_positioner(
&self,
parser: MsgParser<'_, '_>,
) -> Result<(), CreatePositionerError> {
let req: CreatePositioner = self.client.parse(self, parser)?;
let pos = Rc::new(XdgPositioner::new(req.id, &self.client, 3));
self.client.add_client_obj(&pos)?;
Ok(())
}
async fn get_xdg_surface(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), GetXdgSurfaceError> {
let req: GetXdgSurface = self.client.parse(&**self, parser)?;
let surface = self.client.get_surface(req.surface)?;
let xdg_surface = Rc::new(XdgSurface::new(self, req.id, &surface, 3));
self.client.add_client_obj(&xdg_surface)?;
xdg_surface.install()?;
self.surfaces.set(req.id, xdg_surface);
Ok(())
}
async fn pong(&self, parser: MsgParser<'_, '_>) -> Result<(), PongError> {
let _req: Pong = self.client.parse(self, parser)?;
Ok(())
}
async fn handle_request_(
self: &Rc<Self>,
request: u32,
parser: MsgParser<'_, '_>,
) -> Result<(), ClientError> {
unreachable!();
) -> Result<(), XdgWmBaseError> {
match request {
DESTROY => self.destroy(parser).await?,
CREATE_POSITIONER => self.create_positioner(parser).await?,
GET_XDG_SURFACE => self.get_xdg_surface(parser).await?,
PONG => self.pong(parser).await?,
_ => unreachable!(),
}
Ok(())
}
}
@ -80,6 +154,6 @@ impl Object for XdgWmBaseObj {
}
fn num_requests(&self) -> u32 {
0
PONG + 1
}
}

View file

@ -1,10 +1,149 @@
use crate::client::ClientError;
use crate::client::{ClientError, EventFormatter, RequestParser};
use crate::ifs::xdg_wm_base::{XdgWmBaseObj, PING};
use crate::object::{Object, ObjectId};
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
use std::fmt::{Debug, Formatter};
use std::rc::Rc;
use thiserror::Error;
use crate::ifs::wl_surface::xdg_surface::XdgSurfaceError;
#[derive(Debug, Error)]
pub enum XdgWmBaseError {
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("Could not process a `destroy` request")]
DestroyError(#[from] DestroyError),
#[error("Could not process a `create_positioner` request")]
CreatePositionerError(#[from] CreatePositionerError),
#[error("Could not process a `get_xdg_surface` request")]
GetXdgSurfaceError(#[from] GetXdgSurfaceError),
#[error("Could not process a `pong` request")]
PongError(#[from] PongError),
}
efrom!(XdgWmBaseError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum DestroyError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error("Tried to destroy xdg_wm_base object before destroying its surfaces")]
DefunctSurfaces,
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(DestroyError, ParseError, MsgParserError);
efrom!(DestroyError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum CreatePositionerError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(CreatePositionerError, ParseError, MsgParserError);
efrom!(CreatePositionerError, ClientError, ClientError);
#[derive(Debug, Error)]
pub enum GetXdgSurfaceError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
#[error(transparent)]
XdgSurfaceError(Box<XdgSurfaceError>),
}
efrom!(GetXdgSurfaceError, ParseError, MsgParserError);
efrom!(GetXdgSurfaceError, ClientError, ClientError);
efrom!(GetXdgSurfaceError, XdgSurfaceError, XdgSurfaceError);
#[derive(Debug, Error)]
pub enum PongError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
}
efrom!(PongError, ParseError, MsgParserError);
pub(super) struct Destroy;
impl RequestParser<'_> for Destroy {
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self)
}
}
impl Debug for Destroy {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "destroy()",)
}
}
efrom!(XdgWmBaseError, ClientError, ClientError);
pub(super) struct CreatePositioner {
pub id: ObjectId,
}
impl RequestParser<'_> for CreatePositioner {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
id: parser.object()?,
})
}
}
impl Debug for CreatePositioner {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "create_positioner(id: {})", self.id,)
}
}
pub(super) struct GetXdgSurface {
pub id: ObjectId,
pub surface: ObjectId,
}
impl RequestParser<'_> for GetXdgSurface {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
id: parser.object()?,
surface: parser.object()?,
})
}
}
impl Debug for GetXdgSurface {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"get_xdg_surface(id: {}, surface: {})",
self.id, self.surface,
)
}
}
pub(super) struct Pong {
pub serial: u32,
}
impl RequestParser<'_> for Pong {
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
Ok(Self {
serial: parser.uint()?,
})
}
}
impl Debug for Pong {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "pong(serial: {})", self.serial,)
}
}
pub(super) struct Ping {
pub obj: Rc<XdgWmBaseObj>,
pub serial: u32,
}
impl EventFormatter for Ping {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
fmt.header(self.obj.id, PING).uint(self.serial);
}
fn obj(&self) -> &dyn Object {
&*self.obj
}
}
impl Debug for Ping {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "ping(serial: {})", self.serial)
}
}

View file

@ -1,6 +1,7 @@
#![feature(generic_associated_types, type_alias_impl_trait)]
use crate::acceptor::AcceptorError;
use crate::async_engine::AsyncError;
use crate::client::Clients;
use crate::clientmem::ClientMemError;
use crate::event_loop::EventLoopError;
@ -12,10 +13,15 @@ use crate::ifs::xdg_wm_base::XdgWmBaseGlobal;
use crate::sighand::SighandError;
use crate::state::State;
use crate::utils::numcell::NumCell;
use crate::wheel::WheelError;
use acceptor::Acceptor;
use anyhow::anyhow;
use async_engine::AsyncEngine;
use event_loop::EventLoop;
use log::LevelFilter;
use std::rc::Rc;
use thiserror::Error;
use wheel::Wheel;
#[macro_use]
mod macros;
@ -24,6 +30,7 @@ mod async_engine;
mod client;
mod clientmem;
mod event_loop;
mod format;
mod globals;
mod ifs;
mod object;
@ -54,14 +61,18 @@ enum MainError {
SighandError(#[from] SighandError),
#[error("The clientmem subsystem caused an error")]
ClientmemError(#[from] ClientMemError),
#[error("The timer subsystem caused an error")]
WheelError(#[from] WheelError),
#[error("The async subsystem caused an error")]
AsyncError(#[from] AsyncError),
}
fn main_() -> Result<(), MainError> {
clientmem::init()?;
let el = event_loop::EventLoop::new().unwrap();
sighand::install(&el.to_ref())?;
let wheel = wheel::WheelRef::new(&el.to_ref()).unwrap();
let engine = Rc::new(async_engine::AsyncEngine::new(&el.to_ref(), &wheel).unwrap());
let el = EventLoop::new()?;
sighand::install(&el)?;
let wheel = Wheel::install(&el)?;
let engine = AsyncEngine::install(&el, &wheel)?;
let globals = Globals::new();
globals.insert_no_broadcast(Rc::new(WlCompositorGlobal::new(globals.name())));
globals.insert_no_broadcast(Rc::new(WlShmGlobal::new(globals.name())));
@ -69,12 +80,13 @@ fn main_() -> Result<(), MainError> {
globals.insert_no_broadcast(Rc::new(XdgWmBaseGlobal::new(globals.name())));
let state = Rc::new(State {
eng: engine,
el: el.to_ref(),
el: el.clone(),
clients: Clients::new(),
next_name: NumCell::new(1),
globals,
formats: format::formats(),
});
acceptor::Acceptor::install(&state)?;
Acceptor::install(&state)?;
el.run()?;
Ok(())
}

View file

@ -1,5 +1,4 @@
use crate::client::ClientError;
use crate::ifs::wl_display::WlDisplay;
use crate::utils::buffd::MsgParser;
use std::fmt::{Display, Formatter};
use std::future::Future;
@ -39,9 +38,6 @@ pub trait Object: ObjectHandleRequest + 'static {
fn id(&self) -> ObjectId;
fn interface(&self) -> Interface;
fn num_requests(&self) -> u32;
fn into_display(self: Rc<Self>) -> Result<Rc<WlDisplay>, ClientError> {
Err(ClientError::NotADisplay(self.id()))
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -54,8 +50,12 @@ pub enum Interface {
WlShmPool,
WlSubcompositor,
XdgWmBase,
XdgPositioner,
WlSurface,
WlSubsurface,
XdgSurface,
XdgPopup,
XdgToplevel,
WlRegion,
}
@ -73,6 +73,10 @@ impl Interface {
Interface::WlSubsurface => "wl_subsurface",
Interface::WlShmPool => "wl_shm_pool",
Interface::WlRegion => "wl_region",
Interface::XdgSurface => "xdg_surface",
Interface::XdgPositioner => "xdg_positioner",
Interface::XdgPopup => "xdg_popup",
Interface::XdgToplevel => "xdg_toplevel",
}
}
}

View file

@ -1,4 +1,4 @@
use crate::event_loop::{EventLoopDispatcher, EventLoopId, EventLoopRef};
use crate::event_loop::{EventLoop, EventLoopDispatcher, EventLoopId};
use crate::EventLoopError;
use std::error::Error;
use std::rc::Rc;
@ -19,7 +19,7 @@ pub enum SighandError {
EventLoopError(#[from] EventLoopError),
}
pub fn install(el: &EventLoopRef) -> Result<(), SighandError> {
pub fn install(el: &Rc<EventLoop>) -> Result<(), SighandError> {
let mut set: c::sigset_t = uapi::pod_zeroed();
uapi::sigaddset(&mut set, c::SIGINT).unwrap();
if let Err(e) = uapi::pthread_sigmask(c::SIG_BLOCK, Some(&set), None) {
@ -29,7 +29,7 @@ pub fn install(el: &EventLoopRef) -> Result<(), SighandError> {
Ok(fd) => fd,
Err(e) => return Err(SighandError::CreateFailed(e.into())),
};
let id = el.id()?;
let id = el.id();
let sh = Rc::new(Sighand {
fd,
id,
@ -42,7 +42,7 @@ pub fn install(el: &EventLoopRef) -> Result<(), SighandError> {
struct Sighand {
fd: OwnedFd,
id: EventLoopId,
el: EventLoopRef,
el: Rc<EventLoop>,
}
impl EventLoopDispatcher for Sighand {

View file

@ -1,14 +1,17 @@
use crate::async_engine::AsyncEngine;
use crate::client::Clients;
use crate::event_loop::EventLoopRef;
use crate::event_loop::EventLoop;
use crate::format::Format;
use crate::globals::Globals;
use crate::utils::numcell::NumCell;
use ahash::AHashMap;
use std::rc::Rc;
pub struct State {
pub eng: Rc<AsyncEngine>,
pub el: EventLoopRef,
pub el: Rc<EventLoop>,
pub clients: Clients,
pub next_name: NumCell<u32>,
pub globals: Globals,
pub formats: AHashMap<u32, &'static Format>,
}

View file

@ -1,21 +1,21 @@
use crate::object::ObjectId;
use crate::utils::buffd::buf_out::{BufFdOut, MsgFds};
use std::mem;
use std::mem::MaybeUninit;
use std::mem::{MaybeUninit};
use uapi::OwnedFd;
pub struct MsgFormatter<'a> {
buf: &'a mut BufFdOut,
pos: usize,
fds: Vec<OwnedFd>,
fds: &'a mut Vec<OwnedFd>,
}
impl<'a> MsgFormatter<'a> {
pub fn new(buf: &'a mut BufFdOut) -> Self {
pub fn new(buf: &'a mut BufFdOut, fds: &'a mut Vec<OwnedFd>) -> Self {
Self {
pos: buf.out_pos,
buf,
fds: vec![],
fds,
}
}
@ -57,10 +57,29 @@ impl<'a> MsgFormatter<'a> {
pub fn header(&mut self, obj: ObjectId, event: u32) -> &mut Self {
self.object(obj).uint(event)
}
}
impl<'a> Drop for MsgFormatter<'a> {
fn drop(&mut self) {
pub fn array<F: FnOnce(&mut MsgFormatter<'_>)>(&mut self, f: F) -> &mut Self {
let pos = self.buf.out_pos;
self.uint(0);
let len = {
let mut fmt = MsgFormatter {
buf: self.buf,
pos,
fds: self.fds,
};
f(&mut fmt);
let len = self.buf.out_pos - pos + 4;
let none = [MaybeUninit::new(0); 4];
self.buf.write(&none[..self.buf.out_pos.wrapping_neg() & 3]);
len as u32
};
unsafe {
(*self.buf.out_buf)[pos..pos + 4].copy_from_slice(uapi::as_maybe_uninit_bytes(&len));
}
self
}
pub fn write_len(self) {
assert!(self.buf.out_pos - self.pos >= 8);
assert_eq!(self.pos % 4, 0);
unsafe {
@ -71,7 +90,7 @@ impl<'a> Drop for MsgFormatter<'a> {
if self.fds.len() > 0 {
self.buf.fds.push_back(MsgFds {
pos: self.pos,
fds: mem::take(&mut self.fds),
fds: mem::take(self.fds),
})
}
}

View file

@ -1,6 +1,7 @@
use ahash::AHashMap;
use std::cell::{RefCell, RefMut};
use std::hash::Hash;
use std::mem;
pub struct CopyHashMap<K, V> {
map: RefCell<AHashMap<K, V>>,
@ -40,6 +41,10 @@ impl<K: Eq + Hash, V: Clone> CopyHashMap<K, V> {
}
pub fn clear(&self) {
self.map.borrow_mut().clear();
mem::take(&mut *self.map.borrow_mut());
}
pub fn is_empty(&self) -> bool {
self.map.borrow().is_empty()
}
}

176
src/utils/linkedlist.rs Normal file
View file

@ -0,0 +1,176 @@
use crate::utils::ptr_ext::PtrExt;
use crate::NumCell;
use std::cell::Cell;
use std::mem::MaybeUninit;
use std::ops::Deref;
use std::ptr::NonNull;
pub struct LinkedList<T> {
root: Node<T>,
}
impl<T> Default for LinkedList<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> LinkedList<T> {
pub fn new() -> Self {
let node = Box::into_raw(Box::new(NodeData {
rc: NumCell::new(3),
prev: Cell::new(NonNull::dangling()),
next: Cell::new(NonNull::dangling()),
data: MaybeUninit::uninit(),
}));
unsafe {
node.deref().prev.set(NonNull::new_unchecked(node));
node.deref().next.set(NonNull::new_unchecked(node));
Self {
root: Node {
data: NonNull::new_unchecked(node),
},
}
}
}
pub fn prepend(&self, t: T) -> Node<T> {
self.root.prepend(t)
}
pub fn append(&self, t: T) -> Node<T> {
self.root.append(t)
}
pub fn iter(&self) -> LinkedListIter<T> {
unsafe {
let root = self.root.data.as_ref();
root.rc.fetch_add(1);
root.next.get().as_ref().rc.fetch_add(1);
LinkedListIter {
root: self.root.data,
next: root.next.get(),
}
}
}
}
pub struct LinkedListIter<T> {
root: NonNull<NodeData<T>>,
next: NonNull<NodeData<T>>,
}
impl<T> Iterator for LinkedListIter<T> {
type Item = NodeRef<T>;
fn next(&mut self) -> Option<Self::Item> {
if self.root == self.next {
return None;
}
unsafe {
let old_next = self.next;
self.next = old_next.as_ref().next.get();
self.next.as_ref().rc.fetch_add(1);
Some(NodeRef { data: old_next })
}
}
}
impl<T> Drop for LinkedListIter<T> {
fn drop(&mut self) {
unsafe {
dec_ref_count(self.root, 1);
dec_ref_count(self.next, 1);
}
}
}
pub struct Node<T> {
data: NonNull<NodeData<T>>,
}
impl<T> Deref for Node<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { self.data.as_ref().data.assume_init_ref() }
}
}
pub struct NodeRef<T> {
data: NonNull<NodeData<T>>,
}
impl<T> Deref for NodeRef<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { self.data.as_ref().data.assume_init_ref() }
}
}
impl<T> Drop for NodeRef<T> {
fn drop(&mut self) {
unsafe {
dec_ref_count(self.data, 1);
}
}
}
struct NodeData<T> {
rc: NumCell<usize>,
prev: Cell<NonNull<NodeData<T>>>,
next: Cell<NonNull<NodeData<T>>>,
data: MaybeUninit<T>,
}
unsafe fn dec_ref_count<T>(slf: NonNull<NodeData<T>>, n: usize) {
if slf.as_ref().rc.fetch_sub(n) == n {
drop(Box::from_raw(slf.as_ptr()));
}
}
impl<T> Drop for Node<T> {
fn drop(&mut self) {
unsafe {
{
let data = self.data.as_ref();
data.prev.get().as_ref().next.set(data.next.get());
data.next.get().as_ref().prev.set(data.prev.get());
}
dec_ref_count(self.data, 3);
}
}
}
impl<T> Node<T> {
pub fn prepend(&self, t: T) -> Node<T> {
unsafe {
let data = self.data.as_ref();
let node = NonNull::new_unchecked(Box::into_raw(Box::new(NodeData {
rc: NumCell::new(3),
prev: Cell::new(data.prev.get()),
next: Cell::new(self.data),
data: MaybeUninit::new(t),
})));
data.prev.get().as_ref().next.set(node);
data.prev.set(node);
Node { data: node }
}
}
pub fn append(&self, t: T) -> Node<T> {
unsafe {
let data = self.data.as_ref();
let node = NonNull::new_unchecked(Box::into_raw(Box::new(NodeData {
rc: NumCell::new(3),
prev: Cell::new(self.data),
next: Cell::new(data.next.get()),
data: MaybeUninit::new(t),
})));
data.next.get().as_ref().prev.set(node);
data.next.set(node);
Node { data: node }
}
}
}

View file

@ -1,7 +1,9 @@
pub mod buffd;
pub mod copyhashmap;
pub mod linkedlist;
pub mod lock;
pub mod numcell;
pub mod oneshot;
pub mod ptr_ext;
pub mod queue;
pub mod vec_ext;

25
src/utils/ptr_ext.rs Normal file
View file

@ -0,0 +1,25 @@
pub trait PtrExt<T> {
unsafe fn deref<'a>(self) -> &'a T;
}
pub trait MutPtrExt<T> {
unsafe fn deref_mut<'a>(self) -> &'a mut T;
}
impl<T> PtrExt<T> for *const T {
unsafe fn deref<'a>(self) -> &'a T {
&*self
}
}
impl<T> PtrExt<T> for *mut T {
unsafe fn deref<'a>(self) -> &'a T {
&*self
}
}
impl<T> MutPtrExt<T> for *mut T {
unsafe fn deref_mut<'a>(self) -> &'a mut T {
&mut *self
}
}

View file

@ -1,11 +1,11 @@
use crate::event_loop::{EventLoopDispatcher, EventLoopError, EventLoopId, EventLoopRef};
use crate::event_loop::{EventLoop, EventLoopDispatcher, EventLoopError};
use crate::time::{Time, TimeError};
use crate::utils::copyhashmap::CopyHashMap;
use crate::utils::numcell::NumCell;
use std::cell::{Cell, RefCell};
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::rc::{Rc, Weak};
use std::rc::Rc;
use std::time::Duration;
use thiserror::Error;
use uapi::{c, OwnedFd};
@ -30,11 +30,6 @@ pub trait WheelDispatcher {
fn dispatch(self: Rc<Self>) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
}
#[derive(Clone)]
pub struct WheelRef {
data: Weak<WheelData>,
}
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
struct WheelEntry {
expiration: Time,
@ -44,10 +39,9 @@ struct WheelEntry {
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct WheelId(u64);
struct WheelData {
id: EventLoopId,
pub struct Wheel {
destroyed: Cell<bool>,
fd: OwnedFd,
el: EventLoopRef,
next_id: NumCell<u64>,
start: Time,
current_expiration: Cell<Option<Time>>,
@ -55,37 +49,47 @@ struct WheelData {
expirations: RefCell<BinaryHeap<Reverse<WheelEntry>>>,
}
impl WheelData {
fn new(el: &EventLoopRef) -> Result<Rc<Self>, WheelError> {
impl Wheel {
pub fn install(el: &Rc<EventLoop>) -> Result<Rc<Self>, WheelError> {
let fd = match uapi::timerfd_create(c::CLOCK_MONOTONIC, c::TFD_CLOEXEC | c::TFD_NONBLOCK) {
Ok(fd) => fd,
Err(e) => return Err(WheelError::CreateFailed(e.into())),
};
let id = el.id()?;
let id = el.id();
let wheel = Rc::new(Self {
id,
destroyed: Cell::new(false),
fd,
el: el.clone(),
next_id: Default::default(),
start: Time::now()?,
current_expiration: Cell::new(None),
dispatchers: CopyHashMap::new(),
expirations: RefCell::new(Default::default()),
});
el.insert(id, Some(wheel.fd.raw()), c::EPOLLIN, wheel.clone())?;
let wrapper = Rc::new(WheelWrapper {
wheel: wheel.clone(),
});
el.insert(id, Some(wheel.fd.raw()), c::EPOLLIN, wrapper)?;
Ok(wheel)
}
fn id(&self) -> WheelId {
pub fn id(&self) -> WheelId {
WheelId(self.next_id.fetch_add(1))
}
fn timeout(
fn check_destroyed(&self) -> Result<(), WheelError> {
if self.destroyed.get() {
return Err(WheelError::Destroyed);
}
Ok(())
}
pub fn timeout(
&self,
id: WheelId,
ms: u64,
dispatcher: Rc<dyn WheelDispatcher>,
) -> Result<(), WheelError> {
self.check_destroyed()?;
let expiration = (Time::now()? + Duration::from_millis(ms)).round_to_ms();
let current = self.current_expiration.get();
if current.is_none() || expiration - self.start < current.unwrap() - self.start {
@ -110,41 +114,45 @@ impl WheelData {
Ok(())
}
fn remove(&self, id: WheelId) {
log::trace!("removing {:?} from wheel", id);
pub fn remove(&self, id: WheelId) {
// log::trace!("removing {:?} from wheel", id);
self.dispatchers.remove(&id.0);
}
}
impl EventLoopDispatcher for WheelData {
struct WheelWrapper {
wheel: Rc<Wheel>,
}
impl EventLoopDispatcher for WheelWrapper {
fn dispatch(&self, events: i32) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
if events & (c::EPOLLERR | c::EPOLLHUP) != 0 {
return Err(Box::new(WheelError::ErrorEvent));
}
let mut n = 0u64;
while uapi::read(self.fd.raw(), &mut n).is_ok() {}
while uapi::read(self.wheel.fd.raw(), &mut n).is_ok() {}
let now = match Time::now() {
Ok(n) => n,
Err(e) => return Err(Box::new(e)),
};
let dist = now - self.start;
let dist = now - self.wheel.start;
let mut to_dispatch = vec![];
{
let mut expirations = self.expirations.borrow_mut();
let mut expirations = self.wheel.expirations.borrow_mut();
while let Some(Reverse(entry)) = expirations.peek() {
if entry.expiration - self.start > dist {
if entry.expiration - self.wheel.start > dist {
break;
}
if let Some(dispatcher) = self.dispatchers.remove(&entry.id) {
if let Some(dispatcher) = self.wheel.dispatchers.remove(&entry.id) {
to_dispatch.push(dispatcher);
}
expirations.pop();
}
self.current_expiration.set(None);
self.wheel.current_expiration.set(None);
while let Some(Reverse(entry)) = expirations.peek() {
if self.dispatchers.get(&entry.id).is_some() {
if self.wheel.dispatchers.get(&entry.id).is_some() {
let res = uapi::timerfd_settime(
self.fd.raw(),
self.wheel.fd.raw(),
c::TFD_TIMER_ABSTIME,
&c::itimerspec {
it_interval: uapi::pod_zeroed(),
@ -154,7 +162,7 @@ impl EventLoopDispatcher for WheelData {
if let Err(e) = res {
return Err(Box::new(WheelError::SetFailed(e.into())));
}
self.current_expiration.set(Some(entry.expiration));
self.wheel.current_expiration.set(Some(entry.expiration));
break;
}
expirations.pop();
@ -167,41 +175,9 @@ impl EventLoopDispatcher for WheelData {
}
}
impl Drop for WheelData {
impl Drop for WheelWrapper {
fn drop(&mut self) {
let _ = self.el.remove(self.id);
}
}
impl WheelRef {
pub fn new(el: &EventLoopRef) -> Result<Self, WheelError> {
Ok(Self {
data: Rc::downgrade(&WheelData::new(el)?),
})
}
pub fn id(&self) -> Result<WheelId, WheelError> {
match self.data.upgrade() {
Some(d) => Ok(d.id()),
_ => Err(WheelError::Destroyed),
}
}
pub fn timeout(
&self,
id: WheelId,
ms: u64,
dispatcher: Rc<dyn WheelDispatcher>,
) -> Result<(), WheelError> {
match self.data.upgrade() {
Some(d) => d.timeout(id, ms, dispatcher),
_ => Err(WheelError::Destroyed),
}
}
pub fn remove(&self, id: WheelId) {
if let Some(wheel) = self.data.upgrade() {
wheel.remove(id);
}
self.wheel.destroyed.set(true);
self.wheel.dispatchers.clear();
}
}