alright, keybinds the right way

we still need to make use of the config file, but that's easy enough to change
I'm not quite sure how you would get the inner value for the modmask, but if you make a
simple keypress event listener (or use an existing one, I'm sure those exist),
the inner value that you want is in the keybutmask value of the event object
I'll probably deal with that myself, but I'll leave that here for future reference
This commit is contained in:
Akshat Deshpande 2022-07-28 12:57:50 -05:00
parent 5d14402cc8
commit 65048bab95

View file

@ -16,9 +16,10 @@
#![warn(clippy::pedantic)]
use std::fmt::{Debug, Display};
use std::ops::Deref;
use breadx::{
auto::xproto::{GrabKeyRequest, GrabMode, KeyButMask, Keycode, Keysym, ModMask},
keyboard::KeyboardState,
prelude::{AsyncDisplay, AsyncDisplayXprotoExt, MapState},
traits::DisplayBase,
AsyncDisplayConnection, AsyncDisplayExt, BreadError, ConfigureWindowParameters, Event,
@ -35,6 +36,8 @@ mod x11;
use x11::client::{may_not_exist, XcrabWindowManager};
use std::collections::HashMap;
#[non_exhaustive]
pub enum XcrabError {
Bread(BreadError),
@ -104,7 +107,7 @@ async fn main() -> Result<()> {
// listen for substructure redirects to intercept events like window creation
root.set_event_mask_async(
&mut conn,
EventMask::SUBSTRUCTURE_REDIRECT | EventMask::SUBSTRUCTURE_NOTIFY,
EventMask::SUBSTRUCTURE_REDIRECT | EventMask::SUBSTRUCTURE_NOTIFY | EventMask::KEY_PRESS,
)
.await?;
@ -131,13 +134,34 @@ async fn main() -> Result<()> {
send,
));
let mask = ModMask {
inner: 20
};
let keymap = keymap(&mut conn).await.unwrap_or_default();
let key_u32 = u32::from_str_radix("0078", 16).unwrap_or_default();
let key = keymap
.get(&key_u32)
.expect("yeah sorry that keysym didn't map out");
conn.exchange_request_async(GrabKeyRequest {
req_type: 33,
owner_events: false,
length: 4,
grab_window: root,
modifiers: mask,
key: *key,
pointer_mode: GrabMode::Async,
keyboard_mode: GrabMode::Async,
})
.await?;
loop {
// biased mode makes select! poll the channel first in order to keep xcrab-msg from being
// starved by x11 events. Probably unnecessary, but better safe than sorry.
tokio::select! {
biased;
Some(s) = recv.recv() => msg_listener::on_recv(s, &mut manager, &mut conn).await?,
Ok(ev) = conn.wait_for_event_async() => process_event(ev, &mut manager, &mut conn, root).await?,
Ok(ev) = conn.wait_for_event_async() => process_event(ev, &mut manager, &mut conn, root, &keymap).await?,
}
}
}
@ -147,6 +171,7 @@ async fn process_event<Dpy: AsyncDisplay + ?Sized>(
manager: &mut XcrabWindowManager,
conn: &mut Dpy,
root: Window,
keymap: &HashMap<Keysym, Keycode>,
) -> Result<()> {
match ev {
Event::MapRequest(ev) => {
@ -184,12 +209,37 @@ async fn process_event<Dpy: AsyncDisplay + ?Sized>(
}
}
Event::ButtonPress(ev) => {
dbg!(&ev);
if ev.detail == 1 {
manager.set_focus(conn, ev.event).await?;
}
}
Event::KeyPress(ev) => {
let key_u32 = u32::from_str_radix("0x0078", 16).unwrap_or_default();
let key = keymap.get(&key_u32).unwrap_or(&u8::MIN);
if ev.detail == *key {
manager.destroy_focused_client(conn).await?;
}
dbg!(ev);
}
_ => {}
}
Ok(())
}
// I will move this to x11/client.rs eventually
// this is just ease of coding for now
async fn keymap<Dpy: AsyncDisplay + ?Sized>(conn: &mut Dpy) -> Option<HashMap<Keysym, Keycode>> {
let mut state = KeyboardState::new_async(conn).await.ok()?;
let mut map: HashMap<Keysym, Keycode> = HashMap::new();
for keycode in 8..255_u8 {
let key = state.process_keycode(keycode, KeyButMask::default());
let keysyms = state.lookup_keysyms(keycode);
if key != None {
for keysym in keysyms {
map.insert(*keysym, keycode);
}
}
}
Some(map)
}