Skip to content

Commit

Permalink
POC implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
PolyMeilex committed Aug 26, 2023
1 parent e241ccb commit b0f6ffd
Show file tree
Hide file tree
Showing 10 changed files with 455 additions and 1 deletion.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,17 @@ rustdoc-args = ["--cfg", "docsrs"]
[workspace]
members = [
"smithay-drm-extras",
"smithay-derive",
"smallvil",
"anvil",
"wlcs_anvil"
]

[dependencies]
quote = "1.0.26"
proc-macro-crate = "1.0"
proc-macro2 = "1.0"

appendlist = "1.4"
# Intentionally pick a commit from "0.37-stable" branch since additions for 0.37.1 are used
ash = { version = "0.37.1", optional = true }
Expand Down
23 changes: 23 additions & 0 deletions smithay-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "smithay-derive"
version = "0.1.0"
edition = "2021"

[lib]
proc-macro = true

[dependencies]
proc-macro-crate = "1.0"
proc-macro2 = "1.0"
quote = "1.0.26"
syn = { version = "2.0", default-features = false, features = [
"full",
"parsing",
] }
smithay = { path = "../" }

[dev-dependencies]
smithay = { path = "../" }

[[example]]
name = "simple"
24 changes: 24 additions & 0 deletions smithay-derive/examples/simple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use ::smithay::wayland::{buffer::BufferHandler, shm::ShmHandler};

trait MarkerTrait {}

#[derive(smithay_derive::DelegateModule)]
#[delegate(Output, Shm)]
struct State;

impl BufferHandler for State {
fn buffer_destroyed(
&mut self,
_buffer: &smithay::reexports::wayland_server::protocol::wl_buffer::WlBuffer,
) {
todo!()
}
}

impl ShmHandler for State {
fn shm_state(&self) -> &smithay::wayland::shm::ShmState {
todo!()
}
}

fn main() {}
116 changes: 116 additions & 0 deletions smithay-derive/src/delegate_dispatch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use smithay::wayland::module_registry::{Global, ModuleDescriptor, Resource};

pub(crate) fn delegate_module(
ident: &syn::Ident,
generics: &syn::Generics,
module: &ModuleDescriptor,
) -> TokenStream2 {
let ModuleDescriptor {
dispatch_to,
globals,
resources,
..
} = module;

let globals = globals.iter().map(|Global { interface, data }| {
delegate_global_dispatch(ident, generics, dispatch_to, interface, data)
});
let resources = resources
.iter()
.map(|Resource { interface, data }| delegate_dispatch(ident, generics, dispatch_to, interface, data));

quote! {
#(#globals)*
#(#resources)*
}
}

pub(crate) fn delegate_global_dispatch(
ident: &syn::Ident,
generics: &syn::Generics,

dispatch_to: &TokenStream2,
interface: &TokenStream2,
data: &TokenStream2,
) -> TokenStream2 {
use smithay::wayland::module_registry::smithay;
let wayland_server = smithay!(reexports::wayland_server);

let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
let trait_name = quote!(#wayland_server::GlobalDispatch<#interface, #data>);

quote! {
#[automatically_derived]
impl #impl_generics #trait_name for #ident #type_generics #where_clause {
fn bind(
state: &mut Self,
dhandle: &#wayland_server::DisplayHandle,
client: &#wayland_server::Client,
resource: #wayland_server::New<#interface>,
global_data: &#data,
data_init: &mut #wayland_server::DataInit<'_, Self>,
) {
<#dispatch_to as #wayland_server::GlobalDispatch<
#interface,
#data,
Self,
>>::bind(state, dhandle, client, resource, global_data, data_init)
}

fn can_view(client: #wayland_server::Client, global_data: &#data) -> bool {
<#dispatch_to as #wayland_server::GlobalDispatch<
#interface,
#data,
Self,
>>::can_view(client, global_data)
}
}
}
}

pub(crate) fn delegate_dispatch(
ident: &syn::Ident,
generics: &syn::Generics,

dispatch_to: &TokenStream2,
interface: &TokenStream2,
data: &TokenStream2,
) -> TokenStream2 {
use smithay::wayland::module_registry::smithay;
let wayland_server = smithay!(reexports::wayland_server);

let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
let trait_name = quote!(#wayland_server::Dispatch<#interface, #data>);

quote! {
#[automatically_derived]
impl #impl_generics #trait_name for #ident #type_generics #where_clause {
fn request(
state: &mut Self,
client: &#wayland_server::Client,
resource: &#interface,
request: <#interface as #wayland_server::Resource>::Request,
data: &#data,
dhandle: &#wayland_server::DisplayHandle,
data_init: &mut #wayland_server::DataInit<'_, Self>,
) {
<#dispatch_to as #wayland_server::Dispatch<#interface, #data, Self>>::request(
state, client, resource, request, data, dhandle, data_init,
)
}

fn destroyed(
state: &mut Self,
client: #wayland_server::backend::ClientId,
resource: #wayland_server::backend::ObjectId,
data: &#data,
) {
<#dispatch_to as #wayland_server::Dispatch<#interface, #data, Self>>::destroyed(
state, client, resource, data,
)
}
}
}
}
60 changes: 60 additions & 0 deletions smithay-derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Token};

use smithay::wayland::module_registry::ModuleRegistry;

mod delegate_dispatch;

struct DelegateDeriveInput {
ident: syn::Ident,
generics: syn::Generics,
modules: Vec<syn::Ident>,
}

impl syn::parse::Parse for DelegateDeriveInput {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let input: syn::DeriveInput = input.parse()?;

let mut modules = Vec::new();
for attr in input.attrs {
let args = attr.parse_args_with(|input: syn::parse::ParseStream| {
input.parse_terminated(|input| input.parse::<syn::Ident>(), Token![,])
})?;

for module in args {
modules.push(module);
}
}

Ok(Self {
ident: input.ident,
generics: input.generics,
modules,
})
}
}

#[proc_macro_derive(DelegateModule, attributes(delegate))]
pub fn delegate_global_dispatch(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DelegateDeriveInput);

let registry = ModuleRegistry::new();

let mut impls = Vec::new();
for item in input.modules {
if let Some(module) = registry.get(item.to_string().as_str()) {
impls.push(delegate_dispatch::delegate_module(
&input.ident,
&input.generics,
module,
));
} else {
return syn::Error::new(item.span(), "Unknown smithay module")
.to_compile_error()
.into();
}
}

quote!(#(#impls)*).into()
}
48 changes: 48 additions & 0 deletions src/wayland/compositor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ use wayland_server::protocol::wl_subcompositor::WlSubcompositor;
use wayland_server::protocol::{wl_buffer, wl_callback, wl_output, wl_region, wl_surface::WlSurface};
use wayland_server::{Client, DisplayHandle, GlobalDispatch, Resource};

use super::module_registry;

/// The role of a subsurface surface.
pub const SUBSURFACE_ROLE: &str = "subsurface";

Expand Down Expand Up @@ -629,6 +631,52 @@ macro_rules! delegate_compositor {
};
}

pub(super) fn descriptor() -> module_registry::ModuleDescriptor {
use module_registry::{smithay, wayland_core, Global, ModuleDescriptor, Resource};
use quote::quote;

ModuleDescriptor {
name: quote!(Compositor),
dispatch_to: smithay!(wayland::compositor::CompositorState),
globals: vec![
Global {
interface: wayland_core!(wl_compositor::WlCompositor),
data: quote!(()),
},
Global {
interface: wayland_core!(wl_subcompositor::WlSubcompositor),
data: quote!(()),
},
],
resources: vec![
Resource {
interface: wayland_core!(wl_compositor::WlCompositor),
data: quote!(()),
},
Resource {
interface: wayland_core!(wl_surface::WlSurface),
data: smithay!(wayland::compositor::SurfaceUserData),
},
Resource {
interface: wayland_core!(wl_region::WlRegion),
data: smithay!(wayland::compositor::RegionUserData),
},
Resource {
interface: wayland_core!(wl_callback::WlCallback),
data: quote!(()),
},
Resource {
interface: wayland_core!(wl_subcompositor::WlSubcompositor),
data: quote!(()),
},
Resource {
interface: wayland_core!(wl_subsurface::WlSubsurface),
data: quote!(()),
},
],
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
3 changes: 3 additions & 0 deletions src/wayland/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
//! are not, for example).
//!
#[doc(hidden)]
pub mod module_registry;

pub mod buffer;
pub mod compositor;
pub mod content_type;
Expand Down
Loading

0 comments on commit b0f6ffd

Please sign in to comment.