From f8e7557d1d3c4fa6c05295fb4bb38bd0f8a8e791 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Fri, 7 Jan 2022 15:08:31 +0100 Subject: [PATCH] autocommit 2022-01-07 15:08:31 CET --- src/backend.rs | 6 +- src/backends/xorg/mod.rs | 82 ++++++-- src/client/mod.rs | 42 +++- src/fixed.rs | 8 +- src/ifs/wl_seat/mod.rs | 56 ++++- src/ifs/wl_seat/types.rs | 131 +++++++++++- src/ifs/wl_seat/wl_keyboard/mod.rs | 142 +++++++++++++ src/ifs/wl_seat/wl_keyboard/types.rs | 205 ++++++++++++++++++ src/ifs/wl_seat/wl_pointer/mod.rs | 177 ++++++++++++++++ src/ifs/wl_seat/wl_pointer/types.rs | 299 +++++++++++++++++++++++++++ src/ifs/wl_seat/wl_touch/mod.rs | 68 ++++++ src/ifs/wl_seat/wl_touch/types.rs | 35 ++++ src/main.rs | 2 +- src/object.rs | 6 + src/utils/buffd/buf_out.rs | 9 +- src/utils/buffd/formatter.rs | 9 +- src/utils/buffd/parser.rs | 2 +- src/xkbcommon/mod.rs | 14 ++ 18 files changed, 1258 insertions(+), 35 deletions(-) create mode 100644 src/ifs/wl_seat/wl_keyboard/mod.rs create mode 100644 src/ifs/wl_seat/wl_keyboard/types.rs create mode 100644 src/ifs/wl_seat/wl_pointer/mod.rs create mode 100644 src/ifs/wl_seat/wl_pointer/types.rs create mode 100644 src/ifs/wl_seat/wl_touch/mod.rs create mode 100644 src/ifs/wl_seat/wl_touch/types.rs diff --git a/src/backend.rs b/src/backend.rs index 904a1554..44eb0e71 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,5 +1,6 @@ -use std::rc::Rc; use crate::fixed::Fixed; +use std::rc::Rc; +use crate::xkbcommon::XkbKeymapStr; linear_ids!(OutputIds, OutputId); linear_ids!(SeatIds, SeatId); @@ -27,4 +28,7 @@ pub enum BackendEvent { #[derive(Debug)] pub enum SeatEvent { Motion(OutputId, Fixed, Fixed), + Key(u32), + Keymap(XkbKeymapStr), + Modifiers(u32, u32, u32, u32) } diff --git a/src/backends/xorg/mod.rs b/src/backends/xorg/mod.rs index 8a344ced..ed1baf04 100644 --- a/src/backends/xorg/mod.rs +++ b/src/backends/xorg/mod.rs @@ -1,5 +1,6 @@ use crate::backend::{BackendEvent, Output, OutputId, Seat, SeatEvent, SeatId}; use crate::event_loop::{EventLoopDispatcher, EventLoopId}; +use crate::fixed::Fixed; use crate::ifs::wl_buffer::WlBuffer; use crate::ifs::wl_surface::WlSurface; use crate::pixman::{Image, PixmanError}; @@ -24,7 +25,6 @@ use uapi::c; use xcb_dl::{ffi, Xcb, XcbShm, XcbXinput, XcbXkb}; use xcb_dl_util::error::{XcbError, XcbErrorParser}; use xcb_dl_util::xcb_box::XcbBox; -use crate::fixed::Fixed; #[derive(Debug, Error)] pub enum XorgBackendError { @@ -71,6 +71,7 @@ struct XcbCon { input: Box, input_opcode: u8, xkb: Box, + xkb_event: u8, c: *mut ffi::xcb_connection_t, errors: XcbErrorParser, } @@ -92,6 +93,7 @@ impl XcbCon { input, input_opcode: 0, xkb, + xkb_event: 0, c, errors, }; @@ -125,6 +127,12 @@ impl XcbCon { ); con.errors.check(&con.xcb, res, err)?; + let xkb_ex = con + .xcb + .xcb_get_extension_data(con.c, con.xkb.xcb_xkb_id()); + assert!(xkb_ex.is_not_null()); + con.xkb_event = xkb_ex.deref().first_event; + Ok(con) } } @@ -348,6 +356,21 @@ impl XorgBackend { Ok(()) } + fn create_state(&self, device_id: ffi::xcb_input_device_id_t) -> Result { + unsafe { + let keymap = self.xkbcommonx11.keymap_from_device( + &self.xkbcommon, + self.con.c, + device_id as _, + XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, + )?; + let state = + self.xkbcommonx11 + .state_from_device(&keymap, self.con.c, device_id as _)?; + Ok(state) + } + } + fn handle_input_device(self: &Rc, info: &ffi::xcb_input_xi_device_info_t) { if info.type_ != ffi::XCB_INPUT_DEVICE_TYPE_MASTER_KEYBOARD as _ { return; @@ -379,19 +402,7 @@ impl XorgBackend { e ); } - let res: Result<_, XkbCommonError> = (|| { - let keymap = self.xkbcommonx11.keymap_from_device( - &self.xkbcommon, - con.c, - info.deviceid as _, - XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, - )?; - let state = - self.xkbcommonx11 - .state_from_device(&keymap, con.c, info.deviceid as _)?; - Ok(state) - })(); - let state = match res { + let state = match self.create_state(info.deviceid) { Ok(c) => c, Err(e) => { log::error!( @@ -412,6 +423,7 @@ impl XorgBackend { events: RefCell::new(Default::default()), state, }); + seat.send_new_state(); self.seats.set(info.deviceid, seat.clone()); self.mouse_seats.set(info.attachment, seat.clone()); self.state @@ -443,6 +455,30 @@ impl XorgBackend { ffi::XCB_CONFIGURE_NOTIFY => self.handle_configure(event)?, ffi::XCB_DESTROY_NOTIFY => self.handle_destroy(event)?, ffi::XCB_GE_GENERIC => self.handle_generic(event)?, + _ if event_type == self.con.xkb_event => self.handle_xkb(event)?, + _ => {} + } + Ok(()) + } + + fn handle_xkb( + self: &Rc, + event: &ffi::xcb_generic_event_t, + ) -> Result<(), XorgBackendError> { + let event = unsafe { &*(event as *const _ as *const ffi::xcb_xkb_map_notify_event_t) }; + let seat = match self.seats.get(&(event.device_id as _)) { + Some(s) => s, + _ => return Ok(()), + }; + match event.xkb_type { + ffi::XCB_XKB_MAP_NOTIFY | ffi::XCB_XKB_NEW_KEYBOARD_NOTIFY => { + + } + ffi::XCB_XKB_STATE_NOTIFY => { + let event = unsafe { + (event as *const _ as *const ffi::xcb_xkb_state_notify_event_t).deref() + }; + } _ => {} } Ok(()) @@ -465,12 +501,25 @@ impl XorgBackend { ) -> Result<(), XorgBackendError> { match event.event_type { ffi::XCB_INPUT_MOTION => self.handle_input_motion(event)?, + ffi::XCB_INPUT_KEY_PRESS => self.handle_input_key_press(event)?, ffi::XCB_INPUT_HIERARCHY => self.handle_input_hierarchy(event)?, _ => {} } Ok(()) } + fn handle_input_key_press( + self: &Rc, + event: &ffi::xcb_ge_generic_event_t, + ) -> Result<(), XorgBackendError> { + let event = + unsafe { (event as *const _ as *const ffi::xcb_input_key_press_event_t).deref() }; + if let Some(seat) = self.seats.get(&event.deviceid) { + seat.event(SeatEvent::Key(event.detail - 8)); + } + Ok(()) + } + fn handle_input_hierarchy( self: &Rc, event: &ffi::xcb_ge_generic_event_t, @@ -748,6 +797,7 @@ struct XorgSeat { removed: Cell, cb: RefCell>>, events: RefCell>, + last_modifiers: Cell<(u32, u32, u32, u32)>, state: XkbState, } @@ -781,7 +831,3 @@ impl Seat for XorgSeat { *self.cb.borrow_mut() = Some(cb); } } - -fn fp1616_to_f64(i: ffi::xcb_input_fp1616_t) -> f64 { - i as f64 / (1 << 16) as f64 -} diff --git a/src/client/mod.rs b/src/client/mod.rs index f0b3b9af..67edf8ed 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -32,7 +32,10 @@ use std::future::Future; use std::mem; use std::rc::Rc; use thiserror::Error; -use uapi::OwnedFd; +use uapi::{c, OwnedFd}; +use crate::ifs::wl_seat::wl_keyboard::{WlKeyboard, WlKeyboardError}; +use crate::ifs::wl_seat::wl_pointer::{WlPointer, WlPointerError}; +use crate::ifs::wl_seat::wl_touch::{WlTouch, WlTouchError}; mod objects; mod tasks; @@ -113,6 +116,12 @@ pub enum ClientError { WlOutputError(#[source] Box), #[error("An error occurred in a `wl_seat`")] WlSeatError(#[source] Box), + #[error("An error occurred in a `wl_pointer`")] + WlPointerError(#[source] Box), + #[error("An error occurred in a `wl_keyboard`")] + WlKeyboardError(#[source] Box), + #[error("An error occurred in a `wl_touch`")] + WlTouchError(#[source] Box), #[error("Object {0} is not a display")] NotADisplay(ObjectId), } @@ -135,6 +144,9 @@ efrom!(ClientError, XdgPopupError, XdgPopupError); efrom!(ClientError, WlBufferError, WlBufferError); efrom!(ClientError, WlOutputError, WlOutputError); efrom!(ClientError, WlSeatError, WlSeatError); +efrom!(ClientError, WlTouchError, WlTouchError); +efrom!(ClientError, WlPointerError, WlPointerError); +efrom!(ClientError, WlKeyboardError, WlKeyboardError); impl ClientError { fn peer_closed(&self) -> bool { @@ -187,6 +199,23 @@ impl Clients { global: &Rc, socket: OwnedFd, ) -> Result<(), ClientError> { + let (uid, pid) = unsafe { + let mut cred = c::ucred { + pid: 0, + uid: 0, + gid: 0, + }; + match uapi::getsockopt(socket.raw(), c::SOL_SOCKET, c::SO_PEERCRED, &mut cred) { + Ok(_) => (cred.uid, cred.pid), + Err(e) => { + log::error!( + "Cannot determine peer credentials of new connection: {:?}", + std::io::Error::from(e) + ); + return Ok(()); + } + } + }; let (send, recv) = oneshot(); let data = Rc::new(Client { id, @@ -205,8 +234,14 @@ impl Clients { _handler: global.eng.spawn(tasks::client(data.clone(), recv)), data, }; + log::info!( + "Client {} connected, pid: {}, uid: {}, fd: {}", + id, + pid, + uid, + client.data.socket.raw() + ); self.clients.borrow_mut().insert(client.data.id, client); - log::info!("Client {} connected", id); Ok(()) } @@ -485,6 +520,9 @@ simple_add_obj!(XdgToplevel); simple_add_obj!(XdgPopup); simple_add_obj!(WlOutputObj); simple_add_obj!(WlSeatObj); +simple_add_obj!(WlKeyboard); +simple_add_obj!(WlPointer); +simple_add_obj!(WlTouch); macro_rules! dedicated_add_obj { ($ty:ty, $field:ident) => { diff --git a/src/fixed.rs b/src/fixed.rs index 1f905de1..4171891c 100644 --- a/src/fixed.rs +++ b/src/fixed.rs @@ -1,4 +1,4 @@ -use std::fmt::{Debug, Formatter}; +use std::fmt::{Debug, Display, Formatter}; #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] #[repr(transparent)] @@ -33,3 +33,9 @@ impl Debug for Fixed { Debug::fmt(&f64::from(*self), f) } } + +impl Display for Fixed { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + Display::fmt(&f64::from(*self), f) + } +} diff --git a/src/ifs/wl_seat/mod.rs b/src/ifs/wl_seat/mod.rs index 3a095cb4..97ebb46a 100644 --- a/src/ifs/wl_seat/mod.rs +++ b/src/ifs/wl_seat/mod.rs @@ -1,17 +1,35 @@ mod types; +pub mod wl_keyboard; +pub mod wl_pointer; +pub mod wl_touch; use crate::backend::{Seat, SeatEvent}; -use crate::client::{AddObj, Client, ClientId}; +use crate::client::{AddObj, Client, ClientId, DynEventFormatter}; use crate::globals::{Global, GlobalName}; use crate::object::{Interface, Object, ObjectId}; use crate::utils::buffd::MsgParser; use crate::utils::copyhashmap::CopyHashMap; use std::rc::Rc; pub use types::*; +use crate::ifs::wl_seat::wl_keyboard::WlKeyboard; +use crate::ifs::wl_seat::wl_pointer::WlPointer; +use crate::ifs::wl_seat::wl_touch::WlTouch; id!(WlSeatId); -const RELEASE: u32 = 0; +const GET_POINTER: u32 = 0; +const GET_KEYBOARD: u32 = 1; +const GET_TOUCH: u32 = 2; +const RELEASE: u32 = 3; + +const CAPABILITIES: u32 = 0; +const NAME: u32 = 1; + +const POINTER: u32 = 1; +const KEYBOARD: u32 = 2; +const TOUCH: u32 = 4; + +const MISSING_CAPABILITY: u32 = 0; pub struct WlSeatGlobal { name: GlobalName, @@ -44,6 +62,7 @@ impl WlSeatGlobal { client: client.clone(), }); client.add_client_obj(&obj)?; + client.event(obj.capabilities()).await?; self.bindings.set((client.id, id), obj.clone()); Ok(()) } @@ -80,6 +99,34 @@ pub struct WlSeatObj { } impl WlSeatObj { + fn capabilities(self: &Rc) -> DynEventFormatter { + Box::new(Capabilities { + obj: self.clone(), + capabilities: POINTER | KEYBOARD, + }) + } + + async fn get_pointer(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), GetPointerError> { + let req: GetPointer = self.client.parse(&**self, parser)?; + let p = Rc::new(WlPointer::new(req.id, self)); + self.client.add_client_obj(&p)?; + Ok(()) + } + + async fn get_keyboard(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), GetKeyboardError> { + let req: GetKeyboard = self.client.parse(&**self, parser)?; + let p = Rc::new(WlKeyboard::new(req.id, self)); + self.client.add_client_obj(&p)?; + Ok(()) + } + + async fn get_touch(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), GetTouchError> { + let req: GetTouch = self.client.parse(&**self, parser)?; + let p = Rc::new(WlTouch::new(req.id, self)); + self.client.add_client_obj(&p)?; + Ok(()) + } + async fn release(&self, parser: MsgParser<'_, '_>) -> Result<(), ReleaseError> { let _req: Release = self.client.parse(self, parser)?; self.global.bindings.remove(&(self.client.id, self.id)); @@ -88,11 +135,14 @@ impl WlSeatObj { } async fn handle_request_( - &self, + self: &Rc, request: u32, parser: MsgParser<'_, '_>, ) -> Result<(), WlSeatError> { match request { + GET_POINTER => self.get_pointer(parser).await?, + GET_KEYBOARD => self.get_keyboard(parser).await?, + GET_TOUCH => self.get_touch(parser).await?, RELEASE => self.release(parser).await?, _ => unreachable!(), } diff --git a/src/ifs/wl_seat/types.rs b/src/ifs/wl_seat/types.rs index 946f8f03..30e222d3 100644 --- a/src/ifs/wl_seat/types.rs +++ b/src/ifs/wl_seat/types.rs @@ -1,10 +1,22 @@ -use crate::client::{ClientError, RequestParser}; -use crate::utils::buffd::{MsgParser, MsgParserError}; +use crate::client::{ClientError, EventFormatter, RequestParser}; +use crate::ifs::wl_seat::wl_touch::WlTouchId; +use crate::ifs::wl_seat::{WlSeatObj, CAPABILITIES, NAME}; +use crate::object::Object; +use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; +use std::rc::Rc; use thiserror::Error; +use crate::ifs::wl_seat::wl_keyboard::WlKeyboardId; +use crate::ifs::wl_seat::wl_pointer::WlPointerId; #[derive(Debug, Error)] pub enum WlSeatError { + #[error("Could not handle `get_pointer` request")] + GetPointerError(#[from] GetPointerError), + #[error("Could not handle `get_keyboard` request")] + GetKeyboardError(#[from] GetKeyboardError), + #[error("Could not handle `get_touch` request")] + GetTouchError(#[from] GetTouchError), #[error("Could not handle `release` request")] ReleaseError(#[from] ReleaseError), #[error(transparent)] @@ -12,6 +24,36 @@ pub enum WlSeatError { } efrom!(WlSeatError, ClientError, ClientError); +#[derive(Debug, Error)] +pub enum GetPointerError { + #[error("Parsing failed")] + ParseError(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(GetPointerError, ClientError, ClientError); +efrom!(GetPointerError, ParseError, MsgParserError); + +#[derive(Debug, Error)] +pub enum GetKeyboardError { + #[error("Parsing failed")] + ParseError(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(GetKeyboardError, ClientError, ClientError); +efrom!(GetKeyboardError, ParseError, MsgParserError); + +#[derive(Debug, Error)] +pub enum GetTouchError { + #[error("Parsing failed")] + ParseError(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(GetTouchError, ClientError, ClientError); +efrom!(GetTouchError, ParseError, MsgParserError); + #[derive(Debug, Error)] pub enum ReleaseError { #[error("Parsing failed")] @@ -22,6 +64,54 @@ pub enum ReleaseError { efrom!(ReleaseError, ClientError, ClientError); efrom!(ReleaseError, ParseError, MsgParserError); +pub(super) struct GetPointer { + pub id: WlPointerId, +} +impl RequestParser<'_> for GetPointer { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self { + id: parser.object()?, + }) + } +} +impl Debug for GetPointer { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "get_pointer(id: {})", self.id) + } +} + +pub(super) struct GetKeyboard { + pub id: WlKeyboardId, +} +impl RequestParser<'_> for GetKeyboard { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self { + id: parser.object()?, + }) + } +} +impl Debug for GetKeyboard { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "get_keyboard(id: {})", self.id) + } +} + +pub(super) struct GetTouch { + pub id: WlTouchId, +} +impl RequestParser<'_> for GetTouch { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self { + id: parser.object()?, + }) + } +} +impl Debug for GetTouch { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "get_touch(id: {})", self.id) + } +} + pub(super) struct Release; impl RequestParser<'_> for Release { fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { @@ -33,3 +123,40 @@ impl Debug for Release { write!(f, "release()") } } + +pub(super) struct Capabilities { + pub obj: Rc, + pub capabilities: u32, +} +impl EventFormatter for Capabilities { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, CAPABILITIES) + .uint(self.capabilities); + } + fn obj(&self) -> &dyn Object { + &*self.obj + } +} +impl Debug for Capabilities { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "capabilities(capabilities: {})", self.capabilities) + } +} + +pub(super) struct Name { + pub obj: Rc, + pub name: String, +} +impl EventFormatter for Name { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, NAME).string(&self.name); + } + fn obj(&self) -> &dyn Object { + &*self.obj + } +} +impl Debug for Name { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "name(name: {})", self.name) + } +} diff --git a/src/ifs/wl_seat/wl_keyboard/mod.rs b/src/ifs/wl_seat/wl_keyboard/mod.rs new file mode 100644 index 00000000..5924509e --- /dev/null +++ b/src/ifs/wl_seat/wl_keyboard/mod.rs @@ -0,0 +1,142 @@ +mod types; + +use crate::client::{AddObj, DynEventFormatter}; +use crate::ifs::wl_seat::WlSeatObj; +use crate::ifs::wl_surface::WlSurfaceId; +use crate::object::{Interface, Object, ObjectId}; +use crate::utils::buffd::MsgParser; +use std::rc::Rc; +pub use types::*; +use uapi::OwnedFd; + +const RELEASE: u32 = 0; + +const KEYMAP: u32 = 0; +const ENTER: u32 = 1; +const LEAVE: u32 = 2; +const KEY: u32 = 3; +const MODIFIERS: u32 = 4; +const REPEAT_INFO: u32 = 5; + +const NO_KEYMAP: u32 = 0; +const XKB_V1: u32 = 1; + +const RELEASED: u32 = 0; +const PRESSED: u32 = 1; + +id!(WlKeyboardId); + +pub struct WlKeyboard { + id: WlKeyboardId, + seat: Rc, +} + +impl WlKeyboard { + pub fn new(id: WlKeyboardId, seat: &Rc) -> Self { + Self { + id, + seat: seat.clone(), + } + } + + pub fn keymap(self: &Rc, format: u32, fd: Rc, size: u32) -> DynEventFormatter { + Box::new(Keymap { + obj: self.clone(), + format, + fd, + size, + }) + } + + pub fn enter( + self: &Rc, + serial: u32, + surface: WlSurfaceId, + keys: Vec, + ) -> DynEventFormatter { + Box::new(Enter { + obj: self.clone(), + serial, + surface, + keys, + }) + } + + pub fn leave(self: &Rc, serial: u32, surface: WlSurfaceId) -> DynEventFormatter { + Box::new(Leave { + obj: self.clone(), + serial, + surface, + }) + } + + pub fn key(self: &Rc, serial: u32, time: u32, key: u32, state: u32) -> DynEventFormatter { + Box::new(Key { + obj: self.clone(), + serial, + time, + key, + state, + }) + } + + pub fn modifiers( + self: &Rc, + serial: u32, + mods_depressed: u32, + mods_latched: u32, + mods_locked: u32, + group: u32, + ) -> DynEventFormatter { + Box::new(Modifiers { + obj: self.clone(), + serial, + mods_depressed, + mods_latched, + mods_locked, + group, + }) + } + + pub fn repeat_info(self: &Rc, rate: i32, delay: i32) -> DynEventFormatter { + Box::new(RepeatInfo { + obj: self.clone(), + rate, + delay, + }) + } + + async fn release(&self, parser: MsgParser<'_, '_>) -> Result<(), ReleaseError> { + let _req: Release = self.seat.client.parse(self, parser)?; + self.seat.client.remove_obj(self).await?; + Ok(()) + } + + async fn handle_request_( + &self, + request: u32, + parser: MsgParser<'_, '_>, + ) -> Result<(), WlKeyboardError> { + match request { + RELEASE => self.release(parser).await?, + _ => unreachable!(), + } + Ok(()) + } +} + +handle_request!(WlKeyboard); + +impl Object for WlKeyboard { + fn id(&self) -> ObjectId { + self.id.into() + } + + fn interface(&self) -> Interface { + Interface::WlKeyboard + } + + fn num_requests(&self) -> u32 { + RELEASE + 1 + } +} diff --git a/src/ifs/wl_seat/wl_keyboard/types.rs b/src/ifs/wl_seat/wl_keyboard/types.rs new file mode 100644 index 00000000..44198cfa --- /dev/null +++ b/src/ifs/wl_seat/wl_keyboard/types.rs @@ -0,0 +1,205 @@ +use crate::client::{ClientError, EventFormatter, RequestParser}; +use crate::ifs::wl_seat::wl_keyboard::{ + WlKeyboard, ENTER, KEY, KEYMAP, LEAVE, MODIFIERS, REPEAT_INFO, +}; +use crate::ifs::wl_surface::WlSurfaceId; +use crate::object::Object; +use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; +use std::fmt::{Debug, Formatter}; +use std::ops::Deref; +use std::rc::Rc; +use thiserror::Error; +use uapi::OwnedFd; + +#[derive(Debug, Error)] +pub enum WlKeyboardError { + #[error(transparent)] + ClientError(Box), + #[error("Could not process a `release` request")] + ReleaseError(#[from] ReleaseError), +} +efrom!(WlKeyboardError, ClientError, ClientError); + +#[derive(Debug, Error)] +pub enum ReleaseError { + #[error("Parsing failed")] + ParseError(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(ReleaseError, ParseError, MsgParserError); +efrom!(ReleaseError, ClientError, ClientError); + +pub(super) struct Release; +impl RequestParser<'_> for Release { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self) + } +} +impl Debug for Release { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "destroy()",) + } +} + +pub(super) struct Keymap { + pub obj: Rc, + pub format: u32, + pub fd: Rc, + pub size: u32, +} +impl EventFormatter for Keymap { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, KEYMAP) + .uint(self.format) + .fd(self.fd) + .uint(self.size); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for Keymap { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "keymap(format: {}, fd: {}, size: {})", + self.format, + self.fd.raw(), + self.size + ) + } +} + +pub(super) struct Enter { + pub obj: Rc, + pub serial: u32, + pub surface: WlSurfaceId, + pub keys: Vec, +} +impl EventFormatter for Enter { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, ENTER) + .uint(self.serial) + .object(self.surface) + .array(|f| { + for &key in &self.keys { + f.uint(key); + } + }); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for Enter { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "enter(serial: {}, surface: {}, keys: {:?})", + self.serial, self.surface, self.keys + ) + } +} + +pub(super) struct Leave { + pub obj: Rc, + pub serial: u32, + pub surface: WlSurfaceId, +} +impl EventFormatter for Leave { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, LEAVE) + .uint(self.serial) + .object(self.surface); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for Leave { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "leave(serial: {}, surface: {})", + self.serial, self.surface + ) + } +} + +pub(super) struct Key { + pub obj: Rc, + pub serial: u32, + pub time: u32, + pub key: u32, + pub state: u32, +} +impl EventFormatter for Key { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, KEY) + .uint(self.serial) + .uint(self.time) + .uint(self.key) + .uint(self.state); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for Key { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "key(serial: {}, time: {}, key: {}, state: {})", + self.serial, self.time, self.key, self.state + ) + } +} + +pub(super) struct Modifiers { + pub obj: Rc, + pub serial: u32, + pub mods_depressed: u32, + pub mods_latched: u32, + pub mods_locked: u32, + pub group: u32, +} +impl EventFormatter for Modifiers { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, MODIFIERS) + .uint(self.serial) + .uint(self.mods_depressed) + .uint(self.mods_latched) + .uint(self.mods_locked) + .uint(self.group); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for Modifiers { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "modifiers(serial: {}, mods_depressed: {}, mods_latched: {}, mods_locked: {}, group: {})", self.serial, self.mods_depressed, self.mods_latched, self.mods_locked, self.group) + } +} + +pub(super) struct RepeatInfo { + pub obj: Rc, + pub rate: i32, + pub delay: i32, +} +impl EventFormatter for RepeatInfo { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, REPEAT_INFO) + .int(self.rate) + .int(self.delay); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for RepeatInfo { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "repeat_info(rate: {}, delay: {})", self.rate, self.delay) + } +} diff --git a/src/ifs/wl_seat/wl_pointer/mod.rs b/src/ifs/wl_seat/wl_pointer/mod.rs new file mode 100644 index 00000000..eb00cf96 --- /dev/null +++ b/src/ifs/wl_seat/wl_pointer/mod.rs @@ -0,0 +1,177 @@ +mod types; + +use crate::client::{AddObj, DynEventFormatter}; +use crate::fixed::Fixed; +use crate::ifs::wl_seat::WlSeatObj; +use crate::ifs::wl_surface::WlSurfaceId; +use crate::object::{Interface, Object, ObjectId}; +use crate::utils::buffd::MsgParser; +use std::rc::Rc; +pub use types::*; + +const SET_CURSOR: u32 = 0; +const RELEASE: u32 = 1; + +const ENTER: u32 = 0; +const LEAVE: u32 = 1; +const MOTION: u32 = 2; +const BUTTON: u32 = 3; +const AXIS: u32 = 4; +const FRAME: u32 = 5; +const AXIS_SOURCE: u32 = 6; +const AXIS_STOP: u32 = 7; +const AXIS_DISCRETE: u32 = 8; + +const ROLE: u32 = 0; + +const RELEASED: u32 = 0; +const PRESSED: u32 = 1; + +const VERTICAL_SCROLL: u32 = 0; +const HORIZONTAL_SCROLL: u32 = 1; + +const WHEEL: u32 = 0; +const FINGER: u32 = 1; +const CONTINUOUS: u32 = 2; +const WHEEL_TILT: u32 = 3; + +id!(WlPointerId); + +pub struct WlPointer { + id: WlPointerId, + seat: Rc, +} + +impl WlPointer { + pub fn new(id: WlPointerId, seat: &Rc) -> Self { + Self { + id, + seat: seat.clone(), + } + } + + pub fn enter( + self: &Rc, + serial: u32, + surface: WlSurfaceId, + x: Fixed, + y: Fixed, + ) -> DynEventFormatter { + Box::new(Enter { + obj: self.clone(), + serial, + surface, + surface_x: x, + surface_y: y, + }) + } + + pub fn leave(self: &Rc, serial: u32, surface: WlSurfaceId) -> DynEventFormatter { + Box::new(Leave { + obj: self.clone(), + serial, + surface, + }) + } + + pub fn motion(self: &Rc, time: u32, x: Fixed, y: Fixed) -> DynEventFormatter { + Box::new(Motion { + obj: self.clone(), + time, + surface_x: x, + surface_y: y, + }) + } + + pub fn button( + self: &Rc, + serial: u32, + time: u32, + button: u32, + state: u32, + ) -> DynEventFormatter { + Box::new(Button { + obj: self.clone(), + serial, + time, + button, + state, + }) + } + + pub fn axis(self: &Rc, time: u32, axis: u32, value: Fixed) -> DynEventFormatter { + Box::new(Axis { + obj: self.clone(), + time, + axis, + value, + }) + } + + pub fn frame(self: &Rc) -> DynEventFormatter { + Box::new(Frame { obj: self.clone() }) + } + + pub fn axis_source(self: &Rc, axis_source: u32) -> DynEventFormatter { + Box::new(AxisSource { + obj: self.clone(), + axis_source, + }) + } + + pub fn axis_stop(self: &Rc, time: u32, axis: u32) -> DynEventFormatter { + Box::new(AxisStop { + obj: self.clone(), + time, + axis, + }) + } + + pub fn axis_discrete(self: &Rc, axis: u32, discrete: i32) -> DynEventFormatter { + Box::new(AxisDiscrete { + obj: self.clone(), + axis, + discrete, + }) + } + + async fn set_cursor(&self, parser: MsgParser<'_, '_>) -> Result<(), SetCursorError> { + let _req: Release = self.seat.client.parse(self, parser)?; + self.seat.client.remove_obj(self).await?; + Ok(()) + } + + async fn release(&self, parser: MsgParser<'_, '_>) -> Result<(), ReleaseError> { + let _req: Release = self.seat.client.parse(self, parser)?; + self.seat.client.remove_obj(self).await?; + Ok(()) + } + + async fn handle_request_( + &self, + request: u32, + parser: MsgParser<'_, '_>, + ) -> Result<(), WlPointerError> { + match request { + RELEASE => self.release(parser).await?, + _ => unreachable!(), + } + Ok(()) + } +} + +handle_request!(WlPointer); + +impl Object for WlPointer { + fn id(&self) -> ObjectId { + self.id.into() + } + + fn interface(&self) -> Interface { + Interface::WlPointer + } + + fn num_requests(&self) -> u32 { + RELEASE + 1 + } +} diff --git a/src/ifs/wl_seat/wl_pointer/types.rs b/src/ifs/wl_seat/wl_pointer/types.rs new file mode 100644 index 00000000..987811fa --- /dev/null +++ b/src/ifs/wl_seat/wl_pointer/types.rs @@ -0,0 +1,299 @@ +use crate::client::{ClientError, EventFormatter, RequestParser}; +use crate::fixed::Fixed; +use crate::ifs::wl_seat::wl_pointer::{ + WlPointer, AXIS, AXIS_DISCRETE, AXIS_SOURCE, AXIS_STOP, BUTTON, ENTER, FRAME, LEAVE, MOTION, +}; +use crate::ifs::wl_surface::WlSurfaceId; +use crate::object::Object; +use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; +use std::fmt::{Debug, Formatter}; +use std::ops::Deref; +use std::rc::Rc; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum WlPointerError { + #[error(transparent)] + ClientError(Box), + #[error("Could not process a `set_cursor` request")] + SetCursorError(#[from] SetCursorError), + #[error("Could not process a `release` request")] + ReleaseError(#[from] ReleaseError), +} +efrom!(WlPointerError, ClientError, ClientError); + +#[derive(Debug, Error)] +pub enum SetCursorError { + #[error("Parsing failed")] + ParseError(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(SetCursorError, ParseError, MsgParserError); +efrom!(SetCursorError, ClientError, ClientError); + +#[derive(Debug, Error)] +pub enum ReleaseError { + #[error("Parsing failed")] + ParseError(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(ReleaseError, ParseError, MsgParserError); +efrom!(ReleaseError, ClientError, ClientError); + +pub(super) struct SetCursor { + pub serial: u32, + pub surface: WlSurfaceId, + pub hotspot_x: i32, + pub hotspot_y: i32, +} +impl RequestParser<'_> for SetCursor { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self { + serial: parser.uint()?, + surface: parser.object()?, + hotspot_x: parser.int()?, + hotspot_y: parser.int()?, + }) + } +} +impl Debug for SetCursor { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "set_cursor(serial: {}, surface: {}, hotspot_x: {}, hotspot_y: {})", + self.serial, self.surface, self.hotspot_x, self.hotspot_y + ) + } +} + +pub(super) struct Release; +impl RequestParser<'_> for Release { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self) + } +} +impl Debug for Release { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "destroy()",) + } +} + +pub(super) struct Enter { + pub obj: Rc, + pub serial: u32, + pub surface: WlSurfaceId, + pub surface_x: Fixed, + pub surface_y: Fixed, +} +impl EventFormatter for Enter { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, ENTER) + .uint(self.serial) + .object(self.surface) + .fixed(self.surface_x) + .fixed(self.surface_y); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for Enter { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "enter(serial: {}, surface: {}, surface_x: {}, surface_y: {})", + self.serial, self.surface, self.surface_x, self.surface_y + ) + } +} + +pub(super) struct Leave { + pub obj: Rc, + pub serial: u32, + pub surface: WlSurfaceId, +} +impl EventFormatter for Leave { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, LEAVE) + .uint(self.serial) + .object(self.surface); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for Leave { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "leave(serial: {}, surface: {})", + self.serial, self.surface + ) + } +} + +pub(super) struct Motion { + pub obj: Rc, + pub time: u32, + pub surface_x: Fixed, + pub surface_y: Fixed, +} +impl EventFormatter for Motion { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, MOTION) + .uint(self.time) + .fixed(self.surface_x) + .fixed(self.surface_y); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for Motion { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "motion(time: {}, surface_x: {}, surface_y: {})", + self.time, self.surface_x, self.surface_y + ) + } +} + +pub(super) struct Button { + pub obj: Rc, + pub serial: u32, + pub time: u32, + pub button: u32, + pub state: u32, +} +impl EventFormatter for Button { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, BUTTON) + .uint(self.serial) + .uint(self.time) + .uint(self.button) + .uint(self.state); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for Button { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "button(serial: {}, time: {}, button: {}, state: {})", + self.serial, self.time, self.button, self.state + ) + } +} + +pub(super) struct Axis { + pub obj: Rc, + pub time: u32, + pub axis: u32, + pub value: Fixed, +} +impl EventFormatter for Axis { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, AXIS) + .uint(self.time) + .uint(self.axis) + .fixed(self.value); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for Axis { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "axis(time: {}, axis: {}, value: {:?})", + self.time, self.axis, self.value + ) + } +} + +pub(super) struct Frame { + pub obj: Rc, +} +impl EventFormatter for Frame { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, FRAME); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for Frame { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "frame()") + } +} + +pub(super) struct AxisSource { + pub obj: Rc, + pub axis_source: u32, +} +impl EventFormatter for AxisSource { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, AXIS_SOURCE).uint(self.axis_source); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for AxisSource { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "axis_source(axis_source: {})", self.axis_source) + } +} + +pub(super) struct AxisStop { + pub obj: Rc, + pub time: u32, + pub axis: u32, +} +impl EventFormatter for AxisStop { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, AXIS_STOP) + .uint(self.time) + .uint(self.axis); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for AxisStop { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "axis_stop(time: {}, axis: {})", self.time, self.axis) + } +} + +pub(super) struct AxisDiscrete { + pub obj: Rc, + pub axis: u32, + pub discrete: i32, +} +impl EventFormatter for AxisDiscrete { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, AXIS_DISCRETE) + .uint(self.axis) + .int(self.discrete); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for AxisDiscrete { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "axis_discrete(axis: {}, discrete: {})", + self.axis, self.discrete + ) + } +} diff --git a/src/ifs/wl_seat/wl_touch/mod.rs b/src/ifs/wl_seat/wl_touch/mod.rs new file mode 100644 index 00000000..dd167e4c --- /dev/null +++ b/src/ifs/wl_seat/wl_touch/mod.rs @@ -0,0 +1,68 @@ +mod types; + +use crate::client::{AddObj}; +use crate::ifs::wl_seat::WlSeatObj; +use crate::object::{Interface, Object, ObjectId}; +use crate::utils::buffd::MsgParser; +use std::rc::Rc; +pub use types::*; + +const RELEASE: u32 = 0; + +const DOWN: u32 = 0; +const UP: u32 = 1; +const MOTION: u32 = 2; +const FRAME: u32 = 3; +const CANCEL: u32 = 4; +const SHAPE: u32 = 5; +const ORIENTATION: u32 = 6; + +id!(WlTouchId); + +pub struct WlTouch { + id: WlTouchId, + seat: Rc, +} + +impl WlTouch { + pub fn new(id: WlTouchId, seat: &Rc) -> Self { + Self { + id, + seat: seat.clone(), + } + } + + async fn release(&self, parser: MsgParser<'_, '_>) -> Result<(), ReleaseError> { + let _req: Release = self.seat.client.parse(self, parser)?; + self.seat.client.remove_obj(self).await?; + Ok(()) + } + + async fn handle_request_( + &self, + request: u32, + parser: MsgParser<'_, '_>, + ) -> Result<(), WlTouchError> { + match request { + RELEASE => self.release(parser).await?, + _ => unreachable!(), + } + Ok(()) + } +} + +handle_request!(WlTouch); + +impl Object for WlTouch { + fn id(&self) -> ObjectId { + self.id.into() + } + + fn interface(&self) -> Interface { + Interface::WlTouch + } + + fn num_requests(&self) -> u32 { + RELEASE + 1 + } +} diff --git a/src/ifs/wl_seat/wl_touch/types.rs b/src/ifs/wl_seat/wl_touch/types.rs new file mode 100644 index 00000000..b0861688 --- /dev/null +++ b/src/ifs/wl_seat/wl_touch/types.rs @@ -0,0 +1,35 @@ +use crate::client::{ClientError, RequestParser}; +use crate::utils::buffd::{MsgParser, MsgParserError}; +use std::fmt::{Debug, Formatter}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum WlTouchError { + #[error(transparent)] + ClientError(Box), + #[error("Could not process a `release` request")] + ReleaseError(#[from] ReleaseError), +} +efrom!(WlTouchError, ClientError, ClientError); + +#[derive(Debug, Error)] +pub enum ReleaseError { + #[error("Parsing failed")] + ParseError(#[source] Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(ReleaseError, ParseError, MsgParserError); +efrom!(ReleaseError, ClientError, ClientError); + +pub(super) struct Release; +impl RequestParser<'_> for Release { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self) + } +} +impl Debug for Release { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "destroy()",) + } +} diff --git a/src/main.rs b/src/main.rs index e653af2c..3788e93e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,6 +40,7 @@ mod backends; mod client; mod clientmem; mod event_loop; +mod fixed; mod format; mod globals; mod ifs; @@ -54,7 +55,6 @@ mod tree; mod utils; mod wheel; mod xkbcommon; -mod fixed; fn main() { env_logger::builder() diff --git a/src/object.rs b/src/object.rs index 73af628f..ba1e5cec 100644 --- a/src/object.rs +++ b/src/object.rs @@ -52,6 +52,9 @@ pub enum Interface { WlRegistry, WlShm, WlShmPool, + WlTouch, + WlPointer, + WlKeyboard, WlSubcompositor, XdgWmBase, XdgPositioner, @@ -86,6 +89,9 @@ impl Interface { Interface::WlBuffer => "wl_buffer", Interface::WlOutput => "wl_output", Interface::WlSeat => "wl_seat", + Interface::WlTouch => "wl_touch", + Interface::WlPointer => "wl_pointer", + Interface::WlKeyboard => "wl_keyboard", } } } diff --git a/src/utils/buffd/buf_out.rs b/src/utils/buffd/buf_out.rs index 5f93a4ee..4f89824c 100644 --- a/src/utils/buffd/buf_out.rs +++ b/src/utils/buffd/buf_out.rs @@ -3,6 +3,7 @@ use crate::utils::buffd::{BufFdError, BUF_SIZE, CMSG_BUF_SIZE}; use futures::{select, FutureExt}; use std::collections::VecDeque; use std::mem::MaybeUninit; +use std::rc::Rc; use std::slice; use uapi::{c, Errno, OwnedFd}; @@ -10,7 +11,7 @@ pub(super) const OUT_BUF_SIZE: usize = 2 * BUF_SIZE; pub(super) struct MsgFds { pub(super) pos: usize, - pub(super) fds: Vec, + pub(super) fds: Vec>, } pub struct BufFdOut { @@ -20,6 +21,7 @@ pub struct BufFdOut { pub(super) out_buf: *mut [MaybeUninit; OUT_BUF_SIZE], pub(super) fds: VecDeque, + fd_ids: Vec, cmsg_buf: Box<[MaybeUninit; CMSG_BUF_SIZE]>, } @@ -30,6 +32,7 @@ impl BufFdOut { out_pos: 0, out_buf: Box::into_raw(Box::new([MaybeUninit::::uninit(); OUT_BUF_SIZE / 4])) as _, fds: Default::default(), + fd_ids: vec![], cmsg_buf: Box::new([MaybeUninit::uninit(); CMSG_BUF_SIZE]), } } @@ -75,13 +78,15 @@ impl BufFdOut { let mut f = self.fds.front().map(|f| f.pos); if f == Some(*pos) { let fds = self.fds.pop_front().unwrap(); + self.fd_ids.clear(); + self.fd_ids.extend(fds.fds.iter().map(|f| f.raw())); let hdr = c::cmsghdr { cmsg_len: 0, cmsg_level: c::SOL_SOCKET, cmsg_type: c::SCM_RIGHTS, }; let mut cmsg_buf = &mut self.cmsg_buf[..]; - cmsg_len = uapi::cmsg_write(&mut cmsg_buf, hdr, &fds.fds[..]).unwrap(); + cmsg_len = uapi::cmsg_write(&mut cmsg_buf, hdr, &self.fd_ids[..]).unwrap(); fds_opt = Some(fds); f = self.fds.front().map(|f| f.pos) } diff --git a/src/utils/buffd/formatter.rs b/src/utils/buffd/formatter.rs index cd201838..85e0cd7c 100644 --- a/src/utils/buffd/formatter.rs +++ b/src/utils/buffd/formatter.rs @@ -1,18 +1,19 @@ +use crate::fixed::Fixed; use crate::object::ObjectId; use crate::utils::buffd::buf_out::{BufFdOut, MsgFds}; use std::mem; use std::mem::MaybeUninit; +use std::rc::Rc; use uapi::OwnedFd; -use crate::fixed::Fixed; pub struct MsgFormatter<'a> { buf: &'a mut BufFdOut, pos: usize, - fds: &'a mut Vec, + fds: &'a mut Vec>, } impl<'a> MsgFormatter<'a> { - pub fn new(buf: &'a mut BufFdOut, fds: &'a mut Vec) -> Self { + pub fn new(buf: &'a mut BufFdOut, fds: &'a mut Vec>) -> Self { Self { pos: buf.out_pos, buf, @@ -46,7 +47,7 @@ impl<'a> MsgFormatter<'a> { self } - pub fn fd(&mut self, fd: OwnedFd) -> &mut Self { + pub fn fd(&mut self, fd: Rc) -> &mut Self { self.fds.push(fd); self } diff --git a/src/utils/buffd/parser.rs b/src/utils/buffd/parser.rs index e7aafa81..38fdf601 100644 --- a/src/utils/buffd/parser.rs +++ b/src/utils/buffd/parser.rs @@ -1,10 +1,10 @@ +use crate::fixed::Fixed; use crate::globals::GlobalName; use crate::object::ObjectId; use crate::utils::buffd::BufFdIn; use bstr::{BStr, ByteSlice}; use thiserror::Error; use uapi::OwnedFd; -use crate::fixed::Fixed; #[derive(Debug, Error)] pub enum MsgParserError { diff --git a/src/xkbcommon/mod.rs b/src/xkbcommon/mod.rs index 5d67e434..d6eb81a6 100644 --- a/src/xkbcommon/mod.rs +++ b/src/xkbcommon/mod.rs @@ -53,8 +53,10 @@ extern "C" { keymap: *mut xkb_keymap, format: xkb_keymap_format, ) -> *mut c::c_char; + fn xkb_keymap_ref(keymap: *mut xkb_keymap) -> *mut xkb_keymap; fn xkb_keymap_unref(keymap: *mut xkb_keymap); fn xkb_state_unref(state: *mut xkb_state); + fn xkb_state_get_keymap(state: *mut xkb_state) -> *mut xkb_keymap; } pub struct XkbContext { @@ -129,6 +131,18 @@ pub struct XkbState { state: *mut xkb_state, } +impl XkbState { + pub fn keymap(&self) -> XkbKeymap { + unsafe { + let res = xkb_state_get_keymap(self.state); + xkb_keymap_ref(res); + XkbKeymap { + keymap: res, + } + } + } +} + impl Drop for XkbState { fn drop(&mut self) { unsafe {