wayland: add a generic wayland client
This commit is contained in:
parent
163adbd893
commit
2512470231
34 changed files with 2627 additions and 1 deletions
|
|
@ -1,4 +1,3 @@
|
|||
pub use error::{ClientError, MethodError, ObjectError};
|
||||
use {
|
||||
crate::{
|
||||
async_engine::SpawnedFuture,
|
||||
|
|
@ -30,6 +29,10 @@ use {
|
|||
},
|
||||
uapi::{c, OwnedFd},
|
||||
};
|
||||
pub use {
|
||||
error::{ClientError, MethodError, ObjectError},
|
||||
objects::MIN_SERVER_ID,
|
||||
};
|
||||
|
||||
mod error;
|
||||
mod objects;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,46 @@ macro_rules! efrom {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! usr_object_base {
|
||||
($oname:ident, $iname:ident; $($code:ident => $f:ident,)*) => {
|
||||
impl crate::wl_usr::usr_object::UsrObjectBase for $oname {
|
||||
fn id(&self) -> crate::object::ObjectId {
|
||||
self.id.into()
|
||||
}
|
||||
|
||||
#[allow(unused_variables, unreachable_code)]
|
||||
fn handle_event(
|
||||
self: std::rc::Rc<Self>,
|
||||
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(())
|
||||
}
|
||||
|
||||
fn interface(&self) -> crate::object::Interface {
|
||||
crate::wire::$iname
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! object_base {
|
||||
($oname:ident; $($code:ident => $f:ident,)*) => {
|
||||
impl crate::object::ObjectBase for $oname {
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ mod wheel;
|
|||
mod wire;
|
||||
mod wire_dbus;
|
||||
mod wire_xcon;
|
||||
mod wl_usr;
|
||||
mod xcon;
|
||||
mod xkbcommon;
|
||||
mod xwayland;
|
||||
|
|
|
|||
357
src/wl_usr.rs
Normal file
357
src/wl_usr.rs
Normal file
|
|
@ -0,0 +1,357 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
pub mod usr_ifs;
|
||||
pub mod usr_object;
|
||||
|
||||
use {
|
||||
crate::{
|
||||
async_engine::{AsyncEngine, SpawnedFuture},
|
||||
client::{EventFormatter, RequestParser, MIN_SERVER_ID},
|
||||
io_uring::IoUring,
|
||||
object::{ObjectId, WL_DISPLAY_ID},
|
||||
utils::{
|
||||
asyncevent::AsyncEvent,
|
||||
bitfield::Bitfield,
|
||||
buffd::{
|
||||
BufFdError, BufFdIn, BufFdOut, MsgFormatter, MsgParser, MsgParserError, OutBuffer,
|
||||
OutBufferSwapchain,
|
||||
},
|
||||
clonecell::CloneCell,
|
||||
copyhashmap::CopyHashMap,
|
||||
errorfmt::ErrorFmt,
|
||||
oserror::OsError,
|
||||
vec_ext::VecExt,
|
||||
},
|
||||
wheel::Wheel,
|
||||
wire::wl_display,
|
||||
wl_usr::{
|
||||
usr_ifs::{
|
||||
usr_wl_callback::UsrWlCallback, usr_wl_display::UsrWlDisplay,
|
||||
usr_wl_registry::UsrWlRegistry,
|
||||
},
|
||||
usr_object::{UsrObject, UsrObjectError},
|
||||
},
|
||||
},
|
||||
std::{
|
||||
cell::{Cell, RefCell},
|
||||
collections::VecDeque,
|
||||
mem,
|
||||
rc::Rc,
|
||||
},
|
||||
thiserror::Error,
|
||||
uapi::c,
|
||||
};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum UsrConError {
|
||||
#[error("Could not create a socket")]
|
||||
CreateSocket(#[source] OsError),
|
||||
#[error("The socket path is too long")]
|
||||
SocketPathTooLong,
|
||||
#[error("Could not connect to the compositor")]
|
||||
Connect(#[source] OsError),
|
||||
#[error("The message length is smaller than 8 bytes")]
|
||||
MsgLenTooSmall,
|
||||
#[error("The size of the message is not a multiple of 4")]
|
||||
UnalignedMessage,
|
||||
#[error(transparent)]
|
||||
BufFdError(#[from] BufFdError),
|
||||
#[error("Could not read from the compositor")]
|
||||
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),
|
||||
}
|
||||
|
||||
pub struct UsrCon {
|
||||
pub ring: Rc<IoUring>,
|
||||
pub wheel: Rc<Wheel>,
|
||||
pub eng: Rc<AsyncEngine>,
|
||||
pub server_id: u32,
|
||||
obj_ids: RefCell<Bitfield>,
|
||||
objects: CopyHashMap<ObjectId, Option<Rc<dyn UsrObject>>>,
|
||||
swapchain: Rc<RefCell<OutBufferSwapchain>>,
|
||||
flush_request: AsyncEvent,
|
||||
incoming: Cell<Option<SpawnedFuture<()>>>,
|
||||
outgoing: Cell<Option<SpawnedFuture<()>>>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrConOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrConOwner {
|
||||
fn killed(&self);
|
||||
}
|
||||
|
||||
impl UsrCon {
|
||||
pub fn new(
|
||||
ring: &Rc<IoUring>,
|
||||
wheel: &Rc<Wheel>,
|
||||
eng: &Rc<AsyncEngine>,
|
||||
path: &str,
|
||||
server_id: u32,
|
||||
) -> Result<Rc<Self>, UsrConError> {
|
||||
let socket = match uapi::socket(
|
||||
c::AF_UNIX,
|
||||
c::SOCK_STREAM | c::SOCK_CLOEXEC | c::SOCK_NONBLOCK,
|
||||
0,
|
||||
) {
|
||||
Ok(s) => Rc::new(s),
|
||||
Err(e) => return Err(UsrConError::CreateSocket(e.into())),
|
||||
};
|
||||
let mut addr: c::sockaddr_un = uapi::pod_zeroed();
|
||||
addr.sun_family = c::AF_UNIX as _;
|
||||
if path.len() >= addr.sun_path.len() {
|
||||
return Err(UsrConError::SocketPathTooLong);
|
||||
}
|
||||
let sun_path = uapi::as_bytes_mut(&mut addr.sun_path[..]);
|
||||
sun_path[..path.len()].copy_from_slice(path.as_bytes());
|
||||
sun_path[path.len()] = 0;
|
||||
if let Err(e) = uapi::connect(socket.raw(), &addr) {
|
||||
return Err(UsrConError::Connect(e.into()));
|
||||
}
|
||||
let mut obj_ids = Bitfield::default();
|
||||
obj_ids.take(0);
|
||||
obj_ids.take(1);
|
||||
let slf = Rc::new(Self {
|
||||
ring: ring.clone(),
|
||||
wheel: wheel.clone(),
|
||||
eng: eng.clone(),
|
||||
server_id,
|
||||
obj_ids: RefCell::new(obj_ids),
|
||||
objects: Default::default(),
|
||||
swapchain: Default::default(),
|
||||
flush_request: Default::default(),
|
||||
incoming: Default::default(),
|
||||
outgoing: Default::default(),
|
||||
owner: Default::default(),
|
||||
});
|
||||
slf.objects.set(
|
||||
WL_DISPLAY_ID.into(),
|
||||
Some(Rc::new(UsrWlDisplay {
|
||||
id: WL_DISPLAY_ID,
|
||||
con: slf.clone(),
|
||||
})),
|
||||
);
|
||||
slf.incoming.set(Some(
|
||||
slf.eng.spawn(
|
||||
Incoming {
|
||||
con: slf.clone(),
|
||||
buf: BufFdIn::new(&socket, &slf.ring),
|
||||
data: vec![],
|
||||
}
|
||||
.run(),
|
||||
),
|
||||
));
|
||||
slf.outgoing.set(Some(
|
||||
slf.eng.spawn(
|
||||
Outgoing {
|
||||
con: slf.clone(),
|
||||
buf: BufFdOut::new(&socket, &slf.ring),
|
||||
buffers: Default::default(),
|
||||
}
|
||||
.run(),
|
||||
),
|
||||
));
|
||||
Ok(slf)
|
||||
}
|
||||
|
||||
pub fn kill(&self) {
|
||||
for (_, obj) in self.objects.lock().drain() {
|
||||
if let Some(obj) = obj {
|
||||
obj.break_loops();
|
||||
}
|
||||
}
|
||||
self.incoming.take();
|
||||
self.outgoing.take();
|
||||
if let Some(owner) = self.owner.take() {
|
||||
owner.killed();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn release_id(&self, id: u32) {
|
||||
self.obj_ids.borrow_mut().release(id);
|
||||
self.objects.remove(&ObjectId::from_raw(id));
|
||||
}
|
||||
|
||||
pub fn remove_obj(&self, obj: &impl UsrObject) {
|
||||
obj.destroy();
|
||||
obj.break_loops();
|
||||
if obj.id().raw() >= MIN_SERVER_ID {
|
||||
self.objects.remove(&obj.id());
|
||||
} else {
|
||||
self.objects.set(obj.id(), None);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_object(&self, obj: Rc<dyn UsrObject>) {
|
||||
self.objects.set(obj.id(), Some(obj));
|
||||
}
|
||||
|
||||
pub fn get_registry(self: &Rc<Self>) -> Rc<UsrWlRegistry> {
|
||||
let registry = Rc::new(UsrWlRegistry {
|
||||
id: self.id(),
|
||||
con: self.clone(),
|
||||
owner: Default::default(),
|
||||
});
|
||||
self.request(wl_display::GetRegistry {
|
||||
self_id: WL_DISPLAY_ID,
|
||||
registry: registry.id,
|
||||
});
|
||||
self.objects.set(registry.id.into(), Some(registry.clone()));
|
||||
registry
|
||||
}
|
||||
|
||||
pub fn sync<F>(self: &Rc<Self>, handler: F)
|
||||
where
|
||||
F: FnOnce() + 'static,
|
||||
{
|
||||
let callback = Rc::new(UsrWlCallback::new(self, handler));
|
||||
self.request(wl_display::Sync {
|
||||
self_id: WL_DISPLAY_ID,
|
||||
callback: callback.id,
|
||||
});
|
||||
self.objects.set(callback.id.into(), Some(callback));
|
||||
}
|
||||
|
||||
pub fn parse<'a, R: RequestParser<'a>>(
|
||||
&self,
|
||||
obj: &impl UsrObject,
|
||||
mut parser: MsgParser<'_, 'a>,
|
||||
) -> Result<R, MsgParserError> {
|
||||
let res = R::parse(&mut parser)?;
|
||||
parser.eof()?;
|
||||
log::trace!(
|
||||
"Server {} -> {}@{}.{:?}",
|
||||
self.server_id,
|
||||
obj.interface().name(),
|
||||
obj.id(),
|
||||
res
|
||||
);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn request<T: EventFormatter>(self: &Rc<Self>, event: T) {
|
||||
if log::log_enabled!(log::Level::Trace) {
|
||||
log::trace!(
|
||||
"Server {} <= {}@{}.{:?}",
|
||||
self.server_id,
|
||||
event.interface().name(),
|
||||
event.id(),
|
||||
event,
|
||||
);
|
||||
}
|
||||
let mut fds = vec![];
|
||||
let mut swapchain = self.swapchain.borrow_mut();
|
||||
let mut fmt = MsgFormatter::new(&mut swapchain.cur, &mut fds);
|
||||
event.format(&mut fmt);
|
||||
fmt.write_len();
|
||||
if swapchain.cur.is_full() {
|
||||
swapchain.commit();
|
||||
}
|
||||
self.flush_request.trigger();
|
||||
}
|
||||
|
||||
pub fn id<T: From<ObjectId>>(&self) -> T {
|
||||
let id = self.obj_ids.borrow_mut().acquire();
|
||||
ObjectId::from_raw(id).into()
|
||||
}
|
||||
}
|
||||
|
||||
struct Outgoing {
|
||||
con: Rc<UsrCon>,
|
||||
buf: BufFdOut,
|
||||
buffers: VecDeque<OutBuffer>,
|
||||
}
|
||||
|
||||
impl Outgoing {
|
||||
async fn run(mut self: Self) {
|
||||
loop {
|
||||
self.con.flush_request.triggered().await;
|
||||
if let Err(e) = self.flush().await {
|
||||
log::error!(
|
||||
"Server {}: Could not process an outgoing message: {}",
|
||||
self.con.server_id,
|
||||
ErrorFmt(e)
|
||||
);
|
||||
self.con.kill();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn flush(&mut self) -> Result<(), UsrConError> {
|
||||
{
|
||||
let mut swapchain = self.con.swapchain.borrow_mut();
|
||||
swapchain.commit();
|
||||
mem::swap(&mut swapchain.pending, &mut self.buffers);
|
||||
}
|
||||
while let Some(mut cur) = self.buffers.pop_front() {
|
||||
if let Err(e) = self.buf.flush_no_timeout(&mut cur).await {
|
||||
return Err(UsrConError::Write(e));
|
||||
}
|
||||
self.con.swapchain.borrow_mut().free.push(cur);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct Incoming {
|
||||
con: Rc<UsrCon>,
|
||||
buf: BufFdIn,
|
||||
data: Vec<u32>,
|
||||
}
|
||||
|
||||
impl Incoming {
|
||||
async fn run(mut self: Self) {
|
||||
loop {
|
||||
if let Err(e) = self.handle_msg().await {
|
||||
log::error!(
|
||||
"Server {}: Could not process an incoming message: {}",
|
||||
self.con.server_id,
|
||||
ErrorFmt(e)
|
||||
);
|
||||
self.con.kill();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_msg(&mut self) -> Result<(), UsrConError> {
|
||||
let mut hdr = [0u32, 0];
|
||||
if let Err(e) = self.buf.read_full(&mut hdr[..]).await {
|
||||
return Err(UsrConError::Read(e));
|
||||
}
|
||||
let obj_id = ObjectId::from_raw(hdr[0]);
|
||||
let len = (hdr[1] >> 16) as usize;
|
||||
let event = hdr[1] & 0xffff;
|
||||
if len < 8 {
|
||||
return Err(UsrConError::MsgLenTooSmall);
|
||||
}
|
||||
if len % 4 != 0 {
|
||||
return Err(UsrConError::UnalignedMessage);
|
||||
}
|
||||
let len = len / 4 - 2;
|
||||
self.data.clear();
|
||||
self.data.reserve(len);
|
||||
let unused = self.data.split_at_spare_mut_ext().1;
|
||||
if let Err(e) = self.buf.read_full(&mut unused[..len]).await {
|
||||
return Err(UsrConError::Read(e));
|
||||
}
|
||||
unsafe {
|
||||
self.data.set_len(len);
|
||||
}
|
||||
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)?;
|
||||
}
|
||||
} else if obj_id.raw() < MIN_SERVER_ID {
|
||||
return Err(UsrConError::MissingObject(obj_id));
|
||||
} else {
|
||||
// ignore events for server-created objects that were never added to the state
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
28
src/wl_usr/usr_ifs.rs
Normal file
28
src/wl_usr/usr_ifs.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
pub mod usr_jay_compositor;
|
||||
pub mod usr_jay_output;
|
||||
pub mod usr_jay_pointer;
|
||||
pub mod usr_jay_render_ctx;
|
||||
pub mod usr_jay_screencast;
|
||||
pub mod usr_jay_workspace;
|
||||
pub mod usr_jay_workspace_watcher;
|
||||
pub mod usr_linux_buffer_params;
|
||||
pub mod usr_linux_dmabuf;
|
||||
pub mod usr_wl_buffer;
|
||||
pub mod usr_wl_callback;
|
||||
pub mod usr_wl_compositor;
|
||||
pub mod usr_wl_display;
|
||||
pub mod usr_wl_output;
|
||||
pub mod usr_wl_pointer;
|
||||
pub mod usr_wl_registry;
|
||||
pub mod usr_wl_seat;
|
||||
pub mod usr_wl_shm;
|
||||
pub mod usr_wl_shm_pool;
|
||||
pub mod usr_wl_surface;
|
||||
pub mod usr_wlr_layer_shell;
|
||||
pub mod usr_wlr_layer_surface;
|
||||
pub mod usr_wp_fractional_scale;
|
||||
pub mod usr_wp_fractional_scale_manager;
|
||||
pub mod usr_wp_viewport;
|
||||
pub mod usr_wp_viewporter;
|
||||
pub mod usr_zwlr_screencopy_frame;
|
||||
pub mod usr_zwlr_screencopy_manager;
|
||||
145
src/wl_usr/usr_ifs/usr_jay_compositor.rs
Normal file
145
src/wl_usr/usr_ifs/usr_jay_compositor.rs
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{jay_compositor::*, JayCompositorId},
|
||||
wl_usr::{
|
||||
usr_ifs::{
|
||||
usr_jay_output::UsrJayOutput, usr_jay_pointer::UsrJayPointer,
|
||||
usr_jay_render_ctx::UsrJayRenderCtx, usr_jay_screencast::UsrJayScreencast,
|
||||
usr_jay_workspace_watcher::UsrJayWorkspaceWatcher, usr_wl_output::UsrWlOutput,
|
||||
usr_wl_seat::UsrWlSeat,
|
||||
},
|
||||
usr_object::UsrObject,
|
||||
UsrCon,
|
||||
},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrJayCompositor {
|
||||
pub id: JayCompositorId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrJayCompositorOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrJayCompositorOwner {
|
||||
fn client_id(&self, ev: ClientId) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn seat(&self, ev: Seat) {
|
||||
let _ = ev;
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrJayCompositor {
|
||||
pub fn get_render_context(&self) -> Rc<UsrJayRenderCtx> {
|
||||
let rc = Rc::new(UsrJayRenderCtx {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
});
|
||||
self.con.request(GetRenderCtx {
|
||||
self_id: self.id,
|
||||
id: rc.id,
|
||||
});
|
||||
self.con.add_object(rc.clone());
|
||||
rc
|
||||
}
|
||||
|
||||
pub fn create_screencast(&self) -> Rc<UsrJayScreencast> {
|
||||
let sc = Rc::new(UsrJayScreencast {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
pending_buffers: Default::default(),
|
||||
pending_planes: Default::default(),
|
||||
pending_config: Default::default(),
|
||||
});
|
||||
self.con.request(CreateScreencast {
|
||||
self_id: self.id,
|
||||
id: sc.id,
|
||||
});
|
||||
self.con.add_object(sc.clone());
|
||||
sc
|
||||
}
|
||||
|
||||
pub fn get_output(&self, output: &UsrWlOutput) -> Rc<UsrJayOutput> {
|
||||
let jo = Rc::new(UsrJayOutput {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
});
|
||||
self.con.request(GetOutput {
|
||||
self_id: self.id,
|
||||
id: jo.id,
|
||||
output: output.id,
|
||||
});
|
||||
self.con.add_object(jo.clone());
|
||||
jo
|
||||
}
|
||||
|
||||
pub fn watch_workspaces(&self) -> Rc<UsrJayWorkspaceWatcher> {
|
||||
let ww = Rc::new(UsrJayWorkspaceWatcher {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
});
|
||||
self.con.request(WatchWorkspaces {
|
||||
self_id: self.id,
|
||||
id: ww.id,
|
||||
});
|
||||
self.con.add_object(ww.clone());
|
||||
ww
|
||||
}
|
||||
|
||||
pub fn get_pointer(&self, seat: &UsrWlSeat) -> Rc<UsrJayPointer> {
|
||||
let jp = Rc::new(UsrJayPointer {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
});
|
||||
self.con.add_object(jp.clone());
|
||||
self.con.request(GetPointer {
|
||||
self_id: self.id,
|
||||
id: jp.id,
|
||||
seat: seat.id,
|
||||
});
|
||||
jp
|
||||
}
|
||||
|
||||
fn client_id(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: ClientId = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.client_id(ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn seat(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Seat = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.seat(ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrJayCompositor, JayCompositor;
|
||||
|
||||
CLIENT_ID => client_id,
|
||||
SEAT => seat,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrJayCompositor {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
60
src/wl_usr/usr_ifs/usr_jay_output.rs
Normal file
60
src/wl_usr/usr_ifs/usr_jay_output.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{jay_output::*, JayOutputId},
|
||||
wl_usr::{usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrJayOutput {
|
||||
pub id: JayOutputId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrJayOutputOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrJayOutputOwner {
|
||||
fn linear_id(self: Rc<Self>, ev: &LinearId) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn destroyed(&self) {}
|
||||
}
|
||||
|
||||
impl UsrJayOutput {
|
||||
fn linear_id(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: LinearId = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.linear_id(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroyed(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: Destroyed = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.destroyed();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrJayOutput, JayOutput;
|
||||
|
||||
LINEAR_ID => linear_id,
|
||||
DESTROYED => destroyed,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrJayOutput {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.set(None);
|
||||
}
|
||||
}
|
||||
32
src/wl_usr/usr_ifs/usr_jay_pointer.rs
Normal file
32
src/wl_usr/usr_ifs/usr_jay_pointer.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use {
|
||||
crate::{
|
||||
cursor::KnownCursor,
|
||||
wire::{jay_pointer::*, JayPointerId},
|
||||
wl_usr::{usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrJayPointer {
|
||||
pub id: JayPointerId,
|
||||
pub con: Rc<UsrCon>,
|
||||
}
|
||||
|
||||
impl UsrJayPointer {
|
||||
pub fn set_known_cursor(&self, cursor: KnownCursor) {
|
||||
self.con.request(SetKnownCursor {
|
||||
self_id: self.id,
|
||||
idx: cursor as usize as _,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrJayPointer, JayPointer;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrJayPointer {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
}
|
||||
60
src/wl_usr/usr_ifs/usr_jay_render_ctx.rs
Normal file
60
src/wl_usr/usr_ifs/usr_jay_render_ctx.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{jay_render_ctx::*, JayRenderCtxId},
|
||||
wl_usr::{usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
uapi::OwnedFd,
|
||||
};
|
||||
|
||||
pub struct UsrJayRenderCtx {
|
||||
pub id: JayRenderCtxId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrJayRenderCtxOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrJayRenderCtxOwner {
|
||||
fn no_device(&self) {}
|
||||
fn device(&self, fd: Rc<OwnedFd>) {
|
||||
let _ = fd;
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrJayRenderCtx {
|
||||
fn no_device(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: NoDevice = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.no_device();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn device(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Device = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.device(ev.fd);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrJayRenderCtx, JayRenderCtx;
|
||||
|
||||
NO_DEVICE => no_device,
|
||||
DEVICE => device,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrJayRenderCtx {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
248
src/wl_usr/usr_ifs/usr_jay_screencast.rs
Normal file
248
src/wl_usr/usr_ifs/usr_jay_screencast.rs
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
use {
|
||||
crate::{
|
||||
format::formats,
|
||||
ifs::jay_workspace::JayWorkspace,
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
video::dmabuf::{DmaBuf, DmaBufPlane},
|
||||
wire::{jay_screencast::*, JayScreencastId},
|
||||
wl_usr::{usr_ifs::usr_jay_output::UsrJayOutput, usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::{cell::RefCell, mem, ops::DerefMut, rc::Rc},
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct UsrJayScreencast {
|
||||
pub id: JayScreencastId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrJayScreencastOwner>>>,
|
||||
|
||||
pub pending_buffers: RefCell<Vec<DmaBuf>>,
|
||||
pub pending_planes: RefCell<Vec<DmaBufPlane>>,
|
||||
|
||||
pub pending_config: RefCell<UsrJayScreencastServerConfig>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct UsrJayScreencastServerConfig {
|
||||
pub output: Option<u32>,
|
||||
pub show_all: bool,
|
||||
pub running: bool,
|
||||
pub use_linear_buffers: bool,
|
||||
pub allowed_workspaces: Vec<u32>,
|
||||
}
|
||||
|
||||
pub trait UsrJayScreencastOwner {
|
||||
fn buffers(&self, buffers: Vec<DmaBuf>) {
|
||||
let _ = buffers;
|
||||
}
|
||||
|
||||
fn ready(&self, ev: &Ready) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn destroyed(&self) {}
|
||||
|
||||
fn missed_frame(&self) {}
|
||||
|
||||
fn config(&self, config: UsrJayScreencastServerConfig) {
|
||||
let _ = config;
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrJayScreencast {
|
||||
pub fn set_output(&self, output: &UsrJayOutput) {
|
||||
self.con.request(SetOutput {
|
||||
self_id: self.id,
|
||||
output: output.id,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_allow_all_workspaces(&self, allow_all: bool) {
|
||||
self.con.request(SetAllowAllWorkspaces {
|
||||
self_id: self.id,
|
||||
allow_all: allow_all as _,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn allow_workspace(&self, ws: &JayWorkspace) {
|
||||
self.con.request(AllowWorkspace {
|
||||
self_id: self.id,
|
||||
workspace: ws.id,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn touch_allowed_workspaces(&self) {
|
||||
self.con
|
||||
.request(TouchAllowedWorkspaces { self_id: self.id });
|
||||
}
|
||||
|
||||
pub fn set_use_linear_buffers(&self, linear: bool) {
|
||||
self.con.request(SetUseLinearBuffers {
|
||||
self_id: self.id,
|
||||
use_linear: linear as _,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_running(&self, running: bool) {
|
||||
self.con.request(SetRunning {
|
||||
self_id: self.id,
|
||||
running: running as _,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn configure(&self) {
|
||||
self.con.request(Configure { self_id: self.id });
|
||||
}
|
||||
|
||||
pub fn release_buffer(&self, idx: usize) {
|
||||
self.con.request(ReleaseBuffer {
|
||||
self_id: self.id,
|
||||
idx: idx as _,
|
||||
});
|
||||
}
|
||||
|
||||
fn plane(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Plane = self.con.parse(self, parser)?;
|
||||
self.pending_planes.borrow_mut().push(DmaBufPlane {
|
||||
offset: ev.offset,
|
||||
stride: ev.stride,
|
||||
fd: ev.fd,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer(&self, parser: MsgParser<'_, '_>) -> Result<(), UsrJayScreencastError> {
|
||||
let ev: Buffer = self.con.parse(self, parser)?;
|
||||
let format = match formats().get(&ev.format) {
|
||||
Some(f) => f,
|
||||
_ => return Err(UsrJayScreencastError::UnknownFormat(ev.format)),
|
||||
};
|
||||
self.pending_buffers.borrow_mut().push(DmaBuf {
|
||||
width: ev.width,
|
||||
height: ev.height,
|
||||
format,
|
||||
modifier: ev.modifier,
|
||||
planes: mem::take(self.pending_planes.borrow_mut().deref_mut()),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffers_done(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: BuffersDone = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.buffers(mem::take(self.pending_buffers.borrow_mut().deref_mut()));
|
||||
}
|
||||
self.con.request(AckBuffers {
|
||||
self_id: self.id,
|
||||
serial: ev.serial,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ready(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Ready = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.ready(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroyed(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: Destroyed = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.destroyed();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn missed_frame(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: MissedFrame = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.missed_frame();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_output(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: ConfigOutput = self.con.parse(self, parser)?;
|
||||
self.pending_config.borrow_mut().output = Some(ev.linear_id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_allow_all_workspaces(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: ConfigAllowAllWorkspaces = self.con.parse(self, parser)?;
|
||||
self.pending_config.borrow_mut().show_all = ev.allow_all != 0;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_use_linear_buffers(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: ConfigUseLinearBuffers = self.con.parse(self, parser)?;
|
||||
self.pending_config.borrow_mut().use_linear_buffers = ev.use_linear != 0;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_running(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: ConfigRunning = self.con.parse(self, parser)?;
|
||||
self.pending_config.borrow_mut().running = ev.running != 0;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_allow_workspace(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: ConfigAllowWorkspace = self.con.parse(self, parser)?;
|
||||
self.pending_config
|
||||
.borrow_mut()
|
||||
.allowed_workspaces
|
||||
.push(ev.linear_id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_done(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: ConfigDone = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.config(mem::take(self.pending_config.borrow_mut().deref_mut()));
|
||||
}
|
||||
self.con.request(AckConfig {
|
||||
self_id: self.id,
|
||||
serial: ev.serial,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrJayScreencast, JayScreencast;
|
||||
|
||||
PLANE => plane,
|
||||
BUFFER => buffer,
|
||||
BUFFERS_DONE => buffers_done,
|
||||
READY => ready,
|
||||
DESTROYED => destroyed,
|
||||
MISSED_FRAME => missed_frame,
|
||||
CONFIG_OUTPUT => config_output,
|
||||
CONFIG_ALLOW_ALL_WORKSPACES => config_allow_all_workspaces,
|
||||
CONFIG_ALLOW_WORKSPACE => config_allow_workspace,
|
||||
CONFIG_USE_LINEAR_BUFFERS => config_use_linear_buffers,
|
||||
CONFIG_RUNNING => config_running,
|
||||
CONFIG_DONE => config_done,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrJayScreencast {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum UsrJayScreencastError {
|
||||
#[error("Parsing failed")]
|
||||
MsgParserError(#[from] MsgParserError),
|
||||
#[error("The server sent an unknown format {0}")]
|
||||
UnknownFormat(u32),
|
||||
}
|
||||
110
src/wl_usr/usr_ifs/usr_jay_workspace.rs
Normal file
110
src/wl_usr/usr_ifs/usr_jay_workspace.rs
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{jay_workspace::*, JayWorkspaceId},
|
||||
wl_usr::{usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrJayWorkspace {
|
||||
pub id: JayWorkspaceId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrJayWorkspaceOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrJayWorkspaceOwner {
|
||||
fn linear_id(self: Rc<Self>, ev: &LinearId) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn name(&self, ev: &Name) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn destroyed(&self) {}
|
||||
|
||||
fn done(&self) {}
|
||||
|
||||
fn output(self: Rc<Self>, ev: &Output) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn visible(&self, visible: bool) {
|
||||
let _ = visible;
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrJayWorkspace {
|
||||
fn linear_id(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: LinearId = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.linear_id(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Name = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.name(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroyed(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: Destroyed = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.destroyed();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn done(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: Done = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.done();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn output(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Output = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.output(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visible(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Visible = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.visible(ev.visible != 0);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrJayWorkspace, JayWorkspace;
|
||||
|
||||
LINEAR_ID => linear_id,
|
||||
NAME => name,
|
||||
DESTROYED => destroyed,
|
||||
DONE => done,
|
||||
OUTPUT => output,
|
||||
VISIBLE => visible,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrJayWorkspace {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.set(None);
|
||||
}
|
||||
}
|
||||
58
src/wl_usr/usr_ifs/usr_jay_workspace_watcher.rs
Normal file
58
src/wl_usr/usr_ifs/usr_jay_workspace_watcher.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{jay_workspace_watcher::*, JayWorkspaceWatcherId},
|
||||
wl_usr::{usr_ifs::usr_jay_workspace::UsrJayWorkspace, usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::{ops::Deref, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrJayWorkspaceWatcher {
|
||||
pub id: JayWorkspaceWatcherId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrJayWorkspaceWatcherOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrJayWorkspaceWatcherOwner {
|
||||
fn new(self: Rc<Self>, ev: Rc<UsrJayWorkspace>, linear_id: u32) {
|
||||
let _ = linear_id;
|
||||
ev.con.remove_obj(ev.deref());
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrJayWorkspaceWatcher {
|
||||
fn new(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: New = self.con.parse(self, parser)?;
|
||||
let jw = Rc::new(UsrJayWorkspace {
|
||||
id: ev.id,
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
});
|
||||
self.con.add_object(jw.clone());
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.new(jw, ev.linear_id);
|
||||
} else {
|
||||
self.con.remove_obj(jw.deref());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrJayWorkspaceWatcher, JayWorkspaceWatcher;
|
||||
|
||||
NEW => new,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrJayWorkspaceWatcher {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.set(None);
|
||||
}
|
||||
}
|
||||
90
src/wl_usr/usr_ifs/usr_linux_buffer_params.rs
Normal file
90
src/wl_usr/usr_ifs/usr_linux_buffer_params.rs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
video::dmabuf::DmaBuf,
|
||||
wire::{zwp_linux_buffer_params_v1::*, ZwpLinuxBufferParamsV1Id},
|
||||
wl_usr::{usr_ifs::usr_wl_buffer::UsrWlBuffer, usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::{ops::Deref, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrLinuxBufferParams {
|
||||
pub id: ZwpLinuxBufferParamsV1Id,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrLinuxBufferParamsOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrLinuxBufferParamsOwner {
|
||||
fn created(&self, buffer: Rc<UsrWlBuffer>) {
|
||||
buffer.con.remove_obj(buffer.deref());
|
||||
}
|
||||
|
||||
fn failed(&self) {}
|
||||
}
|
||||
|
||||
impl UsrLinuxBufferParams {
|
||||
pub fn create(&self, buf: &DmaBuf) {
|
||||
for (idx, plane) in buf.planes.iter().enumerate() {
|
||||
self.con.request(Add {
|
||||
self_id: self.id,
|
||||
fd: plane.fd.clone(),
|
||||
plane_idx: idx as _,
|
||||
offset: plane.offset,
|
||||
stride: plane.stride,
|
||||
modifier_hi: (buf.modifier >> 32) as _,
|
||||
modifier_lo: buf.modifier as _,
|
||||
});
|
||||
}
|
||||
self.con.request(Create {
|
||||
self_id: self.id,
|
||||
width: buf.width,
|
||||
height: buf.height,
|
||||
format: buf.format.drm,
|
||||
flags: 0,
|
||||
});
|
||||
}
|
||||
|
||||
fn created(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Created = self.con.parse(self, parser)?;
|
||||
let buffer = Rc::new(UsrWlBuffer {
|
||||
id: ev.buffer,
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
});
|
||||
self.con.add_object(buffer.clone());
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.created(buffer);
|
||||
} else {
|
||||
self.con.remove_obj(buffer.deref());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn failed(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: Failed = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.failed();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrLinuxBufferParams, ZwpLinuxBufferParamsV1;
|
||||
|
||||
CREATED => created,
|
||||
FAILED => failed,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrLinuxBufferParams {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
81
src/wl_usr/usr_ifs/usr_linux_dmabuf.rs
Normal file
81
src/wl_usr/usr_ifs/usr_linux_dmabuf.rs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
use {
|
||||
crate::{
|
||||
format::{formats, Format},
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{
|
||||
zwp_linux_dmabuf_v1::{self, *},
|
||||
ZwpLinuxDmabufV1Id,
|
||||
},
|
||||
wl_usr::{
|
||||
usr_ifs::usr_linux_buffer_params::UsrLinuxBufferParams, usr_object::UsrObject, UsrCon,
|
||||
},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrLinuxDmabuf {
|
||||
pub id: ZwpLinuxDmabufV1Id,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrLinuxDmabufOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrLinuxDmabufOwner {
|
||||
fn modifier(&self, format: &'static Format, modifier: u64) {
|
||||
let _ = format;
|
||||
let _ = modifier;
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrLinuxDmabuf {
|
||||
pub fn create_params(&self) -> Rc<UsrLinuxBufferParams> {
|
||||
let params = Rc::new(UsrLinuxBufferParams {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
});
|
||||
self.con.request(CreateParams {
|
||||
self_id: self.id,
|
||||
params_id: params.id,
|
||||
});
|
||||
self.con.add_object(params.clone());
|
||||
params
|
||||
}
|
||||
|
||||
fn format(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: zwp_linux_dmabuf_v1::Format = self.con.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn modifier(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Modifier = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
if let Some(format) = formats().get(&ev.format) {
|
||||
owner.modifier(
|
||||
*format,
|
||||
(ev.modifier_hi as u64) << 32 | (ev.modifier_lo as u64),
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrLinuxDmabuf, ZwpLinuxDmabufV1;
|
||||
|
||||
FORMAT => format,
|
||||
MODIFIER => modifier,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrLinuxDmabuf {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
47
src/wl_usr/usr_ifs/usr_wl_buffer.rs
Normal file
47
src/wl_usr/usr_ifs/usr_wl_buffer.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{wl_buffer::*, WlBufferId},
|
||||
wl_usr::{usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrWlBuffer {
|
||||
pub id: WlBufferId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrWlBufferOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrWlBufferOwner {
|
||||
fn release(&self) {}
|
||||
}
|
||||
|
||||
impl UsrWlBuffer {
|
||||
fn release(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: Release = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.release();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWlBuffer, WlBuffer;
|
||||
|
||||
RELEASE => release,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlBuffer {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
52
src/wl_usr/usr_ifs/usr_wl_callback.rs
Normal file
52
src/wl_usr/usr_ifs/usr_wl_callback.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::buffd::{MsgParser, MsgParserError},
|
||||
wire::{wl_callback::*, WlCallbackId},
|
||||
wl_usr::{usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::{cell::Cell, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrWlCallback {
|
||||
pub id: WlCallbackId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub handler: Cell<Option<Box<dyn FnOnce()>>>,
|
||||
}
|
||||
|
||||
impl UsrWlCallback {
|
||||
pub fn new<F>(con: &Rc<UsrCon>, handler: F) -> Self
|
||||
where
|
||||
F: FnOnce() + 'static,
|
||||
{
|
||||
Self {
|
||||
id: con.id(),
|
||||
con: con.clone(),
|
||||
handler: Cell::new(Some(Box::new(handler))),
|
||||
}
|
||||
}
|
||||
|
||||
fn done(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: Done = self.con.parse(self, parser)?;
|
||||
if let Some(handler) = self.handler.take() {
|
||||
handler();
|
||||
}
|
||||
self.con.remove_obj(self);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWlCallback, WlCallback;
|
||||
|
||||
DONE => done,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlCallback {
|
||||
fn destroy(&self) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.handler.take();
|
||||
}
|
||||
}
|
||||
37
src/wl_usr/usr_ifs/usr_wl_compositor.rs
Normal file
37
src/wl_usr/usr_ifs/usr_wl_compositor.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
use {
|
||||
crate::{
|
||||
wire::{wl_compositor::CreateSurface, WlCompositorId},
|
||||
wl_usr::{usr_ifs::usr_wl_surface::UsrWlSurface, usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrWlCompositor {
|
||||
pub id: WlCompositorId,
|
||||
pub con: Rc<UsrCon>,
|
||||
}
|
||||
|
||||
impl UsrWlCompositor {
|
||||
pub fn create_surface(&self) -> Rc<UsrWlSurface> {
|
||||
let sfc = Rc::new(UsrWlSurface {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
});
|
||||
self.con.request(CreateSurface {
|
||||
self_id: self.id,
|
||||
id: sfc.id,
|
||||
});
|
||||
self.con.add_object(sfc.clone());
|
||||
sfc
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWlCompositor, WlCompositor;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlCompositor {
|
||||
fn destroy(&self) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
47
src/wl_usr/usr_ifs/usr_wl_display.rs
Normal file
47
src/wl_usr/usr_ifs/usr_wl_display.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::buffd::{MsgParser, MsgParserError},
|
||||
wire::{wl_display::*, WlDisplayId},
|
||||
wl_usr::{usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrWlDisplay {
|
||||
pub id: WlDisplayId,
|
||||
pub con: Rc<UsrCon>,
|
||||
}
|
||||
|
||||
impl UsrWlDisplay {
|
||||
fn error(&self, parser: MsgParser<'_, '_>) -> Result<(), UsrWlDisplayError> {
|
||||
let ev: Error = self.con.parse(self, parser)?;
|
||||
Err(UsrWlDisplayError::ServerError(ev.message.to_owned()))
|
||||
}
|
||||
|
||||
fn delete_id(&self, parser: MsgParser<'_, '_>) -> Result<(), UsrWlDisplayError> {
|
||||
let ev: DeleteId = self.con.parse(self, parser)?;
|
||||
self.con.release_id(ev.id);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum UsrWlDisplayError {
|
||||
#[error("The server emitted an error: {0}")]
|
||||
ServerError(String),
|
||||
#[error(transparent)]
|
||||
MsgParserError(#[from] MsgParserError),
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWlDisplay, WlDisplay;
|
||||
|
||||
ERROR => error,
|
||||
DELETE_ID => delete_id,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlDisplay {
|
||||
fn destroy(&self) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
112
src/wl_usr/usr_ifs/usr_wl_output.rs
Normal file
112
src/wl_usr/usr_ifs/usr_wl_output.rs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{wl_output::*, WlOutputId},
|
||||
wl_usr::{usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrWlOutput {
|
||||
pub id: WlOutputId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrWlOutputOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrWlOutputOwner {
|
||||
fn geometry(&self, ev: &Geometry) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn mode(&self, ev: &Mode) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn done(&self) {}
|
||||
|
||||
fn scale(&self, ev: &Scale) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn name(&self, ev: &Name) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn description(&self, ev: &Description) {
|
||||
let _ = ev;
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrWlOutput {
|
||||
fn geometry(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Geometry = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.geometry(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mode(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Mode = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.mode(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn done(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: Done = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.done();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn scale(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Scale = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.scale(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Name = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.name(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn description(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Description = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.description(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWlOutput, WlOutput;
|
||||
|
||||
GEOMETRY => geometry,
|
||||
MODE => mode,
|
||||
DONE => done,
|
||||
SCALE => scale,
|
||||
NAME => name,
|
||||
DESCRIPTION => description,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlOutput {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Release { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.set(None);
|
||||
}
|
||||
}
|
||||
164
src/wl_usr/usr_ifs/usr_wl_pointer.rs
Normal file
164
src/wl_usr/usr_ifs/usr_wl_pointer.rs
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
use {
|
||||
crate::{
|
||||
ifs::wl_seat::wl_pointer::PendingScroll,
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{wl_pointer::*, WlPointerId},
|
||||
wl_usr::{usr_ifs::usr_wl_surface::UsrWlSurface, usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::{cell::Cell, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrWlPointer {
|
||||
pub id: WlPointerId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrWlPointerOwner>>>,
|
||||
pub any_scroll_events: Cell<bool>,
|
||||
pub pending_scroll: PendingScroll,
|
||||
}
|
||||
|
||||
pub trait UsrWlPointerOwner {
|
||||
fn enter(&self, ev: &Enter) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn leave(&self, ev: &Leave) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn motion(&self, ev: &Motion) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn button(&self, ev: &Button) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn scroll(&self, ps: &PendingScroll) {
|
||||
let _ = ps;
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrWlPointer {
|
||||
pub fn set_cursor(&self, serial: u32, cursor: &UsrWlSurface, hot_x: i32, hot_y: i32) {
|
||||
self.con.request(SetCursor {
|
||||
self_id: self.id,
|
||||
serial,
|
||||
surface: cursor.id,
|
||||
hotspot_x: hot_x,
|
||||
hotspot_y: hot_y,
|
||||
});
|
||||
}
|
||||
|
||||
fn enter(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Enter = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.enter(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn leave(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Leave = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.leave(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn motion(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Motion = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.motion(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn button(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Button = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.button(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn axis(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Axis = self.con.parse(self, parser)?;
|
||||
self.pending_scroll.time_usec.set(ev.time as u64 * 1000);
|
||||
if ev.axis < 2 {
|
||||
self.pending_scroll.px[ev.axis as usize].set(Some(ev.value));
|
||||
}
|
||||
self.any_scroll_events.set(true);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn frame(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: Frame = self.con.parse(self, parser)?;
|
||||
if self.any_scroll_events.take() {
|
||||
let pe = self.pending_scroll.take();
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.scroll(&pe);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn axis_source(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: AxisSource = self.con.parse(self, parser)?;
|
||||
self.pending_scroll.source.set(Some(ev.axis_source));
|
||||
self.any_scroll_events.set(true);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn axis_stop(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: AxisStop = self.con.parse(self, parser)?;
|
||||
self.pending_scroll.time_usec.set(ev.time as u64 * 1000);
|
||||
if ev.axis < 2 {
|
||||
self.pending_scroll.stop[ev.axis as usize].set(true);
|
||||
}
|
||||
self.any_scroll_events.set(true);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn axis_discrete(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: AxisDiscrete = self.con.parse(self, parser)?;
|
||||
self.any_scroll_events.set(true);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn axis_value120(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: AxisValue120 = self.con.parse(self, parser)?;
|
||||
if ev.axis < 2 {
|
||||
self.pending_scroll.v120[ev.axis as usize].set(Some(ev.value120));
|
||||
}
|
||||
self.any_scroll_events.set(true);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWlPointer, WlPointer;
|
||||
|
||||
ENTER => enter,
|
||||
LEAVE => leave,
|
||||
MOTION => motion,
|
||||
BUTTON => button,
|
||||
AXIS => axis,
|
||||
FRAME => frame,
|
||||
AXIS_SOURCE => axis_source,
|
||||
AXIS_STOP => axis_stop,
|
||||
AXIS_DISCRETE => axis_discrete,
|
||||
AXIS_VALUE120 => axis_value120,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlPointer {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Release { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
74
src/wl_usr/usr_ifs/usr_wl_registry.rs
Normal file
74
src/wl_usr/usr_ifs/usr_wl_registry.rs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{wl_registry::*, WlRegistryId},
|
||||
wl_usr::{usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrWlRegistry {
|
||||
pub id: WlRegistryId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrWlRegistryOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrWlRegistryOwner {
|
||||
fn global(self: Rc<Self>, name: u32, interface: &str, version: u32) {
|
||||
let _ = name;
|
||||
let _ = interface;
|
||||
let _ = version;
|
||||
}
|
||||
|
||||
fn global_remove(&self, name: u32) {
|
||||
let _ = name;
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrWlRegistry {
|
||||
pub fn request_bind(&self, name: u32, version: u32, obj: &dyn UsrObject) {
|
||||
self.con.request(Bind {
|
||||
self_id: self.id,
|
||||
name,
|
||||
interface: obj.interface().name(),
|
||||
version,
|
||||
id: obj.id(),
|
||||
});
|
||||
}
|
||||
|
||||
fn global(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Global = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.global(ev.name, ev.interface, ev.version);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn global_remove(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: GlobalRemove = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.global_remove(ev.name);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWlRegistry, WlRegistry;
|
||||
|
||||
GLOBAL => global,
|
||||
GLOBAL_REMOVE => global_remove,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlRegistry {
|
||||
fn destroy(&self) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.set(None);
|
||||
}
|
||||
}
|
||||
78
src/wl_usr/usr_ifs/usr_wl_seat.rs
Normal file
78
src/wl_usr/usr_ifs/usr_wl_seat.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{wl_seat::*, WlSeatId},
|
||||
wl_usr::{usr_ifs::usr_wl_pointer::UsrWlPointer, usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::{cell::Cell, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrWlSeat {
|
||||
pub id: WlSeatId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrWlSeatOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrWlSeatOwner {
|
||||
fn capabilities(self: Rc<Self>, value: u32) {
|
||||
let _ = value;
|
||||
}
|
||||
|
||||
fn name(&self, name: &str) {
|
||||
let _ = name;
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrWlSeat {
|
||||
pub fn get_pointer(&self) -> Rc<UsrWlPointer> {
|
||||
let ptr = Rc::new(UsrWlPointer {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
any_scroll_events: Cell::new(false),
|
||||
pending_scroll: Default::default(),
|
||||
});
|
||||
self.con.add_object(ptr.clone());
|
||||
self.con.request(GetPointer {
|
||||
self_id: self.id,
|
||||
id: ptr.id,
|
||||
});
|
||||
ptr
|
||||
}
|
||||
|
||||
fn capabilities(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Capabilities = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.capabilities(ev.capabilities);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Name = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.name(ev.name);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWlSeat, WlSeat;
|
||||
|
||||
CAPABILITIES => capabilities,
|
||||
NAME => name,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlSeat {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Release { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
57
src/wl_usr/usr_ifs/usr_wl_shm.rs
Normal file
57
src/wl_usr/usr_ifs/usr_wl_shm.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
use {
|
||||
crate::{
|
||||
format::{formats, map_wayland_format_id},
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
copyhashmap::CopyHashMap,
|
||||
},
|
||||
wire::{wl_shm::*, WlShmId},
|
||||
wl_usr::{usr_ifs::usr_wl_shm_pool::UsrWlShmPool, usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
uapi::OwnedFd,
|
||||
};
|
||||
|
||||
pub struct UsrWlShm {
|
||||
pub id: WlShmId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub formats: CopyHashMap<u32, &'static crate::format::Format>,
|
||||
}
|
||||
|
||||
impl UsrWlShm {
|
||||
pub fn create_pool(&self, fd: &Rc<OwnedFd>, size: i32) -> Rc<UsrWlShmPool> {
|
||||
let pool = Rc::new(UsrWlShmPool {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
});
|
||||
self.con.request(CreatePool {
|
||||
self_id: self.id,
|
||||
id: pool.id,
|
||||
fd: fd.clone(),
|
||||
size,
|
||||
});
|
||||
self.con.add_object(pool.clone());
|
||||
pool
|
||||
}
|
||||
|
||||
fn format(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Format = self.con.parse(self, parser)?;
|
||||
let format = map_wayland_format_id(ev.format);
|
||||
if let Some(format) = formats().get(&format) {
|
||||
self.formats.set(format.drm, *format);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWlShm, WlShm;
|
||||
|
||||
FORMAT => format,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlShm {
|
||||
fn destroy(&self) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
32
src/wl_usr/usr_ifs/usr_wl_shm_pool.rs
Normal file
32
src/wl_usr/usr_ifs/usr_wl_shm_pool.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use {
|
||||
crate::{
|
||||
wire::{wl_shm_pool::*, WlShmPoolId},
|
||||
wl_usr::{usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrWlShmPool {
|
||||
pub id: WlShmPoolId,
|
||||
pub con: Rc<UsrCon>,
|
||||
}
|
||||
|
||||
impl UsrWlShmPool {
|
||||
#[allow(dead_code)]
|
||||
pub fn resize(&self, size: i32) {
|
||||
self.con.request(Resize {
|
||||
self_id: self.id,
|
||||
size,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWlShmPool, WlShmPool;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlShmPool {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
}
|
||||
67
src/wl_usr/usr_ifs/usr_wl_surface.rs
Normal file
67
src/wl_usr/usr_ifs/usr_wl_surface.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::buffd::{MsgParser, MsgParserError},
|
||||
wire::{wl_surface::*, WlSurfaceId},
|
||||
wl_usr::{
|
||||
usr_ifs::{usr_wl_buffer::UsrWlBuffer, usr_wl_callback::UsrWlCallback},
|
||||
usr_object::UsrObject,
|
||||
UsrCon,
|
||||
},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrWlSurface {
|
||||
pub id: WlSurfaceId,
|
||||
pub con: Rc<UsrCon>,
|
||||
}
|
||||
|
||||
impl UsrWlSurface {
|
||||
pub fn attach(&self, buffer: &UsrWlBuffer) {
|
||||
self.con.request(Attach {
|
||||
self_id: self.id,
|
||||
buffer: buffer.id,
|
||||
x: 0,
|
||||
y: 0,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn frame<F>(&self, f: F)
|
||||
where
|
||||
F: FnOnce() + 'static,
|
||||
{
|
||||
let cb = Rc::new(UsrWlCallback::new(&self.con, f));
|
||||
self.con.request(Frame {
|
||||
self_id: self.id,
|
||||
callback: cb.id,
|
||||
});
|
||||
self.con.add_object(cb);
|
||||
}
|
||||
|
||||
pub fn commit(&self) {
|
||||
self.con.request(Commit { self_id: self.id });
|
||||
}
|
||||
|
||||
fn enter(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: Enter = self.con.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn leave(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: Leave = self.con.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWlSurface, WlSurface;
|
||||
|
||||
ENTER => enter,
|
||||
LEAVE => leave,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlSurface {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
}
|
||||
54
src/wl_usr/usr_ifs/usr_wlr_layer_shell.rs
Normal file
54
src/wl_usr/usr_ifs/usr_wlr_layer_shell.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
use {
|
||||
crate::{
|
||||
wire::{zwlr_layer_shell_v1::*, ZwlrLayerShellV1Id},
|
||||
wl_usr::{
|
||||
usr_ifs::{
|
||||
usr_wl_output::UsrWlOutput, usr_wl_surface::UsrWlSurface,
|
||||
usr_wlr_layer_surface::UsrWlrLayerSurface,
|
||||
},
|
||||
usr_object::UsrObject,
|
||||
UsrCon,
|
||||
},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrWlrLayerShell {
|
||||
pub id: ZwlrLayerShellV1Id,
|
||||
pub con: Rc<UsrCon>,
|
||||
}
|
||||
|
||||
impl UsrWlrLayerShell {
|
||||
pub fn get_layer_surface(
|
||||
&self,
|
||||
surface: &UsrWlSurface,
|
||||
output: &UsrWlOutput,
|
||||
layer: u32,
|
||||
) -> Rc<UsrWlrLayerSurface> {
|
||||
let sfc = Rc::new(UsrWlrLayerSurface {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
});
|
||||
self.con.add_object(sfc.clone());
|
||||
self.con.request(GetLayerSurface {
|
||||
self_id: self.id,
|
||||
id: sfc.id,
|
||||
surface: surface.id,
|
||||
output: output.id,
|
||||
layer,
|
||||
namespace: "",
|
||||
});
|
||||
sfc
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWlrLayerShell, ZwlrLayerShellV1;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlrLayerShell {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id })
|
||||
}
|
||||
}
|
||||
86
src/wl_usr/usr_ifs/usr_wlr_layer_surface.rs
Normal file
86
src/wl_usr/usr_ifs/usr_wlr_layer_surface.rs
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{zwlr_layer_surface_v1::*, ZwlrLayerSurfaceV1Id},
|
||||
wl_usr::{usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrWlrLayerSurface {
|
||||
pub id: ZwlrLayerSurfaceV1Id,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrWlrLayerSurfaceOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrWlrLayerSurfaceOwner {
|
||||
fn configure(&self, ev: &Configure) {
|
||||
let _ = ev;
|
||||
}
|
||||
|
||||
fn closed(&self) {}
|
||||
}
|
||||
|
||||
impl UsrWlrLayerSurface {
|
||||
pub fn set_size(&self, width: i32, height: i32) {
|
||||
self.con.request(SetSize {
|
||||
self_id: self.id,
|
||||
width: width as _,
|
||||
height: height as _,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_keyboard_interactivity(&self, ki: u32) {
|
||||
self.con.request(SetKeyboardInteractivity {
|
||||
self_id: self.id,
|
||||
keyboard_interactivity: ki,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_layer(&self, layer: u32) {
|
||||
self.con.request(SetLayer {
|
||||
self_id: self.id,
|
||||
layer,
|
||||
});
|
||||
}
|
||||
|
||||
fn configure(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Configure = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.configure(&ev);
|
||||
}
|
||||
self.con.request(AckConfigure {
|
||||
self_id: self.id,
|
||||
serial: ev.serial,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn closed(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: Closed = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.closed();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWlrLayerSurface, ZwlrLayerSurfaceV1;
|
||||
|
||||
CONFIGURE => configure,
|
||||
CLOSED => closed,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlrLayerSurface {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
49
src/wl_usr/usr_ifs/usr_wp_fractional_scale.rs
Normal file
49
src/wl_usr/usr_ifs/usr_wp_fractional_scale.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{wp_fractional_scale_v1::*, WpFractionalScaleV1Id},
|
||||
wl_usr::{usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrWpFractionalScale {
|
||||
pub id: WpFractionalScaleV1Id,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrWpFractionalScaleOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrWpFractionalScaleOwner {
|
||||
fn preferred_scale(self: Rc<Self>, ev: &PreferredScale) {
|
||||
let _ = ev;
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrWpFractionalScale {
|
||||
fn preferred_scale(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: PreferredScale = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.preferred_scale(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWpFractionalScale, WpFractionalScaleV1;
|
||||
|
||||
PREFERRED_SCALE => preferred_scale,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWpFractionalScale {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
45
src/wl_usr/usr_ifs/usr_wp_fractional_scale_manager.rs
Normal file
45
src/wl_usr/usr_ifs/usr_wp_fractional_scale_manager.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
use {
|
||||
crate::{
|
||||
wire::{wp_fractional_scale_manager_v1::*, WpFractionalScaleManagerV1Id},
|
||||
wl_usr::{
|
||||
usr_ifs::{
|
||||
usr_wl_surface::UsrWlSurface, usr_wp_fractional_scale::UsrWpFractionalScale,
|
||||
},
|
||||
usr_object::UsrObject,
|
||||
UsrCon,
|
||||
},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrWpFractionalScaleManager {
|
||||
pub id: WpFractionalScaleManagerV1Id,
|
||||
pub con: Rc<UsrCon>,
|
||||
}
|
||||
|
||||
impl UsrWpFractionalScaleManager {
|
||||
pub fn get_fractional_scale(&self, surface: &UsrWlSurface) -> Rc<UsrWpFractionalScale> {
|
||||
let fs = Rc::new(UsrWpFractionalScale {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
});
|
||||
self.con.add_object(fs.clone());
|
||||
self.con.request(GetFractionalScale {
|
||||
self_id: self.id,
|
||||
id: fs.id,
|
||||
surface: surface.id,
|
||||
});
|
||||
fs
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWpFractionalScaleManager, WpFractionalScaleManagerV1;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWpFractionalScaleManager {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id })
|
||||
}
|
||||
}
|
||||
43
src/wl_usr/usr_ifs/usr_wp_viewport.rs
Normal file
43
src/wl_usr/usr_ifs/usr_wp_viewport.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
use {
|
||||
crate::{
|
||||
fixed::Fixed,
|
||||
wire::{wp_viewport::*, WpViewportId},
|
||||
wl_usr::{usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrWpViewport {
|
||||
pub id: WpViewportId,
|
||||
pub con: Rc<UsrCon>,
|
||||
}
|
||||
|
||||
impl UsrWpViewport {
|
||||
pub fn set_source(&self, x: Fixed, y: Fixed, width: Fixed, height: Fixed) {
|
||||
self.con.request(SetSource {
|
||||
self_id: self.id,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_destination(&self, width: i32, height: i32) {
|
||||
self.con.request(SetDestination {
|
||||
self_id: self.id,
|
||||
width,
|
||||
height,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWpViewport, WpViewport;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWpViewport {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
}
|
||||
42
src/wl_usr/usr_ifs/usr_wp_viewporter.rs
Normal file
42
src/wl_usr/usr_ifs/usr_wp_viewporter.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
use {
|
||||
crate::{
|
||||
wire::{wp_viewporter::*, WpViewporterId},
|
||||
wl_usr::{
|
||||
usr_ifs::{usr_wl_surface::UsrWlSurface, usr_wp_viewport::UsrWpViewport},
|
||||
usr_object::UsrObject,
|
||||
UsrCon,
|
||||
},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrWpViewporter {
|
||||
pub id: WpViewporterId,
|
||||
pub con: Rc<UsrCon>,
|
||||
}
|
||||
|
||||
impl UsrWpViewporter {
|
||||
pub fn get_viewport(&self, surface: &UsrWlSurface) -> Rc<UsrWpViewport> {
|
||||
let wv = Rc::new(UsrWpViewport {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
});
|
||||
self.con.add_object(wv.clone());
|
||||
self.con.request(GetViewport {
|
||||
self_id: self.id,
|
||||
id: wv.id,
|
||||
surface: surface.id,
|
||||
});
|
||||
wv
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrWpViewporter, WpViewporter;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWpViewporter {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
}
|
||||
138
src/wl_usr/usr_ifs/usr_zwlr_screencopy_frame.rs
Normal file
138
src/wl_usr/usr_ifs/usr_zwlr_screencopy_frame.rs
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{zwlr_screencopy_frame_v1::*, ZwlrScreencopyFrameV1Id},
|
||||
wl_usr::{usr_ifs::usr_wl_buffer::UsrWlBuffer, usr_object::UsrObject, UsrCon},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UsrZwlrScreencopyFrame {
|
||||
pub id: ZwlrScreencopyFrameV1Id,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrZwlrScreencopyFrameOwner>>>,
|
||||
}
|
||||
|
||||
pub trait UsrZwlrScreencopyFrameOwner {
|
||||
fn buffer(&self, buffer: &Buffer) {
|
||||
let _ = buffer;
|
||||
}
|
||||
|
||||
fn flags(&self, flags: &Flags) {
|
||||
let _ = flags;
|
||||
}
|
||||
|
||||
fn ready(&self, ready: &Ready) {
|
||||
let _ = ready;
|
||||
}
|
||||
|
||||
fn failed(&self) {}
|
||||
|
||||
fn damage(&self, damage: &Damage) {
|
||||
let _ = damage;
|
||||
}
|
||||
|
||||
fn linux_dmabuf(&self, dmabuf: &LinuxDmabuf) {
|
||||
let _ = dmabuf;
|
||||
}
|
||||
|
||||
fn buffer_done(&self) {}
|
||||
}
|
||||
|
||||
impl UsrZwlrScreencopyFrame {
|
||||
pub fn copy(&self, buffer: &UsrWlBuffer) {
|
||||
self.con.request(Copy {
|
||||
self_id: self.id,
|
||||
buffer: buffer.id,
|
||||
});
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn copy_with_damage(&self, buffer: &UsrWlBuffer) {
|
||||
self.con.request(CopyWithDamage {
|
||||
self_id: self.id,
|
||||
buffer: buffer.id,
|
||||
});
|
||||
}
|
||||
|
||||
fn buffer(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Buffer = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.buffer(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn flags(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Flags = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.flags(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ready(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Ready = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.ready(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn failed(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: Failed = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.failed();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn damage(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: Damage = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.damage(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn linux_dmabuf(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let ev: LinuxDmabuf = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.linux_dmabuf(&ev);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_done(&self, parser: MsgParser<'_, '_>) -> Result<(), MsgParserError> {
|
||||
let _ev: BufferDone = self.con.parse(self, parser)?;
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.buffer_done();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrZwlrScreencopyFrame, ZwlrScreencopyFrameV1;
|
||||
|
||||
BUFFER => buffer,
|
||||
FLAGS => flags,
|
||||
READY => ready,
|
||||
FAILED => failed,
|
||||
DAMAGE => damage,
|
||||
LINUX_DMABUF => linux_dmabuf,
|
||||
BUFFER_DONE => buffer_done,
|
||||
}
|
||||
|
||||
impl UsrObject for UsrZwlrScreencopyFrame {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
45
src/wl_usr/usr_ifs/usr_zwlr_screencopy_manager.rs
Normal file
45
src/wl_usr/usr_ifs/usr_zwlr_screencopy_manager.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
use {
|
||||
crate::{
|
||||
wire::{zwlr_screencopy_manager_v1::*, ZwlrScreencopyManagerV1Id},
|
||||
wl_usr::{
|
||||
usr_ifs::{
|
||||
usr_wl_output::UsrWlOutput, usr_zwlr_screencopy_frame::UsrZwlrScreencopyFrame,
|
||||
},
|
||||
usr_object::UsrObject,
|
||||
UsrCon,
|
||||
},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
pub struct UsrZwlrScreencopyManager {
|
||||
pub id: ZwlrScreencopyManagerV1Id,
|
||||
pub con: Rc<UsrCon>,
|
||||
}
|
||||
|
||||
impl UsrZwlrScreencopyManager {
|
||||
pub fn capture_output(&self, output: &UsrWlOutput) -> Rc<UsrZwlrScreencopyFrame> {
|
||||
let frame = Rc::new(UsrZwlrScreencopyFrame {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
});
|
||||
self.con.request(CaptureOutput {
|
||||
self_id: self.id,
|
||||
frame: frame.id,
|
||||
overlay_cursor: 0,
|
||||
output: output.id,
|
||||
});
|
||||
self.con.add_object(frame.clone());
|
||||
frame
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
UsrZwlrScreencopyManager, ZwlrScreencopyManagerV1;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrZwlrScreencopyManager {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
}
|
||||
44
src/wl_usr/usr_object.rs
Normal file
44
src/wl_usr/usr_object.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
use {
|
||||
crate::{
|
||||
object::{Interface, ObjectId},
|
||||
utils::buffd::MsgParser,
|
||||
},
|
||||
std::rc::Rc,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum UsrObjectErrorType {
|
||||
#[error("Could not process a `{event}` event")]
|
||||
EventError {
|
||||
event: &'static str,
|
||||
#[source]
|
||||
error: Box<dyn std::error::Error>,
|
||||
},
|
||||
#[error("Unknown event {event}")]
|
||||
UnknownEventError { event: u32 },
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("An error occurred in a `{}`", .interface.name())]
|
||||
pub struct UsrObjectError {
|
||||
pub interface: Interface,
|
||||
#[source]
|
||||
pub ty: UsrObjectErrorType,
|
||||
}
|
||||
|
||||
pub trait UsrObjectBase {
|
||||
fn id(&self) -> ObjectId;
|
||||
fn handle_event(
|
||||
self: Rc<Self>,
|
||||
event: u32,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), UsrObjectError>;
|
||||
fn interface(&self) -> Interface;
|
||||
}
|
||||
|
||||
pub trait UsrObject: UsrObjectBase + 'static {
|
||||
fn destroy(&self);
|
||||
|
||||
fn break_loops(&self) {}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue