wl_usr: add additional interfaces
This commit is contained in:
parent
56290d5547
commit
ce30901093
16 changed files with 1062 additions and 23 deletions
|
|
@ -72,7 +72,33 @@ impl WpCursorShapeDeviceV1RequestHandler for WpCursorShapeDeviceV1 {
|
|||
}
|
||||
|
||||
fn set_shape(&self, req: SetShape, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let cursor = match req.shape {
|
||||
let cursor = KnownCursor::from_shape(req.shape, self.version)
|
||||
.ok_or(WpCursorShapeDeviceV1Error::UnknownShape(req.shape))?;
|
||||
let tablet_tool;
|
||||
let (node_client_id, user) = match &self.cursor_user {
|
||||
CursorShapeCursorUser::Seat(s) => match s.pointer_node() {
|
||||
Some(n) => (n.node_client_id(), s.pointer_cursor()),
|
||||
_ => return Ok(()),
|
||||
},
|
||||
CursorShapeCursorUser::TabletTool(t) => match t.get() {
|
||||
Some(t) => {
|
||||
tablet_tool = t;
|
||||
(tablet_tool.node().node_client_id(), tablet_tool.cursor())
|
||||
}
|
||||
_ => return Ok(()),
|
||||
},
|
||||
};
|
||||
if node_client_id != Some(self.client.id) {
|
||||
return Ok(());
|
||||
}
|
||||
user.set_known(cursor);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl KnownCursor {
|
||||
pub fn from_shape(shape: u32, version: Version) -> Option<Self> {
|
||||
let cursor = match shape {
|
||||
DEFAULT => KnownCursor::Default,
|
||||
CONTEXT_MENU => KnownCursor::ContextMenu,
|
||||
HELP => KnownCursor::Help,
|
||||
|
|
@ -107,29 +133,52 @@ impl WpCursorShapeDeviceV1RequestHandler for WpCursorShapeDeviceV1 {
|
|||
ALL_SCROLL => KnownCursor::AllScroll,
|
||||
ZOOM_IN => KnownCursor::ZoomIn,
|
||||
ZOOM_OUT => KnownCursor::ZoomOut,
|
||||
DND_ASK if self.version >= V2 => KnownCursor::DndAsk,
|
||||
ALL_RESIZE if self.version >= V2 => KnownCursor::AllResize,
|
||||
_ => return Err(WpCursorShapeDeviceV1Error::UnknownShape(req.shape)),
|
||||
DND_ASK if version >= V2 => KnownCursor::DndAsk,
|
||||
ALL_RESIZE if version >= V2 => KnownCursor::AllResize,
|
||||
_ => return None,
|
||||
};
|
||||
let tablet_tool;
|
||||
let (node_client_id, user) = match &self.cursor_user {
|
||||
CursorShapeCursorUser::Seat(s) => match s.pointer_node() {
|
||||
Some(n) => (n.node_client_id(), s.pointer_cursor()),
|
||||
_ => return Ok(()),
|
||||
},
|
||||
CursorShapeCursorUser::TabletTool(t) => match t.get() {
|
||||
Some(t) => {
|
||||
tablet_tool = t;
|
||||
(tablet_tool.node().node_client_id(), tablet_tool.cursor())
|
||||
}
|
||||
_ => return Ok(()),
|
||||
},
|
||||
};
|
||||
if node_client_id != Some(self.client.id) {
|
||||
return Ok(());
|
||||
Some(cursor)
|
||||
}
|
||||
|
||||
pub fn to_shape(self) -> u32 {
|
||||
match self {
|
||||
KnownCursor::Default => DEFAULT,
|
||||
KnownCursor::ContextMenu => CONTEXT_MENU,
|
||||
KnownCursor::Help => HELP,
|
||||
KnownCursor::Pointer => POINTER,
|
||||
KnownCursor::Progress => PROGRESS,
|
||||
KnownCursor::Wait => WAIT,
|
||||
KnownCursor::Cell => CELL,
|
||||
KnownCursor::Crosshair => CROSSHAIR,
|
||||
KnownCursor::Text => TEXT,
|
||||
KnownCursor::VerticalText => VERTICAL_TEXT,
|
||||
KnownCursor::Alias => ALIAS,
|
||||
KnownCursor::Copy => COPY,
|
||||
KnownCursor::Move => MOVE,
|
||||
KnownCursor::NoDrop => NO_DROP,
|
||||
KnownCursor::NotAllowed => NOT_ALLOWED,
|
||||
KnownCursor::Grab => GRAB,
|
||||
KnownCursor::Grabbing => GRABBING,
|
||||
KnownCursor::EResize => E_RESIZE,
|
||||
KnownCursor::NResize => N_RESIZE,
|
||||
KnownCursor::NeResize => NE_RESIZE,
|
||||
KnownCursor::NwResize => NW_RESIZE,
|
||||
KnownCursor::SResize => S_RESIZE,
|
||||
KnownCursor::SeResize => SE_RESIZE,
|
||||
KnownCursor::SwResize => SW_RESIZE,
|
||||
KnownCursor::WResize => W_RESIZE,
|
||||
KnownCursor::EwResize => EW_RESIZE,
|
||||
KnownCursor::NsResize => NS_RESIZE,
|
||||
KnownCursor::NeswResize => NESW_RESIZE,
|
||||
KnownCursor::NwseResize => NWSE_RESIZE,
|
||||
KnownCursor::ColResize => COL_RESIZE,
|
||||
KnownCursor::RowResize => ROW_RESIZE,
|
||||
KnownCursor::AllScroll => ALL_SCROLL,
|
||||
KnownCursor::ZoomIn => ZOOM_IN,
|
||||
KnownCursor::ZoomOut => ZOOM_OUT,
|
||||
KnownCursor::DndAsk => DND_ASK,
|
||||
KnownCursor::AllResize => ALL_RESIZE,
|
||||
}
|
||||
user.set_known(cursor);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,12 @@ pub mod usr_linux_dmabuf;
|
|||
pub mod usr_wl_buffer;
|
||||
pub mod usr_wl_callback;
|
||||
pub mod usr_wl_compositor;
|
||||
pub mod usr_wl_data_device;
|
||||
pub mod usr_wl_data_device_manager;
|
||||
pub mod usr_wl_data_offer;
|
||||
pub mod usr_wl_data_source;
|
||||
pub mod usr_wl_display;
|
||||
pub mod usr_wl_keyboard;
|
||||
pub mod usr_wl_output;
|
||||
pub mod usr_wl_pointer;
|
||||
pub mod usr_wl_registry;
|
||||
|
|
@ -25,9 +30,17 @@ 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_cursor_shape_device_v1;
|
||||
pub mod usr_wp_cursor_shape_manager_v1;
|
||||
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_xdg_surface;
|
||||
pub mod usr_xdg_toplevel;
|
||||
pub mod usr_xdg_wm_base;
|
||||
pub mod usr_zwlr_screencopy_frame;
|
||||
pub mod usr_zwlr_screencopy_manager;
|
||||
pub mod usr_zwp_linux_buffer_params_v1;
|
||||
pub mod usr_zwp_linux_dmabuf_v1;
|
||||
pub mod usr_zwp_primary_selection_device_manager;
|
||||
|
|
|
|||
99
src/wl_usr/usr_ifs/usr_wl_data_device.rs
Normal file
99
src/wl_usr/usr_ifs/usr_wl_data_device.rs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
use {
|
||||
crate::{
|
||||
object::Version,
|
||||
utils::clonecell::CloneCell,
|
||||
wire::{WlDataDeviceId, wl_data_device::*},
|
||||
wl_usr::{
|
||||
UsrCon,
|
||||
usr_ifs::{usr_wl_data_offer::UsrWlDataOffer, usr_wl_data_source::UsrWlDataSource},
|
||||
usr_object::UsrObject,
|
||||
},
|
||||
},
|
||||
std::{convert::Infallible, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrWlDataDevice {
|
||||
pub id: WlDataDeviceId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub version: Version,
|
||||
pub offer: CloneCell<Option<Rc<UsrWlDataOffer>>>,
|
||||
pub selection: CloneCell<Option<Rc<UsrWlDataOffer>>>,
|
||||
}
|
||||
|
||||
impl UsrWlDataDevice {
|
||||
#[expect(dead_code)]
|
||||
pub fn set_selection(&self, serial: u32, source: &UsrWlDataSource) {
|
||||
self.con.request(SetSelection {
|
||||
self_id: self.id,
|
||||
source: source.id,
|
||||
serial,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl WlDataDeviceEventHandler for UsrWlDataDevice {
|
||||
type Error = Infallible;
|
||||
|
||||
fn data_offer(&self, ev: DataOffer, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let obj = Rc::new(UsrWlDataOffer {
|
||||
id: ev.id,
|
||||
con: self.con.clone(),
|
||||
version: self.version,
|
||||
mime_types: Default::default(),
|
||||
});
|
||||
self.con.add_object(obj.clone());
|
||||
if let Some(offer) = self.offer.set(Some(obj)) {
|
||||
self.con.remove_obj(&*offer);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn enter(&self, ev: Enter, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let _ = ev;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn leave(&self, ev: Leave, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let _ = ev;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn motion(&self, ev: Motion, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let _ = ev;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn drop_(&self, ev: Drop, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let _ = ev;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn selection(&self, ev: Selection, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.selection.take();
|
||||
if let Some(offer) = self.offer.get()
|
||||
&& offer.id == ev.id
|
||||
{
|
||||
self.selection.set(Some(offer));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrWlDataDevice = WlDataDevice;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlDataDevice {
|
||||
fn destroy(&self) {
|
||||
if let Some(offer) = self.offer.take() {
|
||||
self.con.remove_obj(&*offer);
|
||||
}
|
||||
self.con.request(Release { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.selection.take();
|
||||
self.offer.take();
|
||||
}
|
||||
}
|
||||
72
src/wl_usr/usr_ifs/usr_wl_data_device_manager.rs
Normal file
72
src/wl_usr/usr_ifs/usr_wl_data_device_manager.rs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
use {
|
||||
crate::{
|
||||
object::Version,
|
||||
wire::{WlDataDeviceManagerId, wl_data_device_manager::*},
|
||||
wl_usr::{
|
||||
UsrCon,
|
||||
usr_ifs::{
|
||||
usr_wl_data_device::UsrWlDataDevice, usr_wl_data_source::UsrWlDataSource,
|
||||
usr_wl_seat::UsrWlSeat,
|
||||
},
|
||||
usr_object::UsrObject,
|
||||
},
|
||||
},
|
||||
std::{convert::Infallible, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrWlDataDeviceManager {
|
||||
pub id: WlDataDeviceManagerId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
impl UsrWlDataDeviceManager {
|
||||
#[expect(dead_code)]
|
||||
pub fn create_data_source(&self) -> Rc<UsrWlDataSource> {
|
||||
let obj = Rc::new(UsrWlDataSource {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
version: self.version,
|
||||
});
|
||||
self.con.request(CreateDataSource {
|
||||
self_id: self.id,
|
||||
id: obj.id,
|
||||
});
|
||||
self.con.add_object(obj.clone());
|
||||
obj
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
pub fn get_data_device(&self, seat: &UsrWlSeat) -> Rc<UsrWlDataDevice> {
|
||||
let obj = Rc::new(UsrWlDataDevice {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
version: self.version,
|
||||
offer: Default::default(),
|
||||
selection: Default::default(),
|
||||
});
|
||||
self.con.request(GetDataDevice {
|
||||
self_id: self.id,
|
||||
id: obj.id,
|
||||
seat: seat.id,
|
||||
});
|
||||
self.con.add_object(obj.clone());
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
impl WlDataDeviceManagerEventHandler for UsrWlDataDeviceManager {
|
||||
type Error = Infallible;
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrWlDataDeviceManager = WlDataDeviceManager;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlDataDeviceManager {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Release { self_id: self.id });
|
||||
}
|
||||
}
|
||||
58
src/wl_usr/usr_ifs/usr_wl_data_offer.rs
Normal file
58
src/wl_usr/usr_ifs/usr_wl_data_offer.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
use {
|
||||
crate::{
|
||||
object::Version,
|
||||
wire::{WlDataOfferId, wl_data_offer::*},
|
||||
wl_usr::{UsrCon, usr_object::UsrObject},
|
||||
},
|
||||
ahash::AHashSet,
|
||||
std::{cell::RefCell, convert::Infallible, rc::Rc},
|
||||
uapi::OwnedFd,
|
||||
};
|
||||
|
||||
pub struct UsrWlDataOffer {
|
||||
pub id: WlDataOfferId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub version: Version,
|
||||
pub mime_types: RefCell<AHashSet<String>>,
|
||||
}
|
||||
|
||||
impl UsrWlDataOffer {
|
||||
#[expect(dead_code)]
|
||||
pub fn receive(&self, mime_type: &str, fd: &Rc<OwnedFd>) {
|
||||
self.con.request(Receive {
|
||||
self_id: self.id,
|
||||
mime_type,
|
||||
fd: fd.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl WlDataOfferEventHandler for UsrWlDataOffer {
|
||||
type Error = Infallible;
|
||||
|
||||
fn offer(&self, ev: Offer<'_>, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.mime_types
|
||||
.borrow_mut()
|
||||
.insert(ev.mime_type.to_string());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn source_actions(&self, _ev: SourceActions, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn action(&self, _ev: Action, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrWlDataOffer = WlDataOffer;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlDataOffer {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
}
|
||||
82
src/wl_usr/usr_ifs/usr_wl_data_source.rs
Normal file
82
src/wl_usr/usr_ifs/usr_wl_data_source.rs
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
use {
|
||||
crate::{
|
||||
object::Version,
|
||||
utils::clonecell::CloneCell,
|
||||
wire::{WlDataSourceId, wl_data_source::*},
|
||||
wl_usr::{UsrCon, usr_object::UsrObject},
|
||||
},
|
||||
std::{convert::Infallible, rc::Rc},
|
||||
uapi::OwnedFd,
|
||||
};
|
||||
|
||||
pub struct UsrWlDataSource {
|
||||
pub id: WlDataSourceId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrWlDataSourceOwner>>>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
pub trait UsrWlDataSourceOwner {
|
||||
fn send(&self, mime_type: &str, fd: Rc<OwnedFd>);
|
||||
}
|
||||
|
||||
impl UsrWlDataSource {
|
||||
#[expect(dead_code)]
|
||||
pub fn offer(&self, mime_type: &str) {
|
||||
self.con.request(Offer {
|
||||
self_id: self.id,
|
||||
mime_type,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl WlDataSourceEventHandler for UsrWlDataSource {
|
||||
type Error = Infallible;
|
||||
|
||||
fn target(&self, ev: Target<'_>, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let _ = ev;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn send(&self, ev: Send<'_>, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.send(ev.mime_type, ev.fd);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cancelled(&self, ev: Cancelled, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let _ = ev;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dnd_drop_performed(&self, ev: DndDropPerformed, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let _ = ev;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dnd_finished(&self, ev: DndFinished, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let _ = ev;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn action(&self, ev: Action, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let _ = ev;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrWlDataSource = WlDataSource;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlDataSource {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
148
src/wl_usr/usr_ifs/usr_wl_keyboard.rs
Normal file
148
src/wl_usr/usr_ifs/usr_wl_keyboard.rs
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
use {
|
||||
crate::{
|
||||
ifs::wl_seat::wl_keyboard,
|
||||
object::Version,
|
||||
utils::{clonecell::CloneCell, mmap::mmap, oserror::OsError},
|
||||
wire::{WlKeyboardId, WlSurfaceId, wl_keyboard::*},
|
||||
wl_usr::{UsrCon, usr_object::UsrObject},
|
||||
},
|
||||
kbvm::{
|
||||
Components, Keycode, ModifierMask,
|
||||
lookup::{Lookup, LookupTable},
|
||||
xkb::{
|
||||
Context,
|
||||
diagnostic::{Diagnostic, WriteToLog},
|
||||
},
|
||||
},
|
||||
std::{cell::RefCell, rc::Rc},
|
||||
thiserror::Error,
|
||||
uapi::c,
|
||||
};
|
||||
|
||||
pub struct UsrWlKeyboard {
|
||||
pub id: WlKeyboardId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub keyboard: RefCell<Option<Keyboard>>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrWlKeyboardOwner>>>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
pub struct Keyboard {
|
||||
lookup: LookupTable,
|
||||
components: Components,
|
||||
}
|
||||
|
||||
pub trait UsrWlKeyboardOwner {
|
||||
fn focus(self: Rc<Self>, surface: WlSurfaceId, serial: u32);
|
||||
fn unfocus(self: Rc<Self>);
|
||||
fn modifiers(self: Rc<Self>, mods: ModifierMask);
|
||||
fn down(self: Rc<Self>, lookup: Lookup<'_>, serial: u32);
|
||||
fn repeat(self: Rc<Self>, lookup: Lookup<'_>, serial: u32);
|
||||
fn up(self: Rc<Self>, lookup: Lookup<'_>, serial: u32);
|
||||
}
|
||||
|
||||
impl WlKeyboardEventHandler for UsrWlKeyboard {
|
||||
type Error = UsrWlKeyboardError;
|
||||
|
||||
fn keymap(&self, ev: Keymap, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let map = mmap(ev.size as _, c::PROT_READ, c::MAP_PRIVATE, ev.fd.raw(), 0)
|
||||
.map_err(UsrWlKeyboardError::MapKeymap)?;
|
||||
let mut builder = Context::builder();
|
||||
builder.enable_default_includes(false);
|
||||
builder.enable_environment(false);
|
||||
let keymap = builder
|
||||
.build()
|
||||
.keymap_from_bytes(WriteToLog, None, unsafe { &*map.ptr })
|
||||
.map_err(UsrWlKeyboardError::ParseKeymap)?;
|
||||
let lookup = keymap.to_builder().build_lookup_table();
|
||||
let keyboard = Keyboard {
|
||||
lookup,
|
||||
components: Default::default(),
|
||||
};
|
||||
self.keyboard.replace(Some(keyboard));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn enter(&self, ev: Enter<'_>, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let Some(owner) = self.owner.get() else {
|
||||
return Ok(());
|
||||
};
|
||||
owner.focus(ev.surface, ev.serial);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn leave(&self, _ev: Leave, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let Some(owner) = self.owner.get() else {
|
||||
return Ok(());
|
||||
};
|
||||
owner.unfocus();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn key(&self, ev: Key, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let Some(kb) = &*self.keyboard.borrow() else {
|
||||
return Ok(());
|
||||
};
|
||||
let Some(owner) = self.owner.get() else {
|
||||
return Ok(());
|
||||
};
|
||||
let kc = Keycode::from_evdev(ev.key);
|
||||
let lookup = kb
|
||||
.lookup
|
||||
.lookup(kb.components.group, kb.components.mods, kc);
|
||||
if ev.state == wl_keyboard::PRESSED {
|
||||
owner.down(lookup, ev.serial);
|
||||
} else if ev.state == wl_keyboard::REPEATED {
|
||||
owner.repeat(lookup, ev.serial);
|
||||
} else if ev.state == wl_keyboard::RELEASED {
|
||||
owner.up(lookup, ev.serial);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn modifiers(&self, ev: Modifiers, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let Some(kb) = &mut *self.keyboard.borrow_mut() else {
|
||||
return Ok(());
|
||||
};
|
||||
kb.components.mods_pressed.0 = ev.mods_depressed;
|
||||
kb.components.mods_latched.0 = ev.mods_latched;
|
||||
kb.components.mods_locked.0 = ev.mods_locked;
|
||||
kb.components.group_locked.0 = ev.group;
|
||||
let old = kb.components.mods;
|
||||
kb.components.update_effective();
|
||||
let new = kb.components.mods;
|
||||
if old != new
|
||||
&& let Some(owner) = self.owner.get()
|
||||
{
|
||||
owner.modifiers(new);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn repeat_info(&self, _ev: RepeatInfo, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrWlKeyboard = WlKeyboard;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWlKeyboard {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Release { self_id: self.id });
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum UsrWlKeyboardError {
|
||||
#[error("Could not map the keymap")]
|
||||
MapKeymap(#[source] OsError),
|
||||
#[error("Could not parse the keymap")]
|
||||
ParseKeymap(#[source] Diagnostic),
|
||||
}
|
||||
|
|
@ -3,7 +3,11 @@ use {
|
|||
object::Version,
|
||||
utils::clonecell::CloneCell,
|
||||
wire::{WlSeatId, wl_seat::*},
|
||||
wl_usr::{UsrCon, usr_ifs::usr_wl_pointer::UsrWlPointer, usr_object::UsrObject},
|
||||
wl_usr::{
|
||||
UsrCon,
|
||||
usr_ifs::{usr_wl_keyboard::UsrWlKeyboard, usr_wl_pointer::UsrWlPointer},
|
||||
usr_object::UsrObject,
|
||||
},
|
||||
},
|
||||
std::{cell::Cell, convert::Infallible, rc::Rc},
|
||||
};
|
||||
|
|
@ -42,6 +46,23 @@ impl UsrWlSeat {
|
|||
});
|
||||
ptr
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
pub fn get_keyboard(&self) -> Rc<UsrWlKeyboard> {
|
||||
let kb = Rc::new(UsrWlKeyboard {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
keyboard: Default::default(),
|
||||
owner: Default::default(),
|
||||
version: self.version,
|
||||
});
|
||||
self.con.add_object(kb.clone());
|
||||
self.con.request(GetKeyboard {
|
||||
self_id: self.id,
|
||||
id: kb.id,
|
||||
});
|
||||
kb
|
||||
}
|
||||
}
|
||||
|
||||
impl WlSeatEventHandler for UsrWlSeat {
|
||||
|
|
|
|||
41
src/wl_usr/usr_ifs/usr_wp_cursor_shape_device_v1.rs
Normal file
41
src/wl_usr/usr_ifs/usr_wp_cursor_shape_device_v1.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
use {
|
||||
crate::{
|
||||
cursor::KnownCursor,
|
||||
object::Version,
|
||||
wire::{WpCursorShapeDeviceV1Id, wp_cursor_shape_device_v1::*},
|
||||
wl_usr::{UsrCon, usr_object::UsrObject},
|
||||
},
|
||||
std::{convert::Infallible, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrWpCursorShapeDeviceV1 {
|
||||
pub id: WpCursorShapeDeviceV1Id,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
impl UsrWpCursorShapeDeviceV1 {
|
||||
#[expect(dead_code)]
|
||||
pub fn set_shape(&self, serial: u32, cursor: KnownCursor) {
|
||||
self.con.request(SetShape {
|
||||
self_id: self.id,
|
||||
serial,
|
||||
shape: cursor.to_shape(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl WpCursorShapeDeviceV1EventHandler for UsrWpCursorShapeDeviceV1 {
|
||||
type Error = Infallible;
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrWpCursorShapeDeviceV1 = WpCursorShapeDeviceV1;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWpCursorShapeDeviceV1 {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id })
|
||||
}
|
||||
}
|
||||
54
src/wl_usr/usr_ifs/usr_wp_cursor_shape_manager_v1.rs
Normal file
54
src/wl_usr/usr_ifs/usr_wp_cursor_shape_manager_v1.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
use {
|
||||
crate::{
|
||||
object::Version,
|
||||
wire::{WpCursorShapeManagerV1Id, wp_cursor_shape_manager_v1::*},
|
||||
wl_usr::{
|
||||
UsrCon,
|
||||
usr_ifs::{
|
||||
usr_wl_pointer::UsrWlPointer,
|
||||
usr_wp_cursor_shape_device_v1::UsrWpCursorShapeDeviceV1,
|
||||
},
|
||||
usr_object::UsrObject,
|
||||
},
|
||||
},
|
||||
std::{convert::Infallible, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrWpCursorShapeManagerV1 {
|
||||
pub id: WpCursorShapeManagerV1Id,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
impl UsrWpCursorShapeManagerV1 {
|
||||
#[expect(dead_code)]
|
||||
pub fn get_pointer(&self, pointer: &UsrWlPointer) -> Rc<UsrWpCursorShapeDeviceV1> {
|
||||
let obj = Rc::new(UsrWpCursorShapeDeviceV1 {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
version: self.version,
|
||||
});
|
||||
self.con.request(GetPointer {
|
||||
self_id: self.id,
|
||||
cursor_shape_device: obj.id,
|
||||
pointer: pointer.id,
|
||||
});
|
||||
self.con.add_object(obj.clone());
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
impl WpCursorShapeManagerV1EventHandler for UsrWpCursorShapeManagerV1 {
|
||||
type Error = Infallible;
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrWpCursorShapeManagerV1 = WpCursorShapeManagerV1;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrWpCursorShapeManagerV1 {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id })
|
||||
}
|
||||
}
|
||||
70
src/wl_usr/usr_ifs/usr_xdg_surface.rs
Normal file
70
src/wl_usr/usr_ifs/usr_xdg_surface.rs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
use {
|
||||
crate::{
|
||||
object::Version,
|
||||
utils::clonecell::CloneCell,
|
||||
wire::{XdgSurfaceId, xdg_surface::*},
|
||||
wl_usr::{UsrCon, usr_ifs::usr_xdg_toplevel::UsrXdgToplevel, usr_object::UsrObject},
|
||||
},
|
||||
std::{convert::Infallible, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrXdgSurface {
|
||||
pub id: XdgSurfaceId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrXdgSurfaceOwner>>>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
pub trait UsrXdgSurfaceOwner {
|
||||
fn configure(&self) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrXdgSurface {
|
||||
#[expect(dead_code)]
|
||||
pub fn get_toplevel(&self) -> Rc<UsrXdgToplevel> {
|
||||
let obj = Rc::new(UsrXdgToplevel {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
version: self.version,
|
||||
});
|
||||
self.con.request(GetToplevel {
|
||||
self_id: self.id,
|
||||
id: obj.id,
|
||||
});
|
||||
self.con.add_object(obj.clone());
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
impl XdgSurfaceEventHandler for UsrXdgSurface {
|
||||
type Error = Infallible;
|
||||
|
||||
fn configure(&self, ev: Configure, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.con.request(AckConfigure {
|
||||
self_id: self.id,
|
||||
serial: ev.serial,
|
||||
});
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.configure();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrXdgSurface = XdgSurface;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrXdgSurface {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id })
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.owner.take();
|
||||
}
|
||||
}
|
||||
95
src/wl_usr/usr_ifs/usr_xdg_toplevel.rs
Normal file
95
src/wl_usr/usr_ifs/usr_xdg_toplevel.rs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
use {
|
||||
crate::{
|
||||
object::Version,
|
||||
utils::clonecell::CloneCell,
|
||||
wire::{WlOutputId, XdgToplevelId, xdg_toplevel::*},
|
||||
wl_usr::{UsrCon, usr_object::UsrObject},
|
||||
},
|
||||
std::{convert::Infallible, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrXdgToplevel {
|
||||
pub id: XdgToplevelId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub owner: CloneCell<Option<Rc<dyn UsrXdgToplevelOwner>>>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
impl UsrXdgToplevel {
|
||||
#[expect(dead_code)]
|
||||
pub fn set_title(&self, title: &str) {
|
||||
self.con.request(SetTitle {
|
||||
self_id: self.id,
|
||||
title,
|
||||
});
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
pub fn set_fullscreen(&self, fullscreen: bool) {
|
||||
match fullscreen {
|
||||
true => {
|
||||
self.con.request(SetFullscreen {
|
||||
self_id: self.id,
|
||||
output: WlOutputId::NONE,
|
||||
});
|
||||
}
|
||||
false => {
|
||||
self.con.request(UnsetFullscreen { self_id: self.id });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait UsrXdgToplevelOwner {
|
||||
fn configure(&self, width: i32, height: i32) {
|
||||
let _ = width;
|
||||
let _ = height;
|
||||
}
|
||||
|
||||
fn close(&self) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
||||
impl UsrXdgToplevel {}
|
||||
|
||||
impl XdgToplevelEventHandler for UsrXdgToplevel {
|
||||
type Error = Infallible;
|
||||
|
||||
fn configure(&self, ev: Configure<'_>, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.configure(ev.width, ev.height);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn close(&self, _ev: Close, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if let Some(owner) = self.owner.get() {
|
||||
owner.close();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn configure_bounds(&self, _ev: ConfigureBounds, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn wm_capabilities(&self, _ev: WmCapabilities<'_>, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrXdgToplevel = XdgToplevel;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrXdgToplevel {
|
||||
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_xdg_wm_base.rs
Normal file
60
src/wl_usr/usr_ifs/usr_xdg_wm_base.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
use {
|
||||
crate::{
|
||||
object::Version,
|
||||
wire::{XdgWmBaseId, xdg_wm_base::*},
|
||||
wl_usr::{
|
||||
UsrCon,
|
||||
usr_ifs::{usr_wl_surface::UsrWlSurface, usr_xdg_surface::UsrXdgSurface},
|
||||
usr_object::UsrObject,
|
||||
},
|
||||
},
|
||||
std::{convert::Infallible, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrXdgWmBase {
|
||||
pub id: XdgWmBaseId,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
impl UsrXdgWmBase {
|
||||
#[expect(dead_code)]
|
||||
pub fn get_xdg_surface(&self, surface: &UsrWlSurface) -> Rc<UsrXdgSurface> {
|
||||
let obj = Rc::new(UsrXdgSurface {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
version: self.version,
|
||||
});
|
||||
self.con.request(GetXdgSurface {
|
||||
self_id: self.id,
|
||||
id: obj.id,
|
||||
surface: surface.id,
|
||||
});
|
||||
self.con.add_object(obj.clone());
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
impl XdgWmBaseEventHandler for UsrXdgWmBase {
|
||||
type Error = Infallible;
|
||||
|
||||
fn ping(&self, ev: Ping, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.con.request(Pong {
|
||||
self_id: self.id,
|
||||
serial: ev.serial,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrXdgWmBase = XdgWmBase;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrXdgWmBase {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id })
|
||||
}
|
||||
}
|
||||
79
src/wl_usr/usr_ifs/usr_zwp_linux_buffer_params_v1.rs
Normal file
79
src/wl_usr/usr_ifs/usr_zwp_linux_buffer_params_v1.rs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
use {
|
||||
crate::{
|
||||
format::Format,
|
||||
object::Version,
|
||||
video::Modifier,
|
||||
wire::{ZwpLinuxBufferParamsV1Id, zwp_linux_buffer_params_v1::*},
|
||||
wl_usr::{UsrCon, usr_ifs::usr_wl_buffer::UsrWlBuffer, usr_object::UsrObject},
|
||||
},
|
||||
std::{convert::Infallible, rc::Rc},
|
||||
uapi::OwnedFd,
|
||||
};
|
||||
|
||||
pub struct UsrZwpLinuxBufferParamsV1 {
|
||||
pub id: ZwpLinuxBufferParamsV1Id,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
impl UsrZwpLinuxBufferParamsV1 {
|
||||
pub fn add(
|
||||
&self,
|
||||
fd: &Rc<OwnedFd>,
|
||||
plane_idx: usize,
|
||||
offset: u32,
|
||||
stride: u32,
|
||||
modifier: Modifier,
|
||||
) {
|
||||
self.con.request(Add {
|
||||
self_id: self.id,
|
||||
fd: fd.clone(),
|
||||
plane_idx: plane_idx as u32,
|
||||
offset,
|
||||
stride,
|
||||
modifier,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn create_immed(&self, width: i32, height: i32, format: &Format) -> Rc<UsrWlBuffer> {
|
||||
let obj = Rc::new(UsrWlBuffer {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
owner: Default::default(),
|
||||
version: self.version,
|
||||
});
|
||||
self.con.request(CreateImmed {
|
||||
self_id: self.id,
|
||||
buffer_id: obj.id,
|
||||
width,
|
||||
height,
|
||||
format: format.drm,
|
||||
flags: 0,
|
||||
});
|
||||
self.con.add_object(obj.clone());
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
impl ZwpLinuxBufferParamsV1EventHandler for UsrZwpLinuxBufferParamsV1 {
|
||||
type Error = Infallible;
|
||||
|
||||
fn created(&self, _ev: Created, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn failed(&self, _ev: Failed, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrZwpLinuxBufferParamsV1 = ZwpLinuxBufferParamsV1;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrZwpLinuxBufferParamsV1 {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id })
|
||||
}
|
||||
}
|
||||
67
src/wl_usr/usr_ifs/usr_zwp_linux_dmabuf_v1.rs
Normal file
67
src/wl_usr/usr_ifs/usr_zwp_linux_dmabuf_v1.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
use {
|
||||
crate::{
|
||||
object::Version,
|
||||
video::dmabuf::DmaBuf,
|
||||
wire::{ZwpLinuxDmabufV1Id, zwp_linux_dmabuf_v1::*},
|
||||
wl_usr::{
|
||||
UsrCon,
|
||||
usr_ifs::{
|
||||
usr_wl_buffer::UsrWlBuffer,
|
||||
usr_zwp_linux_buffer_params_v1::UsrZwpLinuxBufferParamsV1,
|
||||
},
|
||||
usr_object::UsrObject,
|
||||
},
|
||||
},
|
||||
std::{convert::Infallible, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrZwpLinuxDmabufV1 {
|
||||
pub id: ZwpLinuxDmabufV1Id,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
impl UsrZwpLinuxDmabufV1 {
|
||||
#[expect(dead_code)]
|
||||
pub fn create_buffer(&self, buffer: &DmaBuf) -> Rc<UsrWlBuffer> {
|
||||
let params = Rc::new(UsrZwpLinuxBufferParamsV1 {
|
||||
id: self.con.id(),
|
||||
con: self.con.clone(),
|
||||
version: self.version,
|
||||
});
|
||||
self.con.request(CreateParams {
|
||||
self_id: self.id,
|
||||
params_id: params.id,
|
||||
});
|
||||
self.con.add_object(params.clone());
|
||||
for (idx, plane) in buffer.planes.iter().enumerate() {
|
||||
params.add(&plane.fd, idx, plane.offset, plane.stride, buffer.modifier);
|
||||
}
|
||||
let obj = params.create_immed(buffer.width, buffer.height, &buffer.format);
|
||||
self.con.remove_obj(&*params);
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
impl ZwpLinuxDmabufV1EventHandler for UsrZwpLinuxDmabufV1 {
|
||||
type Error = Infallible;
|
||||
|
||||
fn format(&self, _ev: Format, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn modifier(&self, _ev: Modifier, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrZwpLinuxDmabufV1 = ZwpLinuxDmabufV1;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrZwpLinuxDmabufV1 {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id })
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
use {
|
||||
crate::{
|
||||
object::Version,
|
||||
wire::{ZwpPrimarySelectionDeviceManagerV1Id, zwp_primary_selection_device_manager_v1::*},
|
||||
wl_usr::{UsrCon, usr_object::UsrObject},
|
||||
},
|
||||
std::{convert::Infallible, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct UsrZwpPrimarySelectionDeviceManagerV1 {
|
||||
pub id: ZwpPrimarySelectionDeviceManagerV1Id,
|
||||
pub con: Rc<UsrCon>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
impl UsrZwpPrimarySelectionDeviceManagerV1 {}
|
||||
|
||||
impl ZwpPrimarySelectionDeviceManagerV1EventHandler for UsrZwpPrimarySelectionDeviceManagerV1 {
|
||||
type Error = Infallible;
|
||||
}
|
||||
|
||||
usr_object_base! {
|
||||
self = UsrZwpPrimarySelectionDeviceManagerV1 = ZwpPrimarySelectionDeviceManagerV1;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl UsrObject for UsrZwpPrimarySelectionDeviceManagerV1 {
|
||||
fn destroy(&self) {
|
||||
self.con.request(Destroy { self_id: self.id })
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue