1
0
Fork 0
forked from wry/wry

autocommit 2022-03-30 18:10:37 CEST

This commit is contained in:
Julian Orth 2022-03-30 18:10:37 +02:00
parent c4854c4d7d
commit a8136ed88c
17 changed files with 189 additions and 81 deletions

View file

@ -12,6 +12,7 @@ use jay_config::{
config, create_seat, input_devices, on_new_input_device, quit, switch_to_vt, Command, Seat,
};
use rand::Rng;
use jay_config::input::CAP_KEYBOARD;
const MOD: Modifiers = ALT;
@ -93,12 +94,14 @@ fn configure_seat(s: Seat) {
fn do_grab(s: Seat, grab: bool) {
for device in s.input_devices() {
log::info!(
"{}rabbing keyboard {:?}",
if grab { "G" } else { "Ung" },
device.0
);
grab_input_device(device, grab);
if device.has_capability(CAP_KEYBOARD) {
log::info!(
"{}rabbing keyboard {:?}",
if grab { "G" } else { "Ung" },
device.0
);
grab_input_device(device, grab);
}
}
if grab {
s.unbind(SYM_y);

View file

@ -4,13 +4,14 @@ use crate::_private::ipc::{ClientMessage, InitMessage, Response, ServerMessage};
use crate::_private::{bincode_ops, logging, Config, ConfigEntry, ConfigEntryGen, VERSION};
use crate::keyboard::keymap::Keymap;
use crate::theme::Color;
use crate::{Axis, Command, Direction, InputDevice, LogLevel, ModifiedKeySym, Seat};
use crate::{Axis, Command, Direction, LogLevel, ModifiedKeySym, Seat};
use std::cell::{Cell, RefCell};
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::ops::Deref;
use std::rc::Rc;
use std::{ptr, slice};
use crate::input::{Capability, InputDevice};
pub(crate) struct Client {
configure: extern "C" fn(),
@ -317,6 +318,17 @@ impl Client {
self.send(&ClientMessage::SetSeat { device, seat })
}
pub fn has_capability(&self, device: InputDevice, cap: Capability) -> bool {
let res = self.with_response(|| self.send(&ClientMessage::HasCapability { device, cap }));
match res {
Response::HasCapability { has } => has,
_ => {
log::error!("Server did not send a response to a has_capability request");
false
}
}
}
pub fn seat_set_keymap(&self, seat: Seat, keymap: Keymap) {
self.send(&ClientMessage::SeatSetKeymap { seat, keymap })
}

View file

@ -2,8 +2,9 @@ use crate::keyboard::keymap::Keymap;
use crate::keyboard::mods::Modifiers;
use crate::keyboard::syms::KeySym;
use crate::theme::Color;
use crate::{Axis, Direction, InputDevice, LogLevel, Seat};
use crate::{Axis, Direction, LogLevel, Seat};
use bincode::{BorrowDecode, Decode, Encode};
use crate::input::{Capability, InputDevice};
#[derive(Encode, BorrowDecode, Debug)]
pub enum ServerMessage {
@ -136,6 +137,10 @@ pub enum ClientMessage<'a> {
ToggleFloating {
seat: Seat,
},
HasCapability {
device: InputDevice,
cap: Capability,
},
}
#[derive(Encode, Decode, Debug)]
@ -150,6 +155,7 @@ pub enum Response {
GetInputDevices { devices: Vec<InputDevice> },
GetTitleHeight { height: i32 },
GetBorderWidth { width: i32 },
HasCapability { has: bool },
}
#[derive(Encode, Decode, Debug)]

View file

@ -1,4 +1,4 @@
use crate::InputDevice;
use crate::input::InputDevice;
pub fn grab_input_device(kb: InputDevice, grab: bool) {
get!().grab(kb, grab);

26
jay-config/src/input.rs Normal file
View file

@ -0,0 +1,26 @@
use bincode::{Decode, Encode};
use crate::Seat;
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub struct InputDevice(pub u64);
impl InputDevice {
pub fn set_seat(self, seat: Seat) {
get!().set_seat(self, seat)
}
pub fn has_capability(self, cap: Capability) -> bool {
get!(false).has_capability(self, cap)
}
}
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub struct Capability(pub u32);
pub const CAP_KEYBOARD: Capability = Capability(0);
pub const CAP_POINTER: Capability = Capability(1);
pub const CAP_TOUCH: Capability = Capability(2);
pub const CAP_TABLET_TOOL: Capability = Capability(3);
pub const CAP_TABLET_PAD: Capability = Capability(4);
pub const CAP_GESTURE: Capability = Capability(5);
pub const CAP_SWITCH: Capability = Capability(6);

View file

@ -2,6 +2,7 @@ use crate::keyboard::keymap::Keymap;
use crate::keyboard::ModifiedKeySym;
use bincode::{Decode, Encode};
use std::collections::HashMap;
use crate::input::InputDevice;
#[macro_use]
mod macros;
@ -10,6 +11,7 @@ pub mod _private;
pub mod embedded;
pub mod keyboard;
pub mod theme;
pub mod input;
#[derive(Encode, Decode, Copy, Clone, Debug)]
pub enum LogLevel {
@ -39,15 +41,6 @@ impl Seat {
}
}
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub struct InputDevice(pub u64);
impl InputDevice {
pub fn set_seat(self, seat: Seat) {
get!().set_seat(self, seat)
}
}
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum Axis {
Horizontal,

View file

@ -17,11 +17,14 @@ macro_rules! config {
macro_rules! get {
() => {{
get!(())
}};
($def:expr) => {{
#[allow(unused_unsafe)]
let client = unsafe {
let client = crate::_private::client::CLIENT.with(|client| client.get());
if client.is_null() {
return;
return $def;
}
&*client
};

View file

@ -23,6 +23,18 @@ pub trait InputDevice {
fn event(&self) -> Option<InputEvent>;
fn on_change(&self, cb: Rc<dyn Fn()>);
fn grab(&self, grab: bool);
fn has_capability(&self, cap: InputDeviceCapability) -> bool;
}
#[derive(Debug, Copy, Clone)]
pub enum InputDeviceCapability {
Keyboard,
Pointer,
Touch,
TabletTool,
TabletPad,
Gesture,
Switch,
}
pub enum BackendEvent {

View file

@ -3,7 +3,7 @@ mod monitor;
mod video;
use crate::async_engine::{AsyncError, AsyncFd};
use crate::backend::{Backend, InputDevice, InputDeviceId, InputEvent};
use crate::backend::{Backend, InputDevice, InputDeviceCapability, InputDeviceId, InputEvent};
use crate::backends::metal::video::{MetalDrmDevice, PendingDrmDevice};
use crate::dbus::DbusError;
use crate::drm::drm::DrmError;
@ -25,6 +25,7 @@ use std::future::pending;
use std::rc::Rc;
use thiserror::Error;
use uapi::{c, OwnedFd};
use crate::libinput::consts::{LIBINPUT_DEVICE_CAP_GESTURE, LIBINPUT_DEVICE_CAP_KEYBOARD, LIBINPUT_DEVICE_CAP_POINTER, LIBINPUT_DEVICE_CAP_SWITCH, LIBINPUT_DEVICE_CAP_TABLET_PAD, LIBINPUT_DEVICE_CAP_TABLET_TOOL, LIBINPUT_DEVICE_CAP_TOUCH};
#[derive(Debug, Error)]
pub enum MetalError {
@ -180,7 +181,7 @@ struct MetalInputDevice {
id: InputDeviceId,
_devnum: c::dev_t,
fd: CloneCell<Option<Rc<OwnedFd>>>,
inputdev: Cell<Option<RegisteredDevice>>,
inputdev: CloneCell<Option<Rc<RegisteredDevice>>>,
devnode: CString,
_sysname: CString,
removed: Cell<bool>,
@ -242,6 +243,22 @@ impl InputDevice for MetalInputDevice {
fn grab(&self, _grab: bool) {
// nothing
}
fn has_capability(&self, cap: InputDeviceCapability) -> bool {
let li = match cap {
InputDeviceCapability::Keyboard => LIBINPUT_DEVICE_CAP_KEYBOARD,
InputDeviceCapability::Pointer => LIBINPUT_DEVICE_CAP_POINTER,
InputDeviceCapability::Touch => LIBINPUT_DEVICE_CAP_TOUCH,
InputDeviceCapability::TabletTool => LIBINPUT_DEVICE_CAP_TABLET_TOOL,
InputDeviceCapability::TabletPad => LIBINPUT_DEVICE_CAP_TABLET_PAD,
InputDeviceCapability::Gesture => LIBINPUT_DEVICE_CAP_GESTURE,
InputDeviceCapability::Switch => LIBINPUT_DEVICE_CAP_SWITCH,
};
match self.inputdev.get() {
Some(dev) => dev.device().has_cap(li),
_ => false,
}
}
}
impl MetalInputDevice {

View file

@ -95,7 +95,7 @@ impl MetalBackend {
self.state.fdcloser.close(old);
}
let inputdev = match self.libinput.open(dev.devnode.as_c_str()) {
Ok(d) => d,
Ok(d) => Rc::new(d),
Err(_) => return,
};
inputdev.device().set_slot(dev.slot);
@ -314,7 +314,7 @@ impl MetalBackend {
}
dev.fd.set(Some(res.fd.clone()));
let inputdev = match slf.libinput.open(dev.devnode.as_c_str()) {
Ok(d) => d,
Ok(d) => Rc::new(d),
Err(_) => return,
};
inputdev.device().set_slot(slot);

View file

@ -1,8 +1,5 @@
use crate::async_engine::{Phase, SpawnedFuture};
use crate::backend::{
Backend, BackendEvent, InputDevice, InputDeviceId, InputEvent, KeyState, Output, OutputId,
ScrollAxis,
};
use crate::backend::{Backend, BackendEvent, InputDevice, InputDeviceCapability, InputDeviceId, InputEvent, KeyState, Output, OutputId, ScrollAxis};
use crate::drm::drm::{Drm, DrmError};
use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING};
use crate::drm::{ModifiedFormat, INVALID_MODIFIER};
@ -638,9 +635,12 @@ impl XBackendData {
return;
}
let image = &output.images[output.next_image.fetch_add(1) % output.images.len()];
let serial = output.serial.fetch_add(1);
let image = &output.images[output.next_image.fetch_add(1) % output.images.len()];
image.idle.set(false);
image.last_serial.set(serial);
if let Some(node) = self.state.root.outputs.get(&output.id) {
let fb = image.fb.get();
fb.render(&*node, &self.state, Some(node.position.get()));
@ -667,8 +667,6 @@ impl XBackendData {
log::error!("Could not present image: {:?}", e);
return;
}
image.idle.set(false);
image.last_serial.set(serial);
}
async fn handle_input_event(self: &Rc<Self>, event: &Event) -> Result<(), XBackendError> {
@ -958,6 +956,13 @@ impl InputDevice for XSeatKeyboard {
fn grab(&self, grab: bool) {
self.0.backend.grab_requests.push((self.0.clone(), grab));
}
fn has_capability(&self, cap: InputDeviceCapability) -> bool {
match cap {
InputDeviceCapability::Keyboard => true,
_ => false,
}
}
}
impl InputDevice for XSeatMouse {
@ -980,4 +985,11 @@ impl InputDevice for XSeatMouse {
fn grab(&self, _grab: bool) {
log::error!("Cannot grab xorg mouse");
}
fn has_capability(&self, cap: InputDeviceCapability) -> bool {
match cap {
InputDeviceCapability::Pointer => true,
_ => false,
}
}
}

View file

@ -9,12 +9,13 @@ use crate::utils::ptr_ext::PtrExt;
use jay_config::_private::ipc::{InitMessage, ServerMessage, V1InitMessage};
use jay_config::_private::{bincode_ops, ConfigEntry, VERSION};
use jay_config::keyboard::ModifiedKeySym;
use jay_config::{InputDevice, Seat};
use jay_config::{Seat};
use libloading::Library;
use std::cell::Cell;
use std::ptr;
use std::rc::Rc;
use thiserror::Error;
use jay_config::input::InputDevice;
#[derive(Debug, Error)]
pub enum ConfigError {

View file

@ -1,5 +1,5 @@
use crate::backend;
use crate::backend::InputDeviceId;
use crate::backend::{InputDeviceCapability, InputDeviceId};
use crate::ifs::wl_seat::{SeatId, WlSeatGlobal};
use crate::state::{DeviceHandlerData, State};
use crate::tree::walker::NodeVisitorBase;
@ -16,12 +16,13 @@ use jay_config::_private::ipc::{ClientMessage, Response, ServerMessage};
use jay_config::keyboard::keymap::Keymap;
use jay_config::keyboard::mods::Modifiers;
use jay_config::keyboard::syms::KeySym;
use jay_config::{Axis, Direction, InputDevice, LogLevel, Seat};
use jay_config::{Axis, Direction, LogLevel, Seat};
use libloading::Library;
use log::Level;
use std::cell::Cell;
use std::rc::Rc;
use thiserror::Error;
use jay_config::input::{CAP_GESTURE, CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD, CAP_TABLET_TOOL, CAP_TOUCH, Capability, InputDevice};
pub(super) struct ConfigProxyHandler {
pub client_data: Cell<*const u8>,
@ -47,6 +48,12 @@ impl ConfigProxyHandler {
self.bufs.push(buf);
}
pub fn respond(&self, msg: Response) {
self.send(&ServerMessage::Response {
response: msg,
})
}
fn id(&self) -> u64 {
self.next_id.fetch_add(1)
}
@ -83,10 +90,8 @@ impl ConfigProxyHandler {
let global_name = self.state.globals.name();
let seat = WlSeatGlobal::new(global_name, name, &self.state);
self.state.globals.add_global(&self.state, &seat);
self.send(&ServerMessage::Response {
response: Response::CreateSeat {
seat: Seat(seat.id().raw() as _),
},
self.respond(Response::CreateSeat {
seat: Seat(seat.id().raw() as _),
});
}
@ -99,9 +104,7 @@ impl ConfigProxyHandler {
}
_ => (Keymap::INVALID, Err(ParseKeymapError::ParsingFailed)),
};
self.send(&ServerMessage::Response {
response: Response::ParseKeymap { keymap },
});
self.respond(Response::ParseKeymap { keymap });
res
}
@ -131,9 +134,7 @@ impl ConfigProxyHandler {
fn handle_get_repeat_rate(&self, seat: Seat) -> Result<(), SeatGetRepeatRateError> {
let seat = self.get_seat(seat)?;
let (rate, delay) = seat.get_rate();
self.send(&ServerMessage::Response {
response: Response::GetRepeatRate { rate, delay },
});
self.respond(Response::GetRepeatRate { rate, delay });
Ok(())
}
@ -184,7 +185,7 @@ impl ConfigProxyHandler {
let kbs = self.state.input_device_handlers.borrow_mut();
match kbs.get(&(InputDeviceId::from_raw(kb.0 as _))) {
None => Err(CphError::KeyboardDoesNotExist(kb)),
Some(kb) => Ok(kb.device.clone()),
Some(kb) => Ok(kb.data.device.clone()),
}
}
@ -206,12 +207,31 @@ impl ConfigProxyHandler {
Ok(())
}
fn handle_has_capability(&self, device: InputDevice, cap: Capability) -> Result<(), HasCapabilityError> {
let dev = self.get_device_handler_data(device)?;
let has_cap = 'has_cap: {
let cap = match cap {
CAP_KEYBOARD => InputDeviceCapability::Keyboard,
CAP_POINTER => InputDeviceCapability::Pointer,
CAP_TOUCH => InputDeviceCapability::Touch,
CAP_TABLET_TOOL => InputDeviceCapability::TabletTool,
CAP_TABLET_PAD => InputDeviceCapability::TabletPad,
CAP_GESTURE => InputDeviceCapability::Gesture,
CAP_SWITCH => InputDeviceCapability::Switch,
_ => break 'has_cap false,
};
dev.device.has_capability(cap)
};
self.respond(Response::HasCapability {
has: has_cap,
});
Ok(())
}
fn handle_get_mono(&self, seat: Seat) -> Result<(), GetMonoError> {
let seat = self.get_seat(seat)?;
self.send(&ServerMessage::Response {
response: Response::GetMono {
mono: seat.get_mono().unwrap_or(false),
},
self.respond(Response::GetMono {
mono: seat.get_mono().unwrap_or(false),
});
Ok(())
}
@ -224,13 +244,11 @@ impl ConfigProxyHandler {
fn handle_get_split(&self, seat: Seat) -> Result<(), GetSplitError> {
let seat = self.get_seat(seat)?;
self.send(&ServerMessage::Response {
response: Response::GetSplit {
axis: seat
.get_split()
.unwrap_or(ContainerSplit::Horizontal)
.into(),
},
self.respond(Response::GetSplit {
axis: seat
.get_split()
.unwrap_or(ContainerSplit::Horizontal)
.into(),
});
Ok(())
}
@ -284,9 +302,7 @@ impl ConfigProxyHandler {
}
}
}
self.send(&ServerMessage::Response {
response: Response::GetInputDevices { devices: res },
});
self.respond(Response::GetInputDevices { devices: res });
}
fn handle_get_seats(&self) {
@ -297,9 +313,7 @@ impl ConfigProxyHandler {
.map(|seat| Seat::from_raw(seat.id().raw() as _))
.collect()
};
self.send(&ServerMessage::Response {
response: Response::GetSeats { seats },
});
self.respond(Response::GetSeats { seats });
}
fn handle_run(
@ -323,18 +337,14 @@ impl ConfigProxyHandler {
}
fn handle_get_title_height(&self) {
self.send(&ServerMessage::Response {
response: Response::GetTitleHeight {
height: self.state.theme.title_height.get(),
},
self.respond(Response::GetTitleHeight {
height: self.state.theme.title_height.get(),
});
}
fn handle_get_border_width(&self) {
self.send(&ServerMessage::Response {
response: Response::GetBorderWidth {
width: self.state.theme.border_width.get(),
},
self.respond(Response::GetBorderWidth {
width: self.state.theme.border_width.get(),
});
}
@ -500,6 +510,7 @@ impl ConfigProxyHandler {
ClientMessage::ToggleFloating { seat } => self.handle_toggle_floating(seat)?,
ClientMessage::Quit => self.handle_quit(),
ClientMessage::SwitchTo { vtnr } => self.handle_switch_to(vtnr),
ClientMessage::HasCapability { device, cap } => self.handle_has_capability(device, cap)?,
}
Ok(())
}
@ -547,6 +558,8 @@ enum CphError {
SetTitleHeightError(#[from] SetTitleHeightError),
#[error("Could not process a `set_border_width` request")]
SetBorderWidthError(#[from] SetBorderWidthError),
#[error("Could not process a `has_capability` request")]
HasCapabilityError(#[from] HasCapabilityError),
#[error("Device {0:?} does not exist")]
DeviceDoesNotExist(InputDevice),
#[error("Device {0:?} does not exist")]
@ -572,6 +585,13 @@ enum SetSeatError {
}
efrom!(SetSeatError, CphError);
#[derive(Debug, Error)]
enum HasCapabilityError {
#[error(transparent)]
CphError(#[from] Box<CphError>),
}
efrom!(HasCapabilityError, CphError);
#[derive(Debug, Error)]
enum AddShortcutError {
#[error(transparent)]

View file

@ -1,10 +1,8 @@
use crate::libinput::sys::{
libinput_device, libinput_device_get_user_data, libinput_device_set_user_data,
libinput_device_unref, libinput_path_remove_device,
};
use crate::libinput::sys::{libinput_device, libinput_device_get_user_data, libinput_device_has_capability, libinput_device_set_user_data, libinput_device_unref, libinput_path_remove_device};
use crate::libinput::LibInput;
use std::marker::PhantomData;
use std::rc::Rc;
use crate::libinput::consts::{DeviceCapability};
pub struct LibInputDevice<'a> {
pub(super) dev: *mut libinput_device,
@ -39,6 +37,11 @@ impl<'a> LibInputDevice<'a> {
Some(res - 1)
}
}
pub fn has_cap(&self, cap: DeviceCapability) -> bool {
let res = unsafe { libinput_device_has_capability(self.dev, cap.raw() as _) };
res != 0
}
}
impl RegisteredDevice {

View file

@ -24,6 +24,11 @@ extern "C" {
interface: *const libinput_interface,
user_data: *mut c::c_void,
) -> *mut libinput;
pub fn libinput_unref(libinput: *mut libinput) -> *mut libinput;
pub fn libinput_get_fd(libinput: *mut libinput) -> c::c_int;
pub fn libinput_dispatch(libinput: *mut libinput) -> c::c_int;
pub fn libinput_get_event(libinput: *mut libinput) -> *mut libinput_event;
pub fn libinput_device_set_user_data(device: *mut libinput_device, user_data: *mut c::c_void);
pub fn libinput_device_get_user_data(device: *mut libinput_device) -> *mut c::c_void;
pub fn libinput_device_ref(device: *mut libinput_device) -> *mut libinput_device;
@ -33,12 +38,7 @@ extern "C" {
path: *const c::c_char,
) -> *mut libinput_device;
pub fn libinput_path_remove_device(device: *mut libinput_device);
pub fn libinput_unref(libinput: *mut libinput) -> *mut libinput;
pub fn libinput_get_fd(libinput: *mut libinput) -> c::c_int;
pub fn libinput_dispatch(libinput: *mut libinput) -> c::c_int;
pub fn libinput_get_event(libinput: *mut libinput) -> *mut libinput_event;
pub fn libinput_device_has_capability(device: *mut libinput_device, cap: libinput_device_capability) -> c::c_int;
pub fn libinput_event_destroy(event: *mut libinput_event);
pub fn libinput_event_get_type(event: *mut libinput_event) -> libinput_event_type;

View file

@ -73,12 +73,12 @@ pub struct State {
pub struct InputDeviceData {
pub handler: SpawnedFuture<()>,
pub id: InputDeviceId,
pub device: Rc<dyn InputDevice>,
pub data: Rc<DeviceHandlerData>,
}
pub struct DeviceHandlerData {
pub seat: CloneCell<Option<Rc<WlSeatGlobal>>>,
pub device: Rc<dyn InputDevice>,
}
impl State {

View file

@ -6,6 +6,7 @@ use std::rc::Rc;
pub fn handle(state: &Rc<State>, dev: Rc<dyn InputDevice>) {
let data = Rc::new(DeviceHandlerData {
seat: Default::default(),
device: dev.clone(),
});
let oh = DeviceHandler {
state: state.clone(),
@ -18,7 +19,6 @@ pub fn handle(state: &Rc<State>, dev: Rc<dyn InputDevice>) {
InputDeviceData {
handler,
id: dev.id(),
device: dev.clone(),
data,
},
);