forked from InfoshockTech/xcrab
keybinds without input-only windows (#13)
Reviewed-on: InfoshockTech/xcrab#13 Co-authored-by: Akshat Deshpande <akshatd18@outlook.com> Co-committed-by: Akshat Deshpande <akshatd18@outlook.com>
This commit is contained in:
parent
b54a52f64b
commit
a3a4b21981
1
.gitattributes
vendored
1
.gitattributes
vendored
|
@ -1 +0,0 @@
|
|||
* text=auto
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
/target
|
||||
/.idea
|
64
Cargo.lock
generated
64
Cargo.lock
generated
|
@ -40,9 +40,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async-task"
|
||||
version = "4.2.0"
|
||||
version = "4.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9"
|
||||
checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524"
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
|
@ -99,15 +99,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.9.1"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc"
|
||||
checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.1.0"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
||||
checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
|
||||
|
||||
[[package]]
|
||||
name = "cache-padded"
|
||||
|
@ -129,9 +129,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "1.2.2"
|
||||
version = "1.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
|
||||
checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c"
|
||||
dependencies = [
|
||||
"cache-padded",
|
||||
]
|
||||
|
@ -144,15 +144,15 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
|
|||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "2.5.2"
|
||||
version = "2.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71"
|
||||
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.7.0"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
|
||||
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
@ -290,9 +290,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.12.0"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
|
||||
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
|
@ -344,9 +344,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.40"
|
||||
version = "1.0.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
|
||||
checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -362,9 +362,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.13"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
@ -377,18 +377,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.137"
|
||||
version = "1.0.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
|
||||
checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.137"
|
||||
version = "1.0.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
|
||||
checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -406,9 +406,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.6"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
|
||||
checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slotmap"
|
||||
|
@ -421,9 +424,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.8.1"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2"
|
||||
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
|
@ -463,10 +466,11 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.19.2"
|
||||
version = "1.20.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439"
|
||||
checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
|
@ -503,9 +507,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
|
||||
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
|
|
|
@ -6,4 +6,4 @@ A window manager written in [Rust](https://rust-lang.org).
|
|||
|
||||
## Contributing
|
||||
|
||||
Please contribute, we don't know what the fuck we are doing. How we even got to this point is beyond us.
|
||||
Please contribute, we don't know what the fuck we are doing. How we even got to this point is beyond us.
|
164
src/main.rs
164
src/main.rs
|
@ -18,6 +18,7 @@
|
|||
use std::fmt::{Debug, Display};
|
||||
|
||||
use breadx::{
|
||||
auto::xproto::{GrabKeyRequest, GrabMode, KeyButMask, Keycode, Keysym, ModMask},
|
||||
keyboard::KeyboardState,
|
||||
prelude::{AsyncDisplay, AsyncDisplayXprotoExt, MapState},
|
||||
traits::DisplayBase,
|
||||
|
@ -27,7 +28,7 @@ use breadx::{
|
|||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::mpsc::unbounded_channel;
|
||||
|
||||
mod config;
|
||||
mod msg_listener;
|
||||
|
@ -35,6 +36,8 @@ mod x11;
|
|||
|
||||
use x11::client::{may_not_exist, XcrabWindowManager};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[non_exhaustive]
|
||||
pub enum XcrabError {
|
||||
Bread(BreadError),
|
||||
|
@ -76,7 +79,6 @@ impl From<String> for XcrabError {
|
|||
}
|
||||
|
||||
lazy_static! {
|
||||
// pub static ref CONFIG: config::XcrabConfig = config::load_file().unwrap_or_default();
|
||||
pub static ref CONFIG: config::XcrabConfig = config::load_file().unwrap_or_else(|e| {
|
||||
println!("[CONFIG] Error parsing config: {e}");
|
||||
println!("[CONFIG] Falling back to default config");
|
||||
|
@ -91,9 +93,9 @@ impl Display for XcrabError {
|
|||
Self::Io(ie) => Display::fmt(ie, f)?,
|
||||
Self::Toml(te) => Display::fmt(te, f)?,
|
||||
Self::Var(ve) => Display::fmt(ve, f)?,
|
||||
Self::Custom(fe) => Display::fmt(fe, f)?,
|
||||
Self::ClientDoesntExist => Display::fmt("client didn't exist", f)?,
|
||||
}
|
||||
Self::Custom(fe) => Display::fmt(fe, f)?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -117,7 +119,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?;
|
||||
|
||||
|
@ -137,8 +139,68 @@ async fn main() -> Result<()> {
|
|||
|
||||
conn.ungrab_server_async().await?;
|
||||
|
||||
let (send, mut recv) = mpsc::unbounded_channel();
|
||||
let (result_send, result_recv) = mpsc::unbounded_channel();
|
||||
let mut mask = ModMask::new(false, false, true, false, false, false, false, false, false);
|
||||
let mut keyboard_state = KeyboardState::new_async(&mut conn).await?;
|
||||
let keymap = x11::client::keymap(&mut keyboard_state);
|
||||
let mut request_key = *keymap.get(&120).ok_or_else(|| {
|
||||
XcrabError::Custom("At least one letter could not be found in the keymap".to_string())
|
||||
})?;
|
||||
|
||||
for &binds in CONFIG.binds.keys() {
|
||||
for keysym in 97..122_u32 {
|
||||
let keycode = keymap.get(&keysym).ok_or_else(|| {
|
||||
XcrabError::Custom(
|
||||
"At least one letter could not be found in the keymap".to_string(),
|
||||
)
|
||||
})?;
|
||||
let iter_char = keyboard_state
|
||||
.process_keycode(*keycode, KeyButMask::default())
|
||||
.ok_or_else(|| {
|
||||
XcrabError::Custom(
|
||||
"The keycode returned from the keymap could not be processed".to_string(),
|
||||
)
|
||||
})?
|
||||
.as_char()
|
||||
.ok_or_else(|| {
|
||||
XcrabError::Custom("The processed Key could not be cast as a char".to_string())
|
||||
})?;
|
||||
if iter_char == binds.key {
|
||||
request_key = *keycode;
|
||||
mask.inner = binds.mods.inner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mask.set_Two(true);
|
||||
|
||||
conn.exchange_request_async(GrabKeyRequest {
|
||||
req_type: 33,
|
||||
owner_events: false,
|
||||
length: 4,
|
||||
grab_window: root,
|
||||
modifiers: mask,
|
||||
key: request_key,
|
||||
pointer_mode: GrabMode::Async,
|
||||
keyboard_mode: GrabMode::Async,
|
||||
})
|
||||
.await?;
|
||||
|
||||
mask.set_Two(false);
|
||||
|
||||
conn.exchange_request_async(GrabKeyRequest {
|
||||
req_type: 33,
|
||||
owner_events: false,
|
||||
length: 4,
|
||||
grab_window: root,
|
||||
modifiers: mask,
|
||||
key: request_key,
|
||||
pointer_mode: GrabMode::Async,
|
||||
keyboard_mode: GrabMode::Async,
|
||||
})
|
||||
.await?;
|
||||
|
||||
let (send, mut recv) = unbounded_channel();
|
||||
let (result_send, result_recv) = unbounded_channel();
|
||||
|
||||
tokio::spawn(msg_listener::listener_task(
|
||||
CONFIG.msg.clone().unwrap_or_default().socket_path,
|
||||
|
@ -146,25 +208,18 @@ async fn main() -> Result<()> {
|
|||
result_recv,
|
||||
));
|
||||
|
||||
let mut keyboard_state = KeyboardState::new_async(&mut conn).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, &result_send).await?,
|
||||
Ok(ev) = conn.wait_for_event_async() => process_event(ev,
|
||||
&mut manager,
|
||||
&mut conn,
|
||||
root,
|
||||
&mut keyboard_state,
|
||||
).await?,
|
||||
Ok(ev) = conn.wait_for_event_async() => process_event(ev, &mut manager, &mut conn, root, &mut keyboard_state).await?,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)] // FIXME: missing help i have no idea how to make this shorter
|
||||
#[allow(clippy::too_many_lines)]
|
||||
async fn process_event<Dpy: AsyncDisplay + ?Sized>(
|
||||
ev: Event,
|
||||
manager: &mut XcrabWindowManager,
|
||||
|
@ -172,20 +227,6 @@ async fn process_event<Dpy: AsyncDisplay + ?Sized>(
|
|||
root: Window,
|
||||
keyboard_state: &mut KeyboardState,
|
||||
) -> Result<()> {
|
||||
let focused = {
|
||||
// A new scope is required in order to drop the future stored here, and therefore free the
|
||||
// immutable borrow of `manager`
|
||||
let orig = manager
|
||||
.get_focused()
|
||||
.await
|
||||
.map(|w| (w, manager.get_framed_window(w)));
|
||||
if let Some((w, fut)) = orig {
|
||||
Some((w, fut.await))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
match ev {
|
||||
Event::MapRequest(ev) => {
|
||||
manager.add_client(conn, ev.window).await?;
|
||||
|
@ -221,77 +262,22 @@ async fn process_event<Dpy: AsyncDisplay + ?Sized>(
|
|||
manager.remove_client(conn, ev.window).await?;
|
||||
}
|
||||
}
|
||||
Event::ButtonPress(mut ev) => {
|
||||
if ev.detail == 1 && manager.has_client(ev.event) {
|
||||
Event::ButtonPress(ev) => {
|
||||
if ev.detail == 1 {
|
||||
manager.set_focus(conn, ev.event).await?;
|
||||
}
|
||||
if let Some((focused, focused_frame)) = focused {
|
||||
if ev.event == focused_frame.input {
|
||||
ev.event = focused;
|
||||
conn.send_event_async(focused, EventMask::BUTTON_PRESS, Event::ButtonPress(ev))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::KeyPress(mut ev) => {
|
||||
Event::KeyPress(ev) => {
|
||||
if let Some(k) = keyboard_state.process_keycode(ev.detail, ev.state) {
|
||||
if let Some(c) = k.as_char() {
|
||||
for (&bind, action) in &CONFIG.binds {
|
||||
if bind.key == c && bind.mods == ev.state {
|
||||
if bind.key == c {
|
||||
action.eval(manager, conn).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// keybind did not match, forward instead
|
||||
if let Some((focused, _)) = focused {
|
||||
ev.event = focused;
|
||||
conn.send_event_async(focused, EventMask::KEY_PRESS, Event::KeyPress(ev))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
Event::KeyRelease(mut ev) => {
|
||||
if let Some((focused, focused_frame)) = focused {
|
||||
if ev.event == focused_frame.input {
|
||||
ev.event = focused;
|
||||
conn.send_event_async(focused, EventMask::KEY_RELEASE, Event::KeyRelease(ev))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::ButtonRelease(mut ev) => {
|
||||
if let Some((focused, focused_frame)) = focused {
|
||||
if ev.event == focused_frame.input {
|
||||
ev.event = focused;
|
||||
conn.send_event_async(
|
||||
focused,
|
||||
EventMask::BUTTON_RELEASE,
|
||||
Event::ButtonRelease(ev),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::EnterNotify(mut ev) => {
|
||||
if let Some((focused, focused_frame)) = focused {
|
||||
if ev.event == focused_frame.input {
|
||||
ev.event = focused;
|
||||
conn.send_event_async(focused, EventMask::ENTER_WINDOW, Event::EnterNotify(ev))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::LeaveNotify(mut ev) => {
|
||||
if let Some((focused, focused_frame)) = focused {
|
||||
if ev.event == focused_frame.input {
|
||||
ev.event = focused;
|
||||
conn.send_event_async(focused, EventMask::LEAVE_WINDOW, Event::LeaveNotify(ev))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::Result;
|
||||
use serde::Deserialize;
|
||||
use std::path::PathBuf;
|
||||
|
@ -40,11 +39,8 @@ impl Default for XcrabMsgConfig {
|
|||
|
||||
fn load_file_inner() -> Result<XcrabConfig> {
|
||||
let home_dir = get_home();
|
||||
|
||||
let contents = std::fs::read_to_string(format!("{}/.config/xcrab/config.toml", home_dir))?;
|
||||
|
||||
let config: XcrabConfig = toml::from_str(&contents)?;
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ async fn main() -> Result<()> {
|
|||
let path = conf.msg.socket_path;
|
||||
|
||||
let stream = UnixStream::connect(path).await?;
|
||||
|
||||
let (mut read, mut write) = stream.into_split();
|
||||
|
||||
write.write_all(msg.as_bytes()).await?;
|
||||
|
@ -58,7 +59,6 @@ async fn main() -> Result<()> {
|
|||
let mut buf = String::new();
|
||||
|
||||
read.read_to_string(&mut buf).await?;
|
||||
|
||||
if !buf.is_empty() {
|
||||
return Err(CustomError(buf).into());
|
||||
}
|
||||
|
|
|
@ -13,15 +13,10 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use breadx::{
|
||||
auto::xproto::{ClientMessageEvent, InputFocus, SetInputFocusRequest},
|
||||
client_message_data::ClientMessageData,
|
||||
prelude::{AsByteSequence, AsyncDisplayXprotoExt, PropertyType, SetMode},
|
||||
AsyncDisplay, AsyncDisplayExt, Atom, BreadError, ConfigureWindowParameters, ErrorCode, Event,
|
||||
EventMask, Window, WindowParameters, XidType,
|
||||
};
|
||||
use breadx::{auto::xproto::{ClientMessageEvent, InputFocus, SetInputFocusRequest}, client_message_data::ClientMessageData, prelude::{AsByteSequence, AsyncDisplayXprotoExt, PropertyType, SetMode}, AsyncDisplay, AsyncDisplayExt, Atom, BreadError, ConfigureWindowParameters, ErrorCode, Event, EventMask, Window, WindowParameters, XidType, KeyboardState};
|
||||
use slotmap::{new_key_type, SlotMap};
|
||||
use std::{collections::HashMap, future::Future, pin::Pin, slice};
|
||||
use breadx::auto::xproto::{KeyButMask, Keycode, Keysym};
|
||||
|
||||
use crate::{Result, XcrabError, CONFIG};
|
||||
|
||||
|
@ -242,10 +237,7 @@ impl XcrabWindowManager {
|
|||
};
|
||||
|
||||
if let Some(focus) = self.focused {
|
||||
let focused_key = self.clients.get(&focus).unwrap();
|
||||
let focused = self.rects.get(*focused_key).unwrap();
|
||||
let focused_frame = focused.unwrap_client().frame;
|
||||
req.focus = focused_frame.input;
|
||||
req.focus = focus;
|
||||
}
|
||||
|
||||
conn.exchange_request_async(req).await?;
|
||||
|
@ -640,7 +632,6 @@ pub fn may_not_exist(res: breadx::Result) -> breadx::Result {
|
|||
pub struct FramedWindow {
|
||||
pub frame: Window,
|
||||
pub win: Window,
|
||||
pub input: Window,
|
||||
}
|
||||
|
||||
impl FramedWindow {
|
||||
|
@ -700,27 +691,12 @@ impl FramedWindow {
|
|||
.await,
|
||||
)?;
|
||||
|
||||
self.input
|
||||
.configure_async(
|
||||
conn,
|
||||
ConfigureWindowParameters {
|
||||
x: Some(0),
|
||||
y: Some(0),
|
||||
width,
|
||||
height,
|
||||
border_width: None,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn map<Dpy: AsyncDisplay + ?Sized>(self, conn: &mut Dpy) -> Result<()> {
|
||||
may_not_exist(self.win.map_async(conn).await)?;
|
||||
self.frame.map_async(conn).await?;
|
||||
self.input.map_async(conn).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -736,10 +712,6 @@ impl FramedWindow {
|
|||
// no longer related to us, remove from save set
|
||||
may_not_exist(self.win.change_save_set_async(conn, SetMode::Delete).await)?;
|
||||
|
||||
self.input.unmap_async(conn).await?;
|
||||
|
||||
self.input.free_async(conn).await?;
|
||||
|
||||
self.frame.free_async(conn).await?;
|
||||
|
||||
Ok(())
|
||||
|
@ -851,21 +823,6 @@ async fn frame<Dpy: AsyncDisplay + ?Sized>(conn: &mut Dpy, win: Window) -> Resul
|
|||
)
|
||||
.await?;
|
||||
|
||||
let input = conn
|
||||
.create_window_async(
|
||||
frame,
|
||||
breadx::WindowClass::InputOnly,
|
||||
None,
|
||||
Some(conn.default_visual_id()),
|
||||
0,
|
||||
0,
|
||||
geometry.width,
|
||||
geometry.height,
|
||||
0,
|
||||
WindowParameters::default(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
frame
|
||||
.set_event_mask_async(
|
||||
conn,
|
||||
|
@ -876,21 +833,23 @@ async fn frame<Dpy: AsyncDisplay + ?Sized>(conn: &mut Dpy, win: Window) -> Resul
|
|||
win.set_event_mask_async(conn, EventMask::BUTTON_PRESS)
|
||||
.await?;
|
||||
|
||||
input
|
||||
.set_event_mask_async(
|
||||
conn,
|
||||
EventMask::BUTTON_PRESS
|
||||
| EventMask::BUTTON_RELEASE
|
||||
| EventMask::KEY_PRESS
|
||||
| EventMask::KEY_RELEASE
|
||||
| EventMask::ENTER_WINDOW
|
||||
| EventMask::LEAVE_WINDOW,
|
||||
)
|
||||
.await?;
|
||||
|
||||
may_not_exist(win.change_save_set_async(conn, SetMode::Insert).await)?;
|
||||
|
||||
may_not_exist(win.reparent_async(conn, frame, 0, 0).await)?;
|
||||
|
||||
Ok(FramedWindow { frame, win, input })
|
||||
Ok(FramedWindow { frame, win })
|
||||
}
|
||||
|
||||
pub fn keymap(state: &mut KeyboardState) -> HashMap<Keysym, Keycode> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
map
|
||||
}
|
Loading…
Reference in a new issue