use std::{fmt, cell::Cell, ptr::NonNull, rc::Rc};
use wlroots_sys::{wlr_input_device, wlr_keyboard, wlr_keyboard_led, wlr_keyboard_led_update,
wlr_keyboard_get_modifiers, wlr_keyboard_modifier, wlr_keyboard_modifiers,
wlr_keyboard_set_keymap,
xkb_keysym_t};
pub use wlroots_sys::wlr_key_state;
use xkbcommon::xkb::{self, Keycode, Keymap, LedIndex, ModIndex};
use xkbcommon::xkb::ffi::{xkb_keymap, xkb_state};
use {input::{self, InputState},
utils::{self, Handleable, HandleErr, HandleResult}};
pub use manager::keyboard_handler::*;
pub use events::key_events as event;
pub type Key = xkb_keysym_t;
pub type Handle = utils::Handle<NonNull<wlr_input_device>, wlr_keyboard, Keyboard>;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct RepeatInfo {
pub rate: i32,
pub delay: i32
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct Modifiers {
pub depressed: Modifier,
pub latched: Modifier,
pub locked: Modifier,
pub group: Modifier,
}
impl Default for Modifiers {
fn default() -> Self {
Modifiers {
depressed: Modifier::empty(),
latched: Modifier::empty(),
locked: Modifier::empty(),
group: Modifier::empty()
}
}
}
impl From<wlr_keyboard_modifiers> for Modifiers {
fn from(mods: wlr_keyboard_modifiers) -> Self{
Modifiers {
depressed: Modifier::from_bits_truncate(mods.depressed),
latched: Modifier::from_bits_truncate(mods.latched),
locked: Modifier::from_bits_truncate(mods.locked),
group: Modifier::from_bits_truncate(mods.group),
}
}
}
impl Into<wlr_keyboard_modifiers> for Modifiers {
fn into(self) -> wlr_keyboard_modifiers {
wlr_keyboard_modifiers {
depressed: self.depressed.bits(),
latched: self.latched.bits(),
locked: self.locked.bits(),
group: self.group.bits(),
}
}
}
#[derive(Debug)]
pub struct Keyboard {
liveliness: Rc<Cell<bool>>,
device: input::Device,
keyboard: NonNull<wlr_keyboard>
}
impl Keyboard {
pub(crate) unsafe fn new_from_input_device(device: *mut wlr_input_device) -> Option<Self> {
use wlroots_sys::wlr_input_device_type::*;
match (*device).type_ {
WLR_INPUT_DEVICE_KEYBOARD => {
let keyboard = NonNull::new((*device).__bindgen_anon_1.keyboard)
.expect("Keyboard pointer was null");
let liveliness = Rc::new(Cell::new(false));
let handle = Rc::downgrade(&liveliness);
let state = Box::new(InputState { handle,
device: input::Device::from_ptr(device) });
(*keyboard.as_ptr()).data = Box::into_raw(state) as *mut _;
Some(Keyboard { liveliness,
device: input::Device::from_ptr(device),
keyboard })
}
_ => None
}
}
pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
self.keyboard.as_ptr()
}
pub fn input_device(&self) -> &input::Device {
&self.device
}
pub fn set_keymap(&mut self, keymap: &Keymap) {
unsafe {
wlr_keyboard_set_keymap(self.keyboard.as_ptr(), keymap.get_raw_ptr() as _);
}
}
pub fn get_keymap(&mut self) -> Option<Keymap> {
unsafe {
let keymap_ptr = (*self.keyboard.as_ptr()).keymap as *mut xkb_keymap;
if keymap_ptr.is_null() {
None
} else {
Some(Keymap::from_raw_ptr(keymap_ptr))
}
}
}
pub fn keycodes(&self) -> Vec<Keycode> {
unsafe {
let mut result = (*self.keyboard.as_ptr()).keycodes.to_vec();
result.truncate((*self.keyboard.as_ptr()).num_keycodes);
result
}
}
pub fn led_list(&self) -> &[LedIndex] {
unsafe { &(*self.keyboard.as_ptr()).led_indexes }
}
pub fn modifier_list(&self) -> &[ModIndex] {
unsafe { &(*self.keyboard.as_ptr()).mod_indexes }
}
pub fn keymap_size(&self) -> usize {
unsafe { (*self.keyboard.as_ptr()).keymap_size }
}
pub fn get_xkb_state(&mut self) -> Option<xkb::State> {
unsafe {
let xkb_state_ptr = (*self.keyboard.as_ptr()).xkb_state as *mut xkb_state;
if xkb_state_ptr.is_null() {
None
} else {
Some(xkb::State::from_raw_ptr(xkb_state_ptr))
}
}
}
pub fn repeat_info(&self) -> RepeatInfo {
unsafe {
RepeatInfo { rate: (*self.keyboard.as_ptr()).repeat_info.rate,
delay: (*self.keyboard.as_ptr()).repeat_info.delay }
}
}
pub fn update_led(&mut self, leds: Led) {
unsafe {
wlr_keyboard_led_update(self.keyboard.as_ptr(), leds.bits() as u32);
}
}
pub fn get_modifiers(&self) -> Modifier {
unsafe { Modifier::from_bits_truncate(wlr_keyboard_get_modifiers(self.keyboard.as_ptr())) }
}
pub fn get_modifier_masks(&self) -> Modifiers {
From::from(unsafe { (*self.keyboard.as_ptr()).modifiers })
}
}
impl Drop for Keyboard {
fn drop(&mut self) {
if Rc::strong_count(&self.liveliness) == 1 {
wlr_log!(WLR_DEBUG, "Dropped Keyboard {:p}", self.keyboard.as_ptr());
unsafe {
let _ = Box::from_raw((*self.keyboard.as_ptr()).data as *mut InputState);
}
let weak_count = Rc::weak_count(&self.liveliness);
if weak_count > 0 {
wlr_log!(WLR_DEBUG,
"Still {} weak pointers to Keyboard {:p}",
weak_count,
self.keyboard.as_ptr());
}
}
}
}
impl Handleable<NonNull<wlr_input_device>, wlr_keyboard> for Keyboard {
#[doc(hidden)]
unsafe fn from_ptr(keyboard: *mut wlr_keyboard) -> Option<Self> {
let keyboard = NonNull::new(keyboard)?;
let data = Box::from_raw((*keyboard.as_ptr()).data as *mut InputState);
let handle = data.handle.clone();
let device = data.device.clone();
(*keyboard.as_ptr()).data = Box::into_raw(data) as *mut _;
Some(Keyboard { liveliness: handle.upgrade().unwrap(),
device,
keyboard })
}
#[doc(hidden)]
unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
self.keyboard.as_ptr()
}
#[doc(hidden)]
unsafe fn from_handle(handle: &Handle) -> HandleResult<Self> {
let liveliness = handle.handle
.upgrade()
.ok_or(HandleErr::AlreadyDropped)?;
let device = handle.data.ok_or(HandleErr::AlreadyDropped)?;
Ok(Keyboard { liveliness,
device: input::Device { device },
keyboard: handle.as_non_null()
})
}
fn weak_reference(&self) -> Handle {
Handle { ptr: self.keyboard,
handle: Rc::downgrade(&self.liveliness),
data: unsafe { Some(self.device.as_non_null()) },
_marker: std::marker::PhantomData
}
}
}
bitflags! {
pub struct Led: u32 {
const WLR_LED_NUM_LOCK = wlr_keyboard_led::WLR_LED_NUM_LOCK as u32;
const WLR_LED_CAPS_LOCK = wlr_keyboard_led::WLR_LED_CAPS_LOCK as u32;
const WLR_LED_SCROLL_LOCK = wlr_keyboard_led::WLR_LED_SCROLL_LOCK as u32;
}
}
bitflags! {
pub struct Modifier: u32 {
const WLR_MODIFIER_SHIFT = wlr_keyboard_modifier::WLR_MODIFIER_SHIFT as u32;
const WLR_MODIFIER_CAPS = wlr_keyboard_modifier::WLR_MODIFIER_CAPS as u32;
const WLR_MODIFIER_CTRL = wlr_keyboard_modifier::WLR_MODIFIER_CTRL as u32;
const WLR_MODIFIER_ALT = wlr_keyboard_modifier::WLR_MODIFIER_ALT as u32;
const WLR_MODIFIER_MOD2 = wlr_keyboard_modifier::WLR_MODIFIER_MOD2 as u32;
const WLR_MODIFIER_MOD3 = wlr_keyboard_modifier::WLR_MODIFIER_MOD3 as u32;
const WLR_MODIFIER_LOGO = wlr_keyboard_modifier::WLR_MODIFIER_LOGO as u32;
const WLR_MODIFIER_MOD5 = wlr_keyboard_modifier::WLR_MODIFIER_MOD5 as u32;
}
}
impl fmt::Display for Modifier {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let mod_vec = vec![("Shift", Modifier::WLR_MODIFIER_SHIFT),
("Caps lock", Modifier::WLR_MODIFIER_CAPS),
("Ctrl", Modifier::WLR_MODIFIER_CTRL),
("Alt", Modifier::WLR_MODIFIER_ALT),
("Mod2", Modifier::WLR_MODIFIER_MOD2),
("Mod3", Modifier::WLR_MODIFIER_MOD3),
("Logo", Modifier::WLR_MODIFIER_LOGO),
("Mod5", Modifier::WLR_MODIFIER_MOD5)];
let mods: Vec<&str> = mod_vec.into_iter()
.filter(|&(_, flag)| self.contains(flag))
.map(|(st, _)| st)
.collect();
write!(formatter, "{:?}", mods)
}
}