1
0
Fork 0
forked from wry/wry

autocommit 2022-02-16 18:14:14 CET

This commit is contained in:
Julian Orth 2022-02-16 18:14:14 +01:00
parent 086f2f73f4
commit 8d0b82c37c
17 changed files with 220 additions and 42 deletions

View file

@ -6,6 +6,9 @@ linear_ids!(OutputIds, OutputId);
linear_ids!(KeyboardIds, KeyboardId);
linear_ids!(MouseIds, MouseId);
pub trait Backend {
}
pub trait Output {
fn id(&self) -> OutputId;
fn removed(&self) -> bool;
@ -19,6 +22,7 @@ pub trait Keyboard {
fn removed(&self) -> bool;
fn event(&self) -> Option<KeyboardEvent>;
fn on_change(&self, cb: Rc<dyn Fn()>);
fn grab(&self, grab: bool);
}
pub trait Mouse {

15
src/backends/dummy.rs Normal file
View file

@ -0,0 +1,15 @@
use std::rc::Rc;
use crate::backend::Backend;
pub struct DummyBackend {
}
impl DummyBackend {
pub fn new() -> Rc<Self> {
Rc::new(Self { })
}
}
impl Backend for DummyBackend {
}

View file

@ -1 +1,2 @@
pub mod xorg;
pub mod dummy;

View file

@ -1,7 +1,4 @@
use crate::backend::{
BackendEvent, KeyState, Keyboard, KeyboardEvent, KeyboardId, Mouse, MouseEvent, MouseId,
Output, OutputId, ScrollAxis,
};
use crate::backend::{BackendEvent, KeyState, Keyboard, KeyboardEvent, KeyboardId, Mouse, MouseEvent, MouseId, Output, OutputId, ScrollAxis, Backend};
use crate::drm::drm::{Drm, DrmError};
use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING};
use crate::drm::{ModifiedFormat, INVALID_MODIFIER};
@ -14,7 +11,7 @@ use crate::utils::clonecell::CloneCell;
use crate::utils::copyhashmap::CopyHashMap;
use crate::utils::ptr_ext::PtrExt;
use crate::wheel::{WheelDispatcher, WheelId};
use crate::{EventLoopError, NumCell, State, WheelError};
use crate::{ErrorFmt, EventLoopError, NumCell, State, WheelError};
use isnt::std_1::primitive::IsntConstPtrExt;
use rand::Rng;
use std::cell::{Cell, RefCell};
@ -214,6 +211,9 @@ pub struct XorgBackend {
b: Cell<f32>,
}
impl Backend for XorgBackend {
}
fn get_drm(con: &XcbCon) -> Result<Drm, XorgBackendError> {
unsafe {
let mut err = ptr::null_mut();
@ -555,7 +555,7 @@ impl XorgBackend {
kb_id: self.state.kb_ids.next(),
mouse_id: self.state.mouse_ids.next(),
backend: self.clone(),
_kb: info.deviceid,
kb: info.deviceid,
mouse: info.attachment,
removed: Cell::new(false),
kb_cb: Default::default(),
@ -998,7 +998,7 @@ struct XorgSeat {
kb_id: KeyboardId,
mouse_id: MouseId,
backend: Rc<XorgBackend>,
_kb: ffi::xcb_input_device_id_t,
kb: ffi::xcb_input_device_id_t,
mouse: ffi::xcb_input_device_id_t,
removed: Cell<bool>,
kb_cb: CloneCell<Option<Rc<dyn Fn()>>>,
@ -1080,6 +1080,43 @@ impl Keyboard for XorgSeat {
fn on_change(&self, cb: Rc<dyn Fn()>) {
self.kb_cb.set(Some(cb));
}
fn grab(&self, grab: bool) {
unsafe {
let con = &self.backend.con;
let mut err = ptr::null_mut();
if grab {
let res = con.input.xcb_input_xi_grab_device(
con.c,
con.screen.root,
0,
0,
self.kb,
ffi::XCB_GRAB_MODE_ASYNC as _,
ffi::XCB_GRAB_MODE_ASYNC as _,
1,
0,
ptr::null(),
);
let res = con.input.xcb_input_xi_grab_device_reply(con.c, res, &mut err);
let res = match con.check(res, err) {
Ok(r) => r,
Err(e) => {
log::error!("Could not grab device {}: {}", self.kb, ErrorFmt(e));
return;
}
};
if res.status != ffi::XCB_GRAB_STATUS_SUCCESS as _ {
log::error!("Could not grab device {}: status = {}", self.kb, res.status);
}
} else {
let cookie = con.input.xcb_input_xi_ungrab_device_checked(con.c, 0, self.kb);
if let Err(e) = con.check_cookie(cookie) {
log::error!("Could not ungrab device {}: {}", self.kb, ErrorFmt(e));
}
}
}
}
}
impl Mouse for XorgSeat {

View file

@ -1,12 +1,12 @@
use crate::backend::{KeyboardId, MouseId};
use crate::ifs::wl_seat::WlSeatGlobal;
use crate::state::DeviceHandlerData;
use crate::ifs::wl_seat::{SeatId, WlSeatGlobal};
use crate::state::{DeviceHandlerData};
use crate::tree::ContainerSplit;
use crate::utils::copyhashmap::CopyHashMap;
use crate::utils::debug_fn::debug_fn;
use crate::utils::stack::Stack;
use crate::xkbcommon::XkbKeymap;
use crate::{ErrorFmt, NumCell, State};
use crate::{backend, ErrorFmt, NumCell, State};
use bincode::error::DecodeError;
use i4config::_private::bincode_ops;
use i4config::_private::ipc::{ClientMessage, Response, ServerMessage};
@ -181,6 +181,14 @@ impl ConfigProxyHandler {
Err(CphError::SeatDoesNotExist(seat))
}
fn get_kb(&self, kb: Keyboard) -> Result<Rc<dyn backend::Keyboard>, CphError> {
let kbs = self.state.kb_handlers.borrow_mut();
match kbs.get(&(KeyboardId::from_raw(kb.0 as _))) {
None => Err(CphError::KeyboardDoesNotExist(kb)),
Some(kb) => Ok(kb.kb.clone()),
}
}
fn get_keymap(&self, keymap: Keymap) -> Result<Rc<XkbKeymap>, CphError> {
match self.keymaps.get(&keymap) {
Some(k) => Ok(k),
@ -229,18 +237,44 @@ impl ConfigProxyHandler {
Ok(())
}
fn handle_get_input_devices(&self) -> Result<(), GetInputDevicesError> {
fn handle_remove_shortcut(
&self,
seat: Seat,
mods: Modifiers,
sym: KeySym,
) -> Result<(), AddShortcutError> {
let seat = self.get_seat(seat)?;
seat.remove_shortcut(mods, sym);
Ok(())
}
fn handle_get_input_devices(&self, seat: Option<Seat>) -> Result<(), GetInputDevicesError> {
let id = seat.map(|s| SeatId::from_raw(s.0 as _));
let matches = |dhd: &DeviceHandlerData| {
let id = match id {
Some(id) => id,
_ => return true,
};
if let Some(seat) = dhd.seat.get() {
return seat.id() == id;
}
false
};
let mut res = vec![];
{
let devs = self.state.kb_handlers.borrow_mut();
for dev in devs.values() {
res.push(InputDevice::Keyboard(Keyboard(dev.id.raw() as _)));
if matches(&dev.data) {
res.push(InputDevice::Keyboard(Keyboard(dev.id.raw() as _)));
}
}
}
{
let devs = self.state.mouse_handlers.borrow_mut();
for dev in devs.values() {
res.push(InputDevice::Mouse(Mouse(dev.id.raw() as _)));
if matches(&dev.data) {
res.push(InputDevice::Mouse(Mouse(dev.id.raw() as _)));
}
}
}
self.send(&ServerMessage::Response {
@ -277,6 +311,16 @@ impl ConfigProxyHandler {
Ok(())
}
fn handle_grab(
&self,
kb: Keyboard,
grab: bool,
) -> Result<(), GrabError> {
let kb = self.get_kb(kb)?;
kb.grab(grab);
Ok(())
}
pub fn handle_request(&self, msg: &[u8]) {
if let Err(e) = self.handle_request_(msg) {
log::error!("Could not handle client request: {}", ErrorFmt(e));
@ -311,13 +355,16 @@ impl ConfigProxyHandler {
ClientMessage::AddShortcut { seat, mods, sym } => {
self.handle_add_shortcut(seat, mods, sym)?
}
ClientMessage::RemoveShortcut { .. } => {}
ClientMessage::RemoveShortcut { seat, mods, sym } => {
self.handle_remove_shortcut(seat, mods, sym)?
}
ClientMessage::Focus { seat, direction } => self.handle_focus(seat, direction)?,
ClientMessage::Move { seat, direction } => {}
ClientMessage::GetInputDevices => self.handle_get_input_devices()?,
ClientMessage::GetInputDevices { seat } => self.handle_get_input_devices(seat)?,
ClientMessage::GetSeats => self.handle_get_seats()?,
ClientMessage::RemoveSeat { .. } => {}
ClientMessage::Run { prog, args, env } => self.handle_run(prog, args, env)?,
ClientMessage::GrabKb { kb, grab } => self.handle_grab(kb, grab)?,
}
Ok(())
}
@ -335,6 +382,8 @@ enum CphError {
SetSeatError(#[from] SetSeatError),
#[error("Could not process a `add_shortcut` request")]
AddShortcutError(#[from] AddShortcutError),
#[error("Could not process a `remove_shortcut` request")]
RemoveShortcutError(#[from] RemoveShortcutError),
#[error("Could not process a `get_input_devices` request")]
GetInputDevicesError(#[from] GetInputDevicesError),
#[error("Could not process a `get_seats` request")]
@ -353,12 +402,16 @@ enum CphError {
GetSplitError(#[from] GetSplitError),
#[error("Could not process a `run` request")]
RunError(#[from] RunError),
#[error("Could not process a `grab` request")]
GrabError(#[from] GrabError),
#[error("Device {0:?} does not exist")]
DeviceDoesNotExist(InputDevice),
#[error("Device {0:?} does not exist")]
KeymapDoesNotExist(Keymap),
#[error("Seat {0:?} does not exist")]
SeatDoesNotExist(Seat),
#[error("Keyboard {0:?} does not exist")]
KeyboardDoesNotExist(Keyboard),
#[error("Could not parse the message")]
ParsingFailed(#[source] DecodeError),
}
@ -389,6 +442,13 @@ enum AddShortcutError {
}
efrom!(AddShortcutError, CphError);
#[derive(Debug, Error)]
enum RemoveShortcutError {
#[error(transparent)]
CphError(#[from] Box<CphError>),
}
efrom!(RemoveShortcutError, CphError);
#[derive(Debug, Error)]
enum GetInputDevicesError {}
@ -446,3 +506,10 @@ enum RunError {
#[error("The ol' forker is not available")]
NoForker,
}
#[derive(Debug, Error)]
enum GrabError {
#[error(transparent)]
CphError(#[from] Box<CphError>),
}
efrom!(GrabError, CphError);

View file

@ -189,6 +189,7 @@ impl Forker {
env::set_var("XDG_SESSION_TYPE", "wayland");
env::remove_var("DISPLAY");
env::remove_var("WAYLAND_DISPLAY");
setup_name("the ol' forker");
setup_deathsig(ppid);
reset_signals();
let socket = Rc::new(setup_fds(socket));
@ -349,3 +350,10 @@ fn setup_deathsig(ppid: c::pid_t) {
}
}
}
fn setup_name(name: &str) {
unsafe {
let name = name.into_ustr();
c::prctl(c::PR_SET_NAME, name.as_ptr());
}
}

View file

@ -371,6 +371,10 @@ impl WlSeatGlobal {
self.shortcuts.set((mods.0, keysym.0), mods);
}
pub fn remove_shortcut(&self, mods: Modifiers, keysym: KeySym) {
self.shortcuts.remove(&(mods.0, keysym.0));
}
pub fn trigger_tree_changed(&self) {
self.tree_changed.trigger();
}

View file

@ -40,6 +40,8 @@ use std::ops::Deref;
use std::rc::Rc;
use thiserror::Error;
use wheel::Wheel;
use crate::backends::dummy::DummyBackend;
use crate::utils::clonecell::CloneCell;
#[macro_use]
mod macros;
@ -125,6 +127,7 @@ fn main_() -> Result<(), MainError> {
let state = Rc::new(State {
xkb_ctx,
forker: Default::default(),
backend: CloneCell::new(DummyBackend::new()),
default_keymap: xkb_keymap,
eng: engine.clone(),
el: el.clone(),
@ -152,13 +155,14 @@ fn main_() -> Result<(), MainError> {
kb_handlers: Default::default(),
});
forker.install(&state);
let backend = XorgBackend::new(&state)?;
state.backend.set(backend);
let config = config::ConfigProxy::default(&state);
state.config.set(Some(Rc::new(config)));
let _global_event_handler = engine.spawn(tasks::handle_backend_events(state.clone()));
let _slow_client_handler = engine.spawn(tasks::handle_slow_clients(state.clone()));
let socket_path = Acceptor::install(&state)?;
forker.setenv(b"WAYLAND_DISPLAY", socket_path.as_bytes());
let _backend = XorgBackend::new(&state)?;
el.run()?;
state.clients.clear();
for (_, seat) in state.globals.seats.lock().deref() {

View file

@ -1,7 +1,5 @@
use crate::async_engine::{AsyncEngine, SpawnedFuture};
use crate::backend::{
BackendEvent, KeyboardId, KeyboardIds, MouseId, MouseIds, OutputId, OutputIds,
};
use crate::backend::{Backend, BackendEvent, Keyboard, KeyboardId, KeyboardIds, MouseId, MouseIds, OutputId, OutputIds};
use crate::client::{Client, Clients};
use crate::config::ConfigProxy;
use crate::cursor::ServerCursors;
@ -27,6 +25,7 @@ use std::rc::Rc;
pub struct State {
pub xkb_ctx: XkbContext,
pub forker: CloneCell<Option<Rc<ForkerProxy>>>,
pub backend: CloneCell<Rc<dyn Backend>>,
pub default_keymap: Rc<XkbKeymap>,
pub eng: Rc<AsyncEngine>,
pub el: Rc<EventLoop>,
@ -63,6 +62,7 @@ pub struct MouseData {
pub struct KeyboardData {
pub handler: SpawnedFuture<()>,
pub id: KeyboardId,
pub kb: Rc<dyn Keyboard>,
pub data: Rc<DeviceHandlerData>,
}

View file

@ -14,7 +14,7 @@ pub trait DeviceApi: 'static {
fn announce(&self, config: &ConfigProxy);
fn announce_del(&self, config: &ConfigProxy);
fn removed(&self) -> bool;
fn add(&self, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>);
fn add(self: &Rc<Self>, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>);
fn remove(&self, state: &State);
fn event(&self) -> Option<Self::Event>;
fn send(seat: &Rc<WlSeatGlobal>, event: Self::Event);
@ -39,12 +39,13 @@ impl DeviceApi for dyn Keyboard {
self.removed()
}
fn add(&self, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>) {
fn add(self: &Rc<Self>, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>) {
state.kb_handlers.borrow_mut().insert(
self.id(),
KeyboardData {
handler,
id: self.id(),
kb: self.clone(),
data,
},
);
@ -82,7 +83,7 @@ impl DeviceApi for dyn Mouse {
self.removed()
}
fn add(&self, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>) {
fn add(self: &Rc<Self>, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>) {
state.mouse_handlers.borrow_mut().insert(
self.id(),
MouseData {