Skip to content

Commit

Permalink
wayland: use code generation for wl_usr event handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
mahkoh committed Jul 25, 2024
1 parent b359b26 commit 084fe50
Show file tree
Hide file tree
Showing 49 changed files with 552 additions and 522 deletions.
78 changes: 59 additions & 19 deletions build/wire.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,9 @@ impl<'a> Parser<'a> {
});
let safe_name = match name {
"move" => "move_",
"type" => "type_",
"drop" => "drop_",
"id" => "id_",
_ => name,
};
Ok(Lined {
Expand Down Expand Up @@ -717,18 +720,50 @@ fn write_message<W: Write>(f: &mut W, obj: &str, message: &Message) -> Result<()
Ok(())
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum RequestHandlerDirection {
Request,
Event,
}

fn write_request_handler<W: Write>(
f: &mut W,
camel_obj_name: &str,
messages: &ParseResult,
messages: &[Lined<Message>],
direction: RequestHandlerDirection,
) -> Result<()> {
let snake_direction;
let camel_direction;
let parent;
let parser;
let error;
let param;
writeln!(f)?;
match direction {
RequestHandlerDirection::Request => {
snake_direction = "request";
camel_direction = "Request";
parent = "crate::object::Object";
parser = "crate::client::Client";
error = "crate::client::ClientError";
param = "req";
}
RequestHandlerDirection::Event => {
snake_direction = "event";
camel_direction = "Event";
parent = "crate::wl_usr::usr_object::UsrObject";
parser = "crate::wl_usr::UsrCon";
error = "crate::wl_usr::UsrConError";
param = "ev";
writeln!(f, " #[allow(dead_code)]")?;
}
}
writeln!(
f,
" pub trait {camel_obj_name}RequestHandler: crate::object::Object + Sized {{"
" pub trait {camel_obj_name}{camel_direction}Handler: {parent} + Sized {{"
)?;
writeln!(f, " type Error: std::error::Error;")?;
for message in &messages.requests {
for message in messages {
let msg = &message.val;
let lt = match msg.has_reference_type {
true => "<'_>",
Expand All @@ -737,34 +772,31 @@ fn write_request_handler<W: Write>(
writeln!(f)?;
writeln!(
f,
" fn {}(&self, req: {}{lt}, _slf: &Rc<Self>) -> Result<(), Self::Error>;",
" fn {}(&self, {param}: {}{lt}, _slf: &Rc<Self>) -> Result<(), Self::Error>;",
msg.safe_name, msg.camel_name
)?;
}
writeln!(f)?;
writeln!(f, " #[inline(always)]")?;
writeln!(f, " fn handle_request_impl(")?;
writeln!(f, " fn handle_{snake_direction}_impl(")?;
writeln!(f, " self: Rc<Self>,")?;
writeln!(f, " client: &crate::client::Client,")?;
writeln!(f, " client: &{parser},")?;
writeln!(f, " req: u32,")?;
writeln!(
f,
" parser: crate::utils::buffd::MsgParser<'_, '_>,"
)?;
writeln!(f, " ) -> Result<(), crate::client::ClientError> {{")?;
if messages.requests.is_empty() {
writeln!(f, " ) -> Result<(), {error}> {{")?;
if messages.is_empty() {
writeln!(f, " #![allow(unused_variables)]")?;
writeln!(
f,
" Err(crate::client::ClientError::InvalidMethod)"
)?;
writeln!(f, " Err({error}::InvalidMethod)")?;
} else {
writeln!(f, " let method;")?;
writeln!(
f,
" let error: Box<dyn std::error::Error> = match req {{"
)?;
for message in &messages.requests {
for message in messages {
let msg = &message.val;
write!(f, " {} ", msg.id)?;
if let Some(since) = msg.attribs.since {
Expand Down Expand Up @@ -793,13 +825,10 @@ fn write_request_handler<W: Write>(
}
writeln!(
f,
" _ => return Err(crate::client::ClientError::InvalidMethod),"
" _ => return Err({error}::InvalidMethod),"
)?;
writeln!(f, " }};")?;
writeln!(
f,
" Err(crate::client::ClientError::MethodError {{"
)?;
writeln!(f, " Err({error}::MethodError {{")?;
writeln!(f, " interface: {camel_obj_name},")?;
writeln!(f, " method,")?;
writeln!(f, " error,")?;
Expand Down Expand Up @@ -832,7 +861,18 @@ fn write_file<W: Write>(f: &mut W, file: &DirEntry) -> Result<()> {
for message in messages.requests.iter().chain(messages.events.iter()) {
write_message(f, &camel_obj_name, &message.val)?;
}
write_request_handler(f, &camel_obj_name, &messages)?;
write_request_handler(
f,
&camel_obj_name,
&messages.requests,
RequestHandlerDirection::Request,
)?;
write_request_handler(
f,
&camel_obj_name,
&messages.events,
RequestHandlerDirection::Event,
)?;
writeln!(f, "}}")?;
Ok(())
}
Expand Down
37 changes: 12 additions & 25 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,26 @@ macro_rules! efrom {
}

macro_rules! usr_object_base {
($oname:ident, $iname:ident; $($code:ident => $f:ident,)*) => {
($self:ident = $oname:ident = $iname:ident; version = $version:expr;) => {
impl crate::wl_usr::usr_object::UsrObjectBase for $oname {
fn id(&self) -> crate::object::ObjectId {
self.id.into()
fn id(&$self) -> crate::object::ObjectId {
$self.id.into()
}

fn version(&$self) -> crate::object::Version {
$version
}

#[allow(unused_variables, unreachable_code)]
fn handle_event(
self: std::rc::Rc<Self>,
$self: std::rc::Rc<Self>,
con: &crate::wl_usr::UsrCon,
event: u32,
parser: crate::utils::buffd::MsgParser<'_, '_>,
) -> Result<(), crate::wl_usr::usr_object::UsrObjectError> {
let res: std::result::Result<(), _> = match event {
$(
$code => $oname::$f(&self, parser).map_err(|e| crate::wl_usr::usr_object::UsrObjectErrorType::EventError {
event: stringify!($f),
error: Box::new(e),
}),
)*
_ => Err(crate::wl_usr::usr_object::UsrObjectErrorType::UnknownEventError {
event,
}),
};
if let Err(e) = res {
return Err(crate::wl_usr::usr_object::UsrObjectError {
interface: crate::wire::$iname,
ty: e,
});
}
Ok(())
) -> Result<(), crate::wl_usr::UsrConError> {
$self.handle_event_impl(con, event, parser)
}

fn interface(&self) -> crate::object::Interface {
fn interface(&$self) -> crate::object::Interface {
crate::wire::$iname
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/portal/ptl_display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use {
crate::{
gfx_apis::create_gfx_context,
ifs::wl_seat::POINTER,
object::Version,
portal::{
ptl_render_ctx::PortalRenderCtx, ptl_screencast::ScreencastSession,
ptr_gui::WindowData, PortalState,
Expand Down Expand Up @@ -213,6 +214,7 @@ impl UsrWlRegistryOwner for PortalDisplay {
id: self.con.id(),
con: self.con.clone(),
owner: Default::default(),
version: Version(version.min(5)),
});
self.con.add_object(ls.clone());
self.registry.request_bind(name, version, ls.deref());
Expand Down Expand Up @@ -301,6 +303,7 @@ fn finish_display_connect(dpy: Rc<PortalDisplayPrelude>) {
con: dpy.con.clone(),
owner: Default::default(),
caps: Default::default(),
version: Version(version.min(4)),
});
dpy.con.add_object(jc.clone());
dpy.registry.request_bind(name, version, jc.deref());
Expand All @@ -309,6 +312,7 @@ fn finish_display_connect(dpy: Rc<PortalDisplayPrelude>) {
let ls = Rc::new(UsrWpFractionalScaleManager {
id: dpy.con.id(),
con: dpy.con.clone(),
version: Version(version.min(1)),
});
dpy.con.add_object(ls.clone());
dpy.registry.request_bind(name, version, ls.deref());
Expand All @@ -317,6 +321,7 @@ fn finish_display_connect(dpy: Rc<PortalDisplayPrelude>) {
let ls = Rc::new(UsrWlrLayerShell {
id: dpy.con.id(),
con: dpy.con.clone(),
version: Version(version.min(5)),
});
dpy.con.add_object(ls.clone());
dpy.registry.request_bind(name, version, ls.deref());
Expand All @@ -325,6 +330,7 @@ fn finish_display_connect(dpy: Rc<PortalDisplayPrelude>) {
let ls = Rc::new(UsrWpViewporter {
id: dpy.con.id(),
con: dpy.con.clone(),
version: Version(version.min(1)),
});
dpy.con.add_object(ls.clone());
dpy.registry.request_bind(name, version, ls.deref());
Expand All @@ -333,6 +339,7 @@ fn finish_display_connect(dpy: Rc<PortalDisplayPrelude>) {
let ls = Rc::new(UsrWlCompositor {
id: dpy.con.id(),
con: dpy.con.clone(),
version: Version(version.min(6)),
});
dpy.con.add_object(ls.clone());
dpy.registry.request_bind(name, version, ls.deref());
Expand All @@ -342,6 +349,7 @@ fn finish_display_connect(dpy: Rc<PortalDisplayPrelude>) {
id: dpy.con.id(),
con: dpy.con.clone(),
owner: Default::default(),
version: Version(version.min(5)),
});
dpy.con.add_object(ls.clone());
dpy.registry.request_bind(name, version, ls.deref());
Expand Down Expand Up @@ -410,6 +418,7 @@ fn add_seat(dpy: &Rc<PortalDisplay>, name: u32, version: u32) {
id: dpy.con.id(),
con: dpy.con.clone(),
owner: Default::default(),
version: Version(version.min(9)),
});
dpy.con.add_object(wl.clone());
dpy.registry.request_bind(name, version, wl.deref());
Expand All @@ -433,6 +442,7 @@ fn add_output(dpy: &Rc<PortalDisplay>, name: u32, version: u32) {
id: dpy.con.id(),
con: dpy.con.clone(),
owner: Default::default(),
version: Version(version.min(4)),
});
dpy.con.add_object(wl.clone());
dpy.registry.request_bind(name, version, wl.deref());
Expand Down
20 changes: 15 additions & 5 deletions src/wl_usr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use {
async_engine::{AsyncEngine, SpawnedFuture},
client::{EventFormatter, RequestParser, MIN_SERVER_ID},
io_uring::{IoUring, IoUringError},
object::{ObjectId, WL_DISPLAY_ID},
object::{Interface, ObjectId, Version, WL_DISPLAY_ID},
utils::{
asyncevent::AsyncEvent,
bitfield::Bitfield,
Expand All @@ -29,12 +29,13 @@ use {
usr_wl_callback::UsrWlCallback, usr_wl_display::UsrWlDisplay,
usr_wl_registry::UsrWlRegistry,
},
usr_object::{UsrObject, UsrObjectError},
usr_object::UsrObject,
},
},
std::{
cell::{Cell, RefCell},
collections::VecDeque,
error::Error,
mem,
rc::Rc,
},
Expand All @@ -60,10 +61,17 @@ pub enum UsrConError {
Read(#[source] BufFdError),
#[error("Could not write to the compositor")]
Write(#[source] BufFdError),
#[error(transparent)]
UsrObjectError(#[from] UsrObjectError),
#[error("Server sent an event for object {0} that does not exist")]
MissingObject(ObjectId),
#[error("Could not process a `{}.{}` event", .interface.name(), .method)]
MethodError {
interface: Interface,
method: &'static str,
#[source]
error: Box<dyn Error + 'static>,
},
#[error("Client tried to invoke a non-existent method")]
InvalidMethod,
}

pub struct UsrCon {
Expand Down Expand Up @@ -133,6 +141,7 @@ impl UsrCon {
Some(Rc::new(UsrWlDisplay {
id: WL_DISPLAY_ID,
con: slf.clone(),
version: Version(1),
})),
);
slf.incoming.set(Some(
Expand Down Expand Up @@ -198,6 +207,7 @@ impl UsrCon {
id: self.id(),
con: self.clone(),
owner: Default::default(),
version: Version(1),
});
self.request(wl_display::GetRegistry {
self_id: WL_DISPLAY_ID,
Expand Down Expand Up @@ -352,7 +362,7 @@ impl Incoming {
if let Some(obj) = self.con.objects.get(&obj_id) {
if let Some(obj) = obj {
let parser = MsgParser::new(&mut self.buf, &self.data);
obj.handle_event(event, parser)?;
obj.handle_event(&self.con, event, parser)?;
}
} else if obj_id.raw() < MIN_SERVER_ID {
return Err(UsrConError::MissingObject(obj_id));
Expand Down
Loading

0 comments on commit 084fe50

Please sign in to comment.