From 65048bab952a4949c906c15be30bbe6aa3378026 Mon Sep 17 00:00:00 2001 From: Akshat Deshpande Date: Thu, 28 Jul 2022 12:57:50 -0500 Subject: [PATCH] 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 --- src/main.rs | 58 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index a28a758..a93aec5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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( manager: &mut XcrabWindowManager, conn: &mut Dpy, root: Window, + keymap: &HashMap, ) -> Result<()> { match ev { Event::MapRequest(ev) => { @@ -184,12 +209,37 @@ async fn process_event( } } 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(conn: &mut Dpy) -> Option> { + let mut state = KeyboardState::new_async(conn).await.ok()?; + let mut map: HashMap = 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) +}