keybinds without input-only windows #13
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);
|
||||
karx marked this conversation as resolved
|
||||
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
Why is the third value
true
here?AFAIK the third param is Control, which definitely shouldn't be set by default, unless I'm misunderstanding what this code does
Nevermind, it seems to work anyway, so this is fine. Please see my other comments though.