wayland: implement virtual-keyboard
This commit is contained in:
parent
826f40adca
commit
6c0e3a4fff
20 changed files with 689 additions and 14 deletions
|
|
@ -7,6 +7,8 @@ pub mod wl_touch;
|
|||
pub mod zwp_pointer_constraints_v1;
|
||||
pub mod zwp_relative_pointer_manager_v1;
|
||||
pub mod zwp_relative_pointer_v1;
|
||||
pub mod zwp_virtual_keyboard_manager_v1;
|
||||
pub mod zwp_virtual_keyboard_v1;
|
||||
|
||||
pub use event_handling::NodeSeatState;
|
||||
use {
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ impl WlSeatGlobal {
|
|||
self.pointer_owner.button(self, time_usec, button, state);
|
||||
}
|
||||
|
||||
fn key_event(&self, time_usec: u64, key: u32, key_state: KeyState) {
|
||||
pub(super) fn key_event(&self, time_usec: u64, key: u32, key_state: KeyState) {
|
||||
let (state, xkb_dir) = {
|
||||
let mut pk = self.pressed_keys.borrow_mut();
|
||||
match key_state {
|
||||
|
|
@ -411,6 +411,25 @@ impl WlSeatGlobal {
|
|||
node.node_on_mods(self, mods);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn set_modifiers(
|
||||
&self,
|
||||
mods_depressed: u32,
|
||||
mods_latched: u32,
|
||||
mods_locked: u32,
|
||||
group: u32,
|
||||
) {
|
||||
let new_mods =
|
||||
self.kb_state
|
||||
.borrow_mut()
|
||||
.set(mods_depressed, mods_latched, mods_locked, group);
|
||||
if let Some(mods) = new_mods {
|
||||
self.state.for_each_seat_tester(|t| {
|
||||
t.send_modifiers(self.id, &mods);
|
||||
});
|
||||
self.keyboard_node.get().node_on_mods(self, mods);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WlSeatGlobal {
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ pub const REPEAT_INFO_SINCE: Version = Version(4);
|
|||
|
||||
#[allow(dead_code)]
|
||||
const NO_KEYMAP: u32 = 0;
|
||||
pub(super) const XKB_V1: u32 = 1;
|
||||
pub const XKB_V1: u32 = 1;
|
||||
|
||||
pub(super) const RELEASED: u32 = 0;
|
||||
pub(super) const PRESSED: u32 = 1;
|
||||
pub const RELEASED: u32 = 0;
|
||||
pub const PRESSED: u32 = 1;
|
||||
|
||||
pub struct WlKeyboard {
|
||||
id: WlKeyboardId,
|
||||
|
|
|
|||
108
src/ifs/wl_seat/zwp_virtual_keyboard_manager_v1.rs
Normal file
108
src/ifs/wl_seat/zwp_virtual_keyboard_manager_v1.rs
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
use {
|
||||
crate::{
|
||||
client::{Client, ClientError},
|
||||
globals::{Global, GlobalName},
|
||||
ifs::wl_seat::zwp_virtual_keyboard_v1::ZwpVirtualKeyboardV1,
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
wire::{zwp_virtual_keyboard_manager_v1::*, ZwpVirtualKeyboardManagerV1Id},
|
||||
},
|
||||
std::rc::Rc,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct ZwpVirtualKeyboardManagerV1Global {
|
||||
pub name: GlobalName,
|
||||
}
|
||||
|
||||
pub struct ZwpVirtualKeyboardManagerV1 {
|
||||
pub id: ZwpVirtualKeyboardManagerV1Id,
|
||||
pub client: Rc<Client>,
|
||||
pub tracker: Tracker<Self>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
impl ZwpVirtualKeyboardManagerV1Global {
|
||||
pub fn new(name: GlobalName) -> Self {
|
||||
Self { name }
|
||||
}
|
||||
|
||||
fn bind_(
|
||||
self: Rc<Self>,
|
||||
id: ZwpVirtualKeyboardManagerV1Id,
|
||||
client: &Rc<Client>,
|
||||
version: Version,
|
||||
) -> Result<(), ZwpVirtualKeyboardManagerV1Error> {
|
||||
let obj = Rc::new(ZwpVirtualKeyboardManagerV1 {
|
||||
id,
|
||||
client: client.clone(),
|
||||
tracker: Default::default(),
|
||||
version,
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
global_base!(
|
||||
ZwpVirtualKeyboardManagerV1Global,
|
||||
ZwpVirtualKeyboardManagerV1,
|
||||
ZwpVirtualKeyboardManagerV1Error
|
||||
);
|
||||
|
||||
impl Global for ZwpVirtualKeyboardManagerV1Global {
|
||||
fn singleton(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn version(&self) -> u32 {
|
||||
1
|
||||
}
|
||||
|
||||
fn secure(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
simple_add_global!(ZwpVirtualKeyboardManagerV1Global);
|
||||
|
||||
impl ZwpVirtualKeyboardManagerV1RequestHandler for ZwpVirtualKeyboardManagerV1 {
|
||||
type Error = ZwpVirtualKeyboardManagerV1Error;
|
||||
|
||||
fn create_virtual_keyboard(
|
||||
&self,
|
||||
req: CreateVirtualKeyboard,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
let seat = self.client.lookup(req.seat)?;
|
||||
let kb = Rc::new(ZwpVirtualKeyboardV1 {
|
||||
id: req.id,
|
||||
client: self.client.clone(),
|
||||
seat: seat.global.clone(),
|
||||
tracker: Default::default(),
|
||||
version: self.version,
|
||||
keymap_id: Default::default(),
|
||||
keymap: Default::default(),
|
||||
});
|
||||
track!(self.client, kb);
|
||||
self.client.add_client_obj(&kb)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
self = ZwpVirtualKeyboardManagerV1;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl Object for ZwpVirtualKeyboardManagerV1 {}
|
||||
|
||||
simple_add_obj!(ZwpVirtualKeyboardManagerV1);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ZwpVirtualKeyboardManagerV1Error {
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(ZwpVirtualKeyboardManagerV1Error, ClientError);
|
||||
131
src/ifs/wl_seat/zwp_virtual_keyboard_v1.rs
Normal file
131
src/ifs/wl_seat/zwp_virtual_keyboard_v1.rs
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
use {
|
||||
crate::{
|
||||
backend::KeyState,
|
||||
client::{Client, ClientError},
|
||||
clientmem::{ClientMem, ClientMemError},
|
||||
ifs::wl_seat::{wl_keyboard, WlSeatGlobal},
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
utils::clonecell::CloneCell,
|
||||
wire::{zwp_virtual_keyboard_v1::*, ZwpVirtualKeyboardV1Id},
|
||||
xkbcommon::{KeymapId, XkbCommonError, XkbKeymap},
|
||||
},
|
||||
std::{cell::Cell, rc::Rc},
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct ZwpVirtualKeyboardV1 {
|
||||
pub id: ZwpVirtualKeyboardV1Id,
|
||||
pub client: Rc<Client>,
|
||||
pub seat: Rc<WlSeatGlobal>,
|
||||
pub tracker: Tracker<Self>,
|
||||
pub version: Version,
|
||||
pub keymap_id: Cell<Option<KeymapId>>,
|
||||
pub keymap: CloneCell<Option<Rc<XkbKeymap>>>,
|
||||
}
|
||||
|
||||
impl ZwpVirtualKeyboardV1 {
|
||||
fn ensure_keymap(&self) {
|
||||
if let Some(id) = self.keymap_id.get() {
|
||||
if id == self.seat.effective_kb_map_id.get() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let Some(keymap) = self.keymap.get() else {
|
||||
return;
|
||||
};
|
||||
self.seat.set_effective_keymap(&keymap);
|
||||
}
|
||||
}
|
||||
|
||||
impl ZwpVirtualKeyboardV1RequestHandler for ZwpVirtualKeyboardV1 {
|
||||
type Error = ZwpVirtualKeyboardV1Error;
|
||||
|
||||
fn keymap(&self, req: Keymap, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if req.format != wl_keyboard::XKB_V1 {
|
||||
return Err(ZwpVirtualKeyboardV1Error::UnsupportedFormat(req.format));
|
||||
}
|
||||
if req.size == 0 {
|
||||
return Err(ZwpVirtualKeyboardV1Error::InvalidKeymap);
|
||||
}
|
||||
const MAX_SIZE: u32 = 1024 * 1024;
|
||||
if req.size > MAX_SIZE {
|
||||
return Err(ZwpVirtualKeyboardV1Error::OversizedKeymap);
|
||||
}
|
||||
let client_mem = ClientMem::new(req.fd.raw(), req.size as usize - 1, true)
|
||||
.map(Rc::new)
|
||||
.map_err(ZwpVirtualKeyboardV1Error::MapKeymap)?;
|
||||
let mut map = vec![];
|
||||
client_mem
|
||||
.offset(0)
|
||||
.read(&mut map)
|
||||
.map_err(ZwpVirtualKeyboardV1Error::ReadKeymap)?;
|
||||
let map = self
|
||||
.client
|
||||
.state
|
||||
.xkb_ctx
|
||||
.keymap_from_str(&map)
|
||||
.map_err(ZwpVirtualKeyboardV1Error::ParseKeymap)?;
|
||||
self.keymap_id.set(Some(map.id));
|
||||
self.keymap.set(Some(map));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn key(&self, req: Key, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.ensure_keymap();
|
||||
let time_usec = (req.time as u64) * 1000;
|
||||
let state = match req.state {
|
||||
wl_keyboard::RELEASED => KeyState::Released,
|
||||
wl_keyboard::PRESSED => KeyState::Pressed,
|
||||
_ => return Err(ZwpVirtualKeyboardV1Error::UnknownState(req.state)),
|
||||
};
|
||||
self.seat.key_event(time_usec, req.key, state);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn modifiers(&self, req: Modifiers, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.ensure_keymap();
|
||||
self.seat.set_modifiers(
|
||||
req.mods_depressed,
|
||||
req.mods_latched,
|
||||
req.mods_locked,
|
||||
req.group,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
self = ZwpVirtualKeyboardV1;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl Object for ZwpVirtualKeyboardV1 {}
|
||||
|
||||
simple_add_obj!(ZwpVirtualKeyboardV1);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ZwpVirtualKeyboardV1Error {
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
#[error("Unknown key state {0}")]
|
||||
UnknownState(u32),
|
||||
#[error("Unsupported keymap format {0}")]
|
||||
UnsupportedFormat(u32),
|
||||
#[error("Keymap is invalid")]
|
||||
InvalidKeymap,
|
||||
#[error("Keymap is too large")]
|
||||
OversizedKeymap,
|
||||
#[error("Could not map the keymap")]
|
||||
MapKeymap(#[source] ClientMemError),
|
||||
#[error("Could not read the keymap")]
|
||||
ReadKeymap(#[source] ClientMemError),
|
||||
#[error("Could not parse the keymap")]
|
||||
ParseKeymap(#[source] XkbCommonError),
|
||||
}
|
||||
efrom!(ZwpVirtualKeyboardV1Error, ClientError);
|
||||
Loading…
Add table
Add a link
Reference in a new issue