jay-compositor 1.15.0

The Jay compositor
use crate::ifs::wl_seat::wl_keyboard;
use crate::object::Version;
use crate::utils::clonecell::CloneCell;
use crate::utils::ptr_ext::PtrExt;
use crate::wire::WlKeyboardId;
use crate::wire::WlSurfaceId;
use crate::wire::wl_keyboard::*;
use crate::wl_usr::UsrCon;
use crate::wl_usr::usr_object::UsrObject;
use jay_algorithms::mmap::mmap;
use jay_algorithms::oserror::OsError;
use kbvm::Components;
use kbvm::Keycode;
use kbvm::ModifierMask;
use kbvm::lookup::Lookup;
use kbvm::lookup::LookupTable;
use kbvm::xkb::Context;
use kbvm::xkb::diagnostic::Diagnostic;
use kbvm::xkb::diagnostic::WriteToLog;
use std::cell::RefCell;
use std::rc::Rc;
use thiserror::Error;
use uapi::c;

pub struct UsrWlKeyboard {
    pub id: WlKeyboardId,
    pub con: Rc<UsrCon>,
    pub keyboard: RefCell<Option<Keyboard>>,
    pub owner: CloneCell<Option<Rc<dyn UsrWlKeyboardOwner>>>,
    pub version: Version,
}

pub struct Keyboard {
    lookup: LookupTable,
    components: Components,
}

pub trait UsrWlKeyboardOwner {
    fn focus(self: Rc<Self>, surface: WlSurfaceId, serial: u32);
    fn unfocus(self: Rc<Self>);
    fn modifiers(self: Rc<Self>, mods: ModifierMask);
    fn down(self: Rc<Self>, lookup: Lookup<'_>, serial: u32);
    fn repeat(self: Rc<Self>, lookup: Lookup<'_>, serial: u32);
    fn up(self: Rc<Self>, lookup: Lookup<'_>, serial: u32);
}

impl WlKeyboardEventHandler for UsrWlKeyboard {
    type Error = UsrWlKeyboardError;

    fn keymap(&self, ev: Keymap, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        let map = mmap(ev.size as _, c::PROT_READ, c::MAP_PRIVATE, ev.fd.raw(), 0)
            .map_err(UsrWlKeyboardError::MapKeymap)?;
        let mut builder = Context::builder();
        builder.enable_default_includes(false);
        builder.enable_environment(false);
        let keymap = builder
            .build()
            .keymap_from_bytes(WriteToLog, None, unsafe { map.ptr.deref() })
            .map_err(UsrWlKeyboardError::ParseKeymap)?;
        let lookup = keymap.to_builder().build_lookup_table();
        let keyboard = Keyboard {
            lookup,
            components: Default::default(),
        };
        self.keyboard.replace(Some(keyboard));
        Ok(())
    }

    fn enter(&self, ev: Enter<'_>, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        let Some(owner) = self.owner.get() else {
            return Ok(());
        };
        owner.focus(ev.surface, ev.serial);
        Ok(())
    }

    fn leave(&self, _ev: Leave, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        let Some(owner) = self.owner.get() else {
            return Ok(());
        };
        owner.unfocus();
        Ok(())
    }

    fn key(&self, ev: Key, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        let Some(kb) = &*self.keyboard.borrow() else {
            return Ok(());
        };
        let Some(owner) = self.owner.get() else {
            return Ok(());
        };
        let kc = Keycode::from_evdev(ev.key);
        let lookup = kb
            .lookup
            .lookup(kb.components.group, kb.components.mods, kc);
        if ev.state == wl_keyboard::PRESSED {
            owner.down(lookup, ev.serial);
        } else if ev.state == wl_keyboard::REPEATED {
            owner.repeat(lookup, ev.serial);
        } else if ev.state == wl_keyboard::RELEASED {
            owner.up(lookup, ev.serial);
        }
        Ok(())
    }

    fn modifiers(&self, ev: Modifiers, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        let Some(kb) = &mut *self.keyboard.borrow_mut() else {
            return Ok(());
        };
        kb.components.mods_pressed.0 = ev.mods_depressed;
        kb.components.mods_latched.0 = ev.mods_latched;
        kb.components.mods_locked.0 = ev.mods_locked;
        kb.components.group_locked.0 = ev.group;
        let old = kb.components.mods;
        kb.components.update_effective();
        let new = kb.components.mods;
        if old != new
            && let Some(owner) = self.owner.get()
        {
            owner.modifiers(new);
        }
        Ok(())
    }

    fn repeat_info(&self, _ev: RepeatInfo, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        Ok(())
    }
}

usr_object_base! {
    self = UsrWlKeyboard = WlKeyboard;
    version = self.version;
}

impl UsrObject for UsrWlKeyboard {
    fn destroy(&self) {
        self.con.request(Release { self_id: self.id });
    }

    fn break_loops(&self) {
        self.owner.take();
    }
}

#[derive(Debug, Error)]
pub enum UsrWlKeyboardError {
    #[error("Could not map the keymap")]
    MapKeymap(#[source] OsError),
    #[error("Could not parse the keymap")]
    ParseKeymap(#[source] Diagnostic),
}