Diff
diff --git a/default.nix b/default.nix
index 89832d6..0ba80d9 100644
--- a/default.nix
+++ b/default.nix
@@ -29,8 +29,8 @@ rustPlatform.buildRustPackage (finalAttrs: {
];
postInstall = ''
- install oxwm.desktop -Dt $out/share/xsessions
- install -Dm644 oxwm.1 -t $out/share/man/man1
+ install resources/oxwm.desktop -Dt $out/share/xsessions
+ install -Dm644 resource/oxwm.1 -t $out/share/man/man1
'';
passthru.providedSessions = ["oxwm"];
diff --git a/justfile b/justfile
index 1fbc233..1f35402 100644
--- a/justfile
+++ b/justfile
@@ -19,17 +19,17 @@ test-clean:
pkill Xephyr || true
rm -rf ~/.config/oxwm
Xephyr -screen 1280x800 :1 & sleep 1
- DISPLAY=:1 cargo run --release -- --config test-config.ron
+ DISPLAY=:1 cargo run --release -- --config resources/test-config.ron
test:
pkill Xephyr || true
Xephyr -screen 1280x800 :1 & sleep 1
- DISPLAY=:1 cargo run --release -- --config test-config.ron
+ DISPLAY=:1 cargo run --release -- --config resources/test-config.ron
test-multimon:
pkill Xephyr || true
Xephyr +xinerama -screen 640x480 -screen 640x480 :1 & sleep 1
- DISPLAY=:1 cargo run --release -- --config test-config.ron
+ DISPLAY=:1 cargo run --release -- --config resources/test-config.ron
init:
cargo run --release -- --init
diff --git a/PKGBUILD b/resources/PKGBUILD
similarity index 85%
rename from PKGBUILD
rename to resources/PKGBUILD
index 6742acd..1c3b655 100644
--- a/PKGBUILD
+++ b/resources/PKGBUILD
@@ -33,6 +33,6 @@ package() {
cd $_pkgname
install -Dm755 "target/release/$_pkgname" "$pkgdir/usr/bin/$_pkgname"
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
- install -Dm644 oxwm.desktop "$pkgdir/usr/share/xsessions/oxwm.desktop"
- install -Dm644 oxwm.1 "$pkgdir/usr/share/man/man1/oxwm.1"
+ install -Dm644 resources/oxwm.desktop "$pkgdir/usr/share/xsessions/oxwm.desktop"
+ install -Dm644 resources/oxwm.1 "$pkgdir/usr/share/man/man1/oxwm.1"
}
diff --git a/oxwm.1 b/resources/oxwm.1
similarity index 100%
rename from oxwm.1
rename to resources/oxwm.1
diff --git a/oxwm.desktop b/resources/oxwm.desktop
similarity index 100%
rename from oxwm.desktop
rename to resources/oxwm.desktop
diff --git a/test-config.ron b/resources/test-config.ron
similarity index 100%
rename from test-config.ron
rename to resources/test-config.ron
diff --git a/src/config/mod.rs b/src/config/mod.rs
index d7aa2a4..8232b86 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -1,11 +1,12 @@
use crate::bar::{BlockCommand, BlockConfig};
use crate::errors::ConfigError;
use crate::keyboard::handlers::{KeyBinding, KeyPress};
-use crate::keyboard::keycodes;
+use crate::keyboard::keysyms;
use crate::keyboard::{Arg, KeyAction};
+use crate::keyboard::keysyms::Keysym;
use serde::Deserialize;
use std::collections::HashMap;
-use x11rb::protocol::xproto::{KeyButMask, Keycode};
+use x11rb::protocol::xproto::KeyButMask;
#[derive(Debug, Deserialize)]
pub enum ModKey {
@@ -76,172 +77,98 @@ pub enum KeyData {
Comma,
Period,
Slash,
+ AudioRaiseVolume,
+ AudioLowerVolume,
+ AudioMute,
+ MonBrightnessUp,
+ MonBrightnessDown,
}
impl KeyData {
- fn to_keycode(&self) -> Keycode {
+ fn to_keysym(&self) -> Keysym {
match self {
- KeyData::Return => keycodes::RETURN,
- KeyData::Q => keycodes::Q,
- KeyData::Escape => keycodes::ESCAPE,
- KeyData::Space => keycodes::SPACE,
- KeyData::Tab => keycodes::TAB,
- KeyData::Backspace => keycodes::BACKSPACE,
- KeyData::Delete => keycodes::DELETE,
- KeyData::F1 => keycodes::F1,
- KeyData::F2 => keycodes::F2,
- KeyData::F3 => keycodes::F3,
- KeyData::F4 => keycodes::F4,
- KeyData::F5 => keycodes::F5,
- KeyData::F6 => keycodes::F6,
- KeyData::F7 => keycodes::F7,
- KeyData::F8 => keycodes::F8,
- KeyData::F9 => keycodes::F9,
- KeyData::F10 => keycodes::F10,
- KeyData::F11 => keycodes::F11,
- KeyData::F12 => keycodes::F12,
- KeyData::A => keycodes::A,
- KeyData::B => keycodes::B,
- KeyData::C => keycodes::C,
- KeyData::D => keycodes::D,
- KeyData::E => keycodes::E,
- KeyData::F => keycodes::F,
- KeyData::G => keycodes::G,
- KeyData::H => keycodes::H,
- KeyData::I => keycodes::I,
- KeyData::J => keycodes::J,
- KeyData::K => keycodes::K,
- KeyData::L => keycodes::L,
- KeyData::M => keycodes::M,
- KeyData::N => keycodes::N,
- KeyData::O => keycodes::O,
- KeyData::P => keycodes::P,
- KeyData::R => keycodes::R,
- KeyData::S => keycodes::S,
- KeyData::T => keycodes::T,
- KeyData::U => keycodes::U,
- KeyData::V => keycodes::V,
- KeyData::W => keycodes::W,
- KeyData::X => keycodes::X,
- KeyData::Y => keycodes::Y,
- KeyData::Z => keycodes::Z,
- KeyData::Key0 => keycodes::KEY_0,
- KeyData::Key1 => keycodes::KEY_1,
- KeyData::Key2 => keycodes::KEY_2,
- KeyData::Key3 => keycodes::KEY_3,
- KeyData::Key4 => keycodes::KEY_4,
- KeyData::Key5 => keycodes::KEY_5,
- KeyData::Key6 => keycodes::KEY_6,
- KeyData::Key7 => keycodes::KEY_7,
- KeyData::Key8 => keycodes::KEY_8,
- KeyData::Key9 => keycodes::KEY_9,
- KeyData::Left => keycodes::LEFT,
- KeyData::Right => keycodes::RIGHT,
- KeyData::Up => keycodes::UP,
- KeyData::Down => keycodes::DOWN,
- KeyData::Home => keycodes::HOME,
- KeyData::End => keycodes::END,
- KeyData::PageUp => keycodes::PAGE_UP,
- KeyData::PageDown => keycodes::PAGE_DOWN,
- KeyData::Insert => keycodes::INSERT,
- KeyData::Minus => keycodes::MINUS,
- KeyData::Equal => keycodes::EQUAL,
- KeyData::BracketLeft => keycodes::LEFT_BRACKET,
- KeyData::BracketRight => keycodes::RIGHT_BRACKET,
- KeyData::Semicolon => keycodes::SEMICOLON,
- KeyData::Apostrophe => keycodes::APOSTROPHE,
- KeyData::Grave => keycodes::GRAVE,
- KeyData::Backslash => keycodes::BACKSLASH,
- KeyData::Comma => keycodes::COMMA,
- KeyData::Period => keycodes::PERIOD,
- KeyData::Slash => keycodes::SLASH,
+ KeyData::Return => keysyms::XK_RETURN,
+ KeyData::Q => keysyms::XK_Q,
+ KeyData::Escape => keysyms::XK_ESCAPE,
+ KeyData::Space => keysyms::XK_SPACE,
+ KeyData::Tab => keysyms::XK_TAB,
+ KeyData::Backspace => keysyms::XK_BACKSPACE,
+ KeyData::Delete => keysyms::XK_DELETE,
+ KeyData::F1 => keysyms::XK_F1,
+ KeyData::F2 => keysyms::XK_F2,
+ KeyData::F3 => keysyms::XK_F3,
+ KeyData::F4 => keysyms::XK_F4,
+ KeyData::F5 => keysyms::XK_F5,
+ KeyData::F6 => keysyms::XK_F6,
+ KeyData::F7 => keysyms::XK_F7,
+ KeyData::F8 => keysyms::XK_F8,
+ KeyData::F9 => keysyms::XK_F9,
+ KeyData::F10 => keysyms::XK_F10,
+ KeyData::F11 => keysyms::XK_F11,
+ KeyData::F12 => keysyms::XK_F12,
+ KeyData::A => keysyms::XK_A,
+ KeyData::B => keysyms::XK_B,
+ KeyData::C => keysyms::XK_C,
+ KeyData::D => keysyms::XK_D,
+ KeyData::E => keysyms::XK_E,
+ KeyData::F => keysyms::XK_F,
+ KeyData::G => keysyms::XK_G,
+ KeyData::H => keysyms::XK_H,
+ KeyData::I => keysyms::XK_I,
+ KeyData::J => keysyms::XK_J,
+ KeyData::K => keysyms::XK_K,
+ KeyData::L => keysyms::XK_L,
+ KeyData::M => keysyms::XK_M,
+ KeyData::N => keysyms::XK_N,
+ KeyData::O => keysyms::XK_O,
+ KeyData::P => keysyms::XK_P,
+ KeyData::R => keysyms::XK_R,
+ KeyData::S => keysyms::XK_S,
+ KeyData::T => keysyms::XK_T,
+ KeyData::U => keysyms::XK_U,
+ KeyData::V => keysyms::XK_V,
+ KeyData::W => keysyms::XK_W,
+ KeyData::X => keysyms::XK_X,
+ KeyData::Y => keysyms::XK_Y,
+ KeyData::Z => keysyms::XK_Z,
+ KeyData::Key0 => keysyms::XK_0,
+ KeyData::Key1 => keysyms::XK_1,
+ KeyData::Key2 => keysyms::XK_2,
+ KeyData::Key3 => keysyms::XK_3,
+ KeyData::Key4 => keysyms::XK_4,
+ KeyData::Key5 => keysyms::XK_5,
+ KeyData::Key6 => keysyms::XK_6,
+ KeyData::Key7 => keysyms::XK_7,
+ KeyData::Key8 => keysyms::XK_8,
+ KeyData::Key9 => keysyms::XK_9,
+ KeyData::Left => keysyms::XK_LEFT,
+ KeyData::Right => keysyms::XK_RIGHT,
+ KeyData::Up => keysyms::XK_UP,
+ KeyData::Down => keysyms::XK_DOWN,
+ KeyData::Home => keysyms::XK_HOME,
+ KeyData::End => keysyms::XK_END,
+ KeyData::PageUp => keysyms::XK_PAGE_UP,
+ KeyData::PageDown => keysyms::XK_PAGE_DOWN,
+ KeyData::Insert => keysyms::XK_INSERT,
+ KeyData::Minus => keysyms::XK_MINUS,
+ KeyData::Equal => keysyms::XK_EQUAL,
+ KeyData::BracketLeft => keysyms::XK_LEFT_BRACKET,
+ KeyData::BracketRight => keysyms::XK_RIGHT_BRACKET,
+ KeyData::Semicolon => keysyms::XK_SEMICOLON,
+ KeyData::Apostrophe => keysyms::XK_APOSTROPHE,
+ KeyData::Grave => keysyms::XK_GRAVE,
+ KeyData::Backslash => keysyms::XK_BACKSLASH,
+ KeyData::Comma => keysyms::XK_COMMA,
+ KeyData::Period => keysyms::XK_PERIOD,
+ KeyData::Slash => keysyms::XK_SLASH,
+ KeyData::AudioRaiseVolume => keysyms::XF86_AUDIO_RAISE_VOLUME,
+ KeyData::AudioLowerVolume => keysyms::XF86_AUDIO_LOWER_VOLUME,
+ KeyData::AudioMute => keysyms::XF86_AUDIO_MUTE,
+ KeyData::MonBrightnessUp => keysyms::XF86_MON_BRIGHTNESS_UP,
+ KeyData::MonBrightnessDown => keysyms::XF86_MON_BRIGHTNESS_DOWN,
}
}
- // Adding this reverse lookup for now so converting to KeySyms is no longer
- // an 'unsafe' call to a C FFI (Sorry Bugsy...)
- // This will set us up in the future to move away from hardcoded keycodes,
- // and directly convert keysyms to keydata at runtime for international
- // keyboard support.
- pub fn from_keycode(keycode: Keycode) -> Option<&'static str> {
- match keycode {
- keycodes::RETURN => Some("Return"),
- keycodes::Q => Some("q"),
- keycodes::ESCAPE => Some("Esc"),
- keycodes::SPACE => Some("Space"),
- keycodes::TAB => Some("Tab"),
- keycodes::BACKSPACE => Some("Backspace"),
- keycodes::DELETE => Some("Del"),
- keycodes::F1 => Some("F1"),
- keycodes::F2 => Some("F2"),
- keycodes::F3 => Some("F3"),
- keycodes::F4 => Some("F4"),
- keycodes::F5 => Some("F5"),
- keycodes::F6 => Some("F6"),
- keycodes::F7 => Some("F7"),
- keycodes::F8 => Some("F8"),
- keycodes::F9 => Some("F9"),
- keycodes::F10 => Some("F10"),
- keycodes::F11 => Some("F11"),
- keycodes::F12 => Some("F12"),
- keycodes::A => Some("a"),
- keycodes::B => Some("b"),
- keycodes::C => Some("c"),
- keycodes::D => Some("d"),
- keycodes::E => Some("e"),
- keycodes::F => Some("f"),
- keycodes::G => Some("g"),
- keycodes::H => Some("h"),
- keycodes::I => Some("i"),
- keycodes::J => Some("j"),
- keycodes::K => Some("k"),
- keycodes::L => Some("l"),
- keycodes::M => Some("m"),
- keycodes::N => Some("n"),
- keycodes::O => Some("o"),
- keycodes::P => Some("p"),
- keycodes::R => Some("r"),
- keycodes::S => Some("s"),
- keycodes::T => Some("t"),
- keycodes::U => Some("u"),
- keycodes::V => Some("v"),
- keycodes::W => Some("w"),
- keycodes::X => Some("x"),
- keycodes::Y => Some("y"),
- keycodes::Z => Some("z"),
- keycodes::KEY_0 => Some("0"),
- keycodes::KEY_1 => Some("1"),
- keycodes::KEY_2 => Some("2"),
- keycodes::KEY_3 => Some("3"),
- keycodes::KEY_4 => Some("4"),
- keycodes::KEY_5 => Some("5"),
- keycodes::KEY_6 => Some("6"),
- keycodes::KEY_7 => Some("7"),
- keycodes::KEY_8 => Some("8"),
- keycodes::KEY_9 => Some("9"),
- keycodes::LEFT => Some("Left"),
- keycodes::RIGHT => Some("Right"),
- keycodes::UP => Some("Up"),
- keycodes::DOWN => Some("Down"),
- keycodes::HOME => Some("Home"),
- keycodes::END => Some("End"),
- keycodes::PAGE_UP => Some("PgUp"),
- keycodes::PAGE_DOWN => Some("PgDn"),
- keycodes::INSERT => Some("Ins"),
- keycodes::MINUS => Some("-"),
- keycodes::EQUAL => Some("="),
- keycodes::LEFT_BRACKET => Some("["),
- keycodes::RIGHT_BRACKET => Some("]"),
- keycodes::SEMICOLON => Some(";"),
- keycodes::APOSTROPHE => Some("'"),
- keycodes::GRAVE => Some("`"),
- keycodes::BACKSLASH => Some("\\"),
- keycodes::COMMA => Some(","),
- keycodes::PERIOD => Some("."),
- keycodes::SLASH => Some("/"),
- _ => None,
- }
- }
}
fn preprocess_variables(input: &str) -> Result<String, ConfigError> {
@@ -412,7 +339,7 @@ fn config_data_to_config(data: ConfigData) -> Result<crate::Config, ConfigError>
KeyPress {
modifiers,
- key: kp.key.to_keycode(),
+ keysym: kp.key.to_keysym(),
}
})
.collect()
@@ -425,7 +352,7 @@ fn config_data_to_config(data: ConfigData) -> Result<crate::Config, ConfigError>
_ => m.to_keybut_mask(),
})
.collect(),
- key: key.to_keycode(),
+ keysym: key.to_keysym(),
}]
} else {
return Err(ConfigError::ValidationError(
diff --git a/src/keyboard/handlers.rs b/src/keyboard/handlers.rs
index 7e6ff2b..226303d 100644
--- a/src/keyboard/handlers.rs
+++ b/src/keyboard/handlers.rs
@@ -1,6 +1,5 @@
-use std::collections::HashSet;
-use std::io;
-use std::io::ErrorKind;
+use std::collections::HashMap;
+use std::io::{ErrorKind, Result};
use std::process::Command;
use serde::Deserialize;
@@ -8,7 +7,7 @@ use x11rb::connection::Connection;
use x11rb::protocol::xproto::*;
use crate::errors::X11Error;
-use crate::keyboard::keycodes;
+use crate::keyboard::keysyms::{self, Keysym};
#[derive(Debug, Copy, Clone, Deserialize)]
pub enum KeyAction {
@@ -48,7 +47,7 @@ impl Arg {
#[derive(Clone, Debug)]
pub struct KeyPress {
pub(crate) modifiers: Vec<KeyButMask>,
- pub(crate) key: Keycode,
+ pub(crate) keysym: Keysym,
}
#[derive(Clone)]
@@ -63,9 +62,14 @@ impl KeyBinding {
Self { keys, func, arg }
}
- pub fn single_key(modifiers: Vec<KeyButMask>, key: Keycode, func: KeyAction, arg: Arg) -> Self {
+ pub fn single_key(
+ modifiers: Vec<KeyButMask>,
+ keysym: Keysym,
+ func: KeyAction,
+ arg: Arg,
+ ) -> Self {
Self {
- keys: vec![KeyPress { modifiers, key }],
+ keys: vec![KeyPress { modifiers, keysym }],
func,
arg,
}
@@ -96,11 +100,48 @@ pub fn modifiers_to_mask(modifiers: &[KeyButMask]) -> u16 {
.fold(0u16, |acc, &modifier| acc | u16::from(modifier))
}
+fn build_keysym_maps(
+ connection: &impl Connection,
+) -> std::result::Result<(HashMap<Keysym, Vec<Keycode>>, HashMap<Keycode, Keysym>), X11Error> {
+ let setup = connection.setup();
+ let min_keycode = setup.min_keycode;
+ let max_keycode = setup.max_keycode;
+
+ let keyboard_mapping = connection
+ .get_keyboard_mapping(min_keycode, max_keycode - min_keycode + 1)?
+ .reply()?;
+
+ let mut keysym_to_keycode: HashMap<Keysym, Vec<Keycode>> = HashMap::new();
+ let mut keycode_to_keysym: HashMap<Keycode, Keysym> = HashMap::new();
+ let keysyms_per_keycode = keyboard_mapping.keysyms_per_keycode;
+
+ for keycode in min_keycode..=max_keycode {
+ let index = (keycode - min_keycode) as usize * keysyms_per_keycode as usize;
+
+ for i in 0..keysyms_per_keycode as usize {
+ if let Some(&keysym) = keyboard_mapping.keysyms.get(index + i) {
+ if keysym != 0 {
+ keysym_to_keycode
+ .entry(keysym)
+ .or_insert_with(Vec::new)
+ .push(keycode);
+ keycode_to_keysym.entry(keycode).or_insert(keysym);
+ }
+ }
+ }
+ }
+
+ Ok((keysym_to_keycode, keycode_to_keysym))
+}
+
pub fn setup_keybinds(
connection: &impl Connection,
root: Window,
keybindings: &[KeyBinding],
-) -> Result<(), X11Error> {
+) -> std::result::Result<(), X11Error> {
+ use std::collections::HashSet;
+
+ let (keysym_to_keycode, _) = build_keysym_maps(connection)?;
let mut grabbed_keys: HashSet<(u16, Keycode)> = HashSet::new();
for keybinding in keybindings {
@@ -110,29 +151,25 @@ pub fn setup_keybinds(
let first_key = &keybinding.keys[0];
let modifier_mask = modifiers_to_mask(&first_key.modifiers);
- let key_tuple = (modifier_mask, first_key.key);
-
- if grabbed_keys.insert(key_tuple) {
- connection.grab_key(
- false,
- root,
- modifier_mask.into(),
- first_key.key,
- GrabMode::ASYNC,
- GrabMode::ASYNC,
- )?;
+
+ if let Some(keycodes) = keysym_to_keycode.get(&first_key.keysym) {
+ if let Some(&keycode) = keycodes.first() {
+ let key_tuple = (modifier_mask, keycode);
+
+ if grabbed_keys.insert(key_tuple) {
+ connection.grab_key(
+ false,
+ root,
+ modifier_mask.into(),
+ keycode,
+ GrabMode::ASYNC,
+ GrabMode::ASYNC,
+ )?;
+ }
+ }
}
}
- connection.grab_key(
- false,
- root,
- ModMask::from(0u16),
- keycodes::ESCAPE,
- GrabMode::ASYNC,
- GrabMode::ASYNC,
- )?;
-
Ok(())
}
@@ -140,24 +177,32 @@ pub fn handle_key_press(
event: KeyPressEvent,
keybindings: &[KeyBinding],
keychord_state: &KeychordState,
-) -> KeychordResult {
- if event.detail == keycodes::ESCAPE {
- return match keychord_state {
+ connection: &impl Connection,
+) -> std::result::Result<KeychordResult, X11Error> {
+ let (_, keycode_to_keysym) = build_keysym_maps(connection)?;
+ let event_keysym = keycode_to_keysym.get(&event.detail).copied().unwrap_or(0);
+
+ if event_keysym == keysyms::XK_ESCAPE {
+ return Ok(match keychord_state {
KeychordState::InProgress { .. } => KeychordResult::Cancelled,
KeychordState::Idle => KeychordResult::None,
- };
+ });
}
- match keychord_state {
- KeychordState::Idle => handle_first_key(event, keybindings),
+ Ok(match keychord_state {
+ KeychordState::Idle => handle_first_key(event, event_keysym, keybindings),
KeychordState::InProgress {
candidates,
keys_pressed,
- } => handle_next_key(event, keybindings, candidates, *keys_pressed),
- }
+ } => handle_next_key(event, event_keysym, keybindings, candidates, *keys_pressed),
+ })
}
-fn handle_first_key(event: KeyPressEvent, keybindings: &[KeyBinding]) -> KeychordResult {
+fn handle_first_key(
+ event: KeyPressEvent,
+ event_keysym: Keysym,
+ keybindings: &[KeyBinding],
+) -> KeychordResult {
let mut candidates = Vec::new();
for (keybinding_index, keybinding) in keybindings.iter().enumerate() {
@@ -168,7 +213,7 @@ fn handle_first_key(event: KeyPressEvent, keybindings: &[KeyBinding]) -> Keychor
let first_key = &keybinding.keys[0];
let modifier_mask = modifiers_to_mask(&first_key.modifiers);
- if event.detail == first_key.key && event.state == modifier_mask.into() {
+ if event_keysym == first_key.keysym && event.state == modifier_mask.into() {
if keybinding.keys.len() == 1 {
return KeychordResult::Completed(keybinding.func, keybinding.arg.clone());
} else {
@@ -186,6 +231,7 @@ fn handle_first_key(event: KeyPressEvent, keybindings: &[KeyBinding]) -> Keychor
fn handle_next_key(
event: KeyPressEvent,
+ event_keysym: Keysym,
keybindings: &[KeyBinding],
candidates: &[usize],
keys_pressed: usize,
@@ -209,7 +255,7 @@ fn handle_next_key(
(event_state & required_mask) == required_mask
};
- if event.detail == next_key.key && modifiers_match {
+ if event_keysym == next_key.keysym && modifiers_match {
if keys_pressed + 1 == keybinding.keys.len() {
return KeychordResult::Completed(keybinding.func, keybinding.arg.clone());
} else {
@@ -225,7 +271,7 @@ fn handle_next_key(
}
}
-pub fn handle_spawn_action(action: KeyAction, arg: &Arg) -> io::Result<()> {
+pub fn handle_spawn_action(action: KeyAction, arg: &Arg) -> Result<()> {
if let KeyAction::Spawn = action {
match arg {
Arg::Str(command) => match Command::new(command.as_str()).spawn() {
diff --git a/src/keyboard/keycodes.rs b/src/keyboard/keycodes.rs
deleted file mode 100644
index 307b57c..0000000
--- a/src/keyboard/keycodes.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-#![allow(dead_code)]
-// Allowing dead code here because its just a file for potential keybinds
-pub const RETURN: u8 = 36;
-pub const Q: u8 = 24;
-pub const ESCAPE: u8 = 9;
-pub const SPACE: u8 = 65;
-pub const TAB: u8 = 23;
-pub const BACKSPACE: u8 = 22;
-pub const DELETE: u8 = 119;
-
-// Function Keys
-pub const F1: u8 = 67;
-pub const F2: u8 = 68;
-pub const F3: u8 = 69;
-pub const F4: u8 = 70;
-pub const F5: u8 = 71;
-pub const F6: u8 = 72;
-pub const F7: u8 = 73;
-pub const F8: u8 = 74;
-pub const F9: u8 = 75;
-pub const F10: u8 = 76;
-pub const F11: u8 = 95;
-pub const F12: u8 = 96;
-
-// Letters
-pub const A: u8 = 38;
-pub const B: u8 = 56;
-pub const C: u8 = 54;
-pub const D: u8 = 40;
-pub const E: u8 = 26;
-pub const F: u8 = 41;
-pub const G: u8 = 42;
-pub const H: u8 = 43;
-pub const I: u8 = 31;
-pub const J: u8 = 44;
-pub const K: u8 = 45;
-pub const L: u8 = 46;
-pub const M: u8 = 58;
-pub const N: u8 = 57;
-pub const O: u8 = 32;
-pub const P: u8 = 33;
-pub const R: u8 = 27;
-pub const S: u8 = 39;
-pub const T: u8 = 28;
-pub const U: u8 = 30;
-pub const V: u8 = 55;
-pub const W: u8 = 25;
-pub const X: u8 = 53;
-pub const Y: u8 = 29;
-pub const Z: u8 = 52;
-
-// Numbers
-pub const KEY_0: u8 = 19;
-pub const KEY_1: u8 = 10;
-pub const KEY_2: u8 = 11;
-pub const KEY_3: u8 = 12;
-pub const KEY_4: u8 = 13;
-pub const KEY_5: u8 = 14;
-pub const KEY_6: u8 = 15;
-pub const KEY_7: u8 = 16;
-pub const KEY_8: u8 = 17;
-pub const KEY_9: u8 = 18;
-
-// Arrows
-pub const LEFT: u8 = 113;
-pub const RIGHT: u8 = 114;
-pub const UP: u8 = 111;
-pub const DOWN: u8 = 116;
-pub const HOME: u8 = 110;
-pub const END: u8 = 115;
-pub const PAGE_UP: u8 = 112;
-pub const PAGE_DOWN: u8 = 117;
-pub const INSERT: u8 = 118;
-
-// Symbols
-pub const MINUS: u8 = 20;
-pub const EQUAL: u8 = 21;
-pub const LEFT_BRACKET: u8 = 34;
-pub const RIGHT_BRACKET: u8 = 35;
-pub const SEMICOLON: u8 = 47;
-pub const APOSTROPHE: u8 = 48;
-pub const GRAVE: u8 = 49;
-pub const BACKSLASH: u8 = 51;
-pub const COMMA: u8 = 59;
-pub const PERIOD: u8 = 60;
-pub const SLASH: u8 = 61;
diff --git a/src/keyboard/keysyms.rs b/src/keyboard/keysyms.rs
new file mode 100644
index 0000000..42e1330
--- /dev/null
+++ b/src/keyboard/keysyms.rs
@@ -0,0 +1,84 @@
+#![allow(dead_code)]
+
+pub type Keysym = u32;
+pub const XK_ESCAPE: Keysym = 0xff1b;
+pub const XK_RETURN: Keysym = 0xff0d;
+pub const XK_SPACE: Keysym = 0x0020;
+pub const XK_TAB: Keysym = 0xff09;
+pub const XK_BACKSPACE: Keysym = 0xff08;
+pub const XK_DELETE: Keysym = 0xffff;
+pub const XK_F1: Keysym = 0xffbe;
+pub const XK_F2: Keysym = 0xffbf;
+pub const XK_F3: Keysym = 0xffc0;
+pub const XK_F4: Keysym = 0xffc1;
+pub const XK_F5: Keysym = 0xffc2;
+pub const XK_F6: Keysym = 0xffc3;
+pub const XK_F7: Keysym = 0xffc4;
+pub const XK_F8: Keysym = 0xffc5;
+pub const XK_F9: Keysym = 0xffc6;
+pub const XK_F10: Keysym = 0xffc7;
+pub const XK_F11: Keysym = 0xffc8;
+pub const XK_F12: Keysym = 0xffc9;
+pub const XK_A: Keysym = 0x0061;
+pub const XK_B: Keysym = 0x0062;
+pub const XK_C: Keysym = 0x0063;
+pub const XK_D: Keysym = 0x0064;
+pub const XK_E: Keysym = 0x0065;
+pub const XK_F: Keysym = 0x0066;
+pub const XK_G: Keysym = 0x0067;
+pub const XK_H: Keysym = 0x0068;
+pub const XK_I: Keysym = 0x0069;
+pub const XK_J: Keysym = 0x006a;
+pub const XK_K: Keysym = 0x006b;
+pub const XK_L: Keysym = 0x006c;
+pub const XK_M: Keysym = 0x006d;
+pub const XK_N: Keysym = 0x006e;
+pub const XK_O: Keysym = 0x006f;
+pub const XK_P: Keysym = 0x0070;
+pub const XK_Q: Keysym = 0x0071;
+pub const XK_R: Keysym = 0x0072;
+pub const XK_S: Keysym = 0x0073;
+pub const XK_T: Keysym = 0x0074;
+pub const XK_U: Keysym = 0x0075;
+pub const XK_V: Keysym = 0x0076;
+pub const XK_W: Keysym = 0x0077;
+pub const XK_X: Keysym = 0x0078;
+pub const XK_Y: Keysym = 0x0079;
+pub const XK_Z: Keysym = 0x007a;
+pub const XK_0: Keysym = 0x0030;
+pub const XK_1: Keysym = 0x0031;
+pub const XK_2: Keysym = 0x0032;
+pub const XK_3: Keysym = 0x0033;
+pub const XK_4: Keysym = 0x0034;
+pub const XK_5: Keysym = 0x0035;
+pub const XK_6: Keysym = 0x0036;
+pub const XK_7: Keysym = 0x0037;
+pub const XK_8: Keysym = 0x0038;
+pub const XK_9: Keysym = 0x0039;
+pub const XK_LEFT: Keysym = 0xff51;
+pub const XK_UP: Keysym = 0xff52;
+pub const XK_RIGHT: Keysym = 0xff53;
+pub const XK_DOWN: Keysym = 0xff54;
+pub const XK_HOME: Keysym = 0xff50;
+pub const XK_END: Keysym = 0xff57;
+pub const XK_PAGE_UP: Keysym = 0xff55;
+pub const XK_PAGE_DOWN: Keysym = 0xff56;
+pub const XK_INSERT: Keysym = 0xff63;
+pub const XK_MINUS: Keysym = 0x002d;
+pub const XK_EQUAL: Keysym = 0x003d;
+pub const XK_LEFT_BRACKET: Keysym = 0x005b;
+pub const XK_RIGHT_BRACKET: Keysym = 0x005d;
+pub const XK_SEMICOLON: Keysym = 0x003b;
+pub const XK_APOSTROPHE: Keysym = 0x0027;
+pub const XK_GRAVE: Keysym = 0x0060;
+pub const XK_BACKSLASH: Keysym = 0x005c;
+pub const XK_COMMA: Keysym = 0x002c;
+pub const XK_PERIOD: Keysym = 0x002e;
+pub const XK_SLASH: Keysym = 0x002f;
+pub const XK_PRINT: Keysym = 0xff61;
+
+pub const XF86_AUDIO_RAISE_VOLUME: Keysym = 0x1008ff13;
+pub const XF86_AUDIO_LOWER_VOLUME: Keysym = 0x1008ff11;
+pub const XF86_AUDIO_MUTE: Keysym = 0x1008ff12;
+pub const XF86_MON_BRIGHTNESS_UP: Keysym = 0x1008ff02;
+pub const XF86_MON_BRIGHTNESS_DOWN: Keysym = 0x1008ff03;
diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs
index 7e76b4a..5ba8b15 100644
--- a/src/keyboard/mod.rs
+++ b/src/keyboard/mod.rs
@@ -1,5 +1,5 @@
pub mod handlers;
-pub mod keycodes;
+pub mod keysyms;
pub use handlers::{Arg, KeyAction, handle_key_press, setup_keybinds};
-pub use keycodes::*;
+pub use keysyms::*;
diff --git a/src/lib.rs b/src/lib.rs
index 75da74b..8f55ebf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -10,7 +10,7 @@ pub mod prelude {
pub use crate::ColorScheme;
pub use crate::LayoutSymbolOverride;
pub use crate::bar::{BlockCommand, BlockConfig};
- pub use crate::keyboard::{Arg, KeyAction, handlers::KeyBinding, keycodes};
+ pub use crate::keyboard::{Arg, KeyAction, handlers::KeyBinding, keysyms};
pub use x11rb::protocol::xproto::KeyButMask;
}
@@ -67,7 +67,7 @@ pub struct ColorScheme {
impl Default for Config {
fn default() -> Self {
use crate::keyboard::handlers::KeyBinding;
- use crate::keyboard::{Arg, KeyAction, keycodes};
+ use crate::keyboard::{Arg, KeyAction, keysyms};
use x11rb::protocol::xproto::KeyButMask;
const MODKEY: KeyButMask = KeyButMask::MOD4;
@@ -95,13 +95,13 @@ impl Default for Config {
keybindings: vec![
KeyBinding::single_key(
vec![MODKEY],
- keycodes::RETURN,
+ keysyms::XK_RETURN,
KeyAction::Spawn,
Arg::Str(TERMINAL.to_string()),
),
KeyBinding::single_key(
vec![MODKEY],
- keycodes::D,
+ keysyms::XK_D,
KeyAction::Spawn,
Arg::Array(vec![
"sh".to_string(),
@@ -109,169 +109,169 @@ impl Default for Config {
"dmenu_run -l 10".to_string(),
]),
),
- KeyBinding::single_key(vec![MODKEY], keycodes::Q, KeyAction::KillClient, Arg::None),
- KeyBinding::single_key(vec![MODKEY], keycodes::N, KeyAction::CycleLayout, Arg::None),
+ KeyBinding::single_key(vec![MODKEY], keysyms::XK_Q, KeyAction::KillClient, Arg::None),
+ KeyBinding::single_key(vec![MODKEY], keysyms::XK_N, KeyAction::CycleLayout, Arg::None),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::F,
+ keysyms::XK_F,
KeyAction::ToggleFullScreen,
Arg::None,
),
- KeyBinding::single_key(vec![MODKEY], keycodes::A, KeyAction::ToggleGaps, Arg::None),
- KeyBinding::single_key(vec![MODKEY, SHIFT], keycodes::Q, KeyAction::Quit, Arg::None),
+ KeyBinding::single_key(vec![MODKEY], keysyms::XK_A, KeyAction::ToggleGaps, Arg::None),
+ KeyBinding::single_key(vec![MODKEY, SHIFT], keysyms::XK_Q, KeyAction::Quit, Arg::None),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::R,
+ keysyms::XK_R,
KeyAction::Restart,
Arg::None,
),
KeyBinding::single_key(
vec![MODKEY],
- keycodes::F,
+ keysyms::XK_F,
KeyAction::ToggleFloating,
Arg::None,
),
KeyBinding::single_key(
vec![MODKEY],
- keycodes::J,
+ keysyms::XK_J,
KeyAction::FocusStack,
Arg::Int(-1),
),
KeyBinding::single_key(
vec![MODKEY],
- keycodes::K,
+ keysyms::XK_K,
KeyAction::FocusStack,
Arg::Int(1),
),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::K,
+ keysyms::XK_K,
KeyAction::ExchangeClient,
Arg::Int(0), // UP
),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::J,
+ keysyms::XK_J,
KeyAction::ExchangeClient,
Arg::Int(1), // DOWN
),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::H,
+ keysyms::XK_H,
KeyAction::ExchangeClient,
Arg::Int(2), // LEFT
),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::L,
+ keysyms::XK_L,
KeyAction::ExchangeClient,
Arg::Int(3), // RIGHT
),
KeyBinding::single_key(
vec![MODKEY],
- keycodes::KEY_1,
+ keysyms::XK_1,
KeyAction::ViewTag,
Arg::Int(0),
),
KeyBinding::single_key(
vec![MODKEY],
- keycodes::KEY_2,
+ keysyms::XK_2,
KeyAction::ViewTag,
Arg::Int(1),
),
KeyBinding::single_key(
vec![MODKEY],
- keycodes::KEY_3,
+ keysyms::XK_3,
KeyAction::ViewTag,
Arg::Int(2),
),
KeyBinding::single_key(
vec![MODKEY],
- keycodes::KEY_4,
+ keysyms::XK_4,
KeyAction::ViewTag,
Arg::Int(3),
),
KeyBinding::single_key(
vec![MODKEY],
- keycodes::KEY_5,
+ keysyms::XK_5,
KeyAction::ViewTag,
Arg::Int(4),
),
KeyBinding::single_key(
vec![MODKEY],
- keycodes::KEY_6,
+ keysyms::XK_6,
KeyAction::ViewTag,
Arg::Int(5),
),
KeyBinding::single_key(
vec![MODKEY],
- keycodes::KEY_7,
+ keysyms::XK_7,
KeyAction::ViewTag,
Arg::Int(6),
),
KeyBinding::single_key(
vec![MODKEY],
- keycodes::KEY_8,
+ keysyms::XK_8,
KeyAction::ViewTag,
Arg::Int(7),
),
KeyBinding::single_key(
vec![MODKEY],
- keycodes::KEY_9,
+ keysyms::XK_9,
KeyAction::ViewTag,
Arg::Int(8),
),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::KEY_1,
+ keysyms::XK_1,
KeyAction::MoveToTag,
Arg::Int(0),
),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::KEY_2,
+ keysyms::XK_2,
KeyAction::MoveToTag,
Arg::Int(1),
),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::KEY_3,
+ keysyms::XK_3,
KeyAction::MoveToTag,
Arg::Int(2),
),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::KEY_4,
+ keysyms::XK_4,
KeyAction::MoveToTag,
Arg::Int(3),
),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::KEY_5,
+ keysyms::XK_5,
KeyAction::MoveToTag,
Arg::Int(4),
),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::KEY_6,
+ keysyms::XK_6,
KeyAction::MoveToTag,
Arg::Int(5),
),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::KEY_7,
+ keysyms::XK_7,
KeyAction::MoveToTag,
Arg::Int(6),
),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::KEY_8,
+ keysyms::XK_8,
KeyAction::MoveToTag,
Arg::Int(7),
),
KeyBinding::single_key(
vec![MODKEY, SHIFT],
- keycodes::KEY_9,
+ keysyms::XK_9,
KeyAction::MoveToTag,
Arg::Int(8),
),
diff --git a/src/window_manager.rs b/src/window_manager.rs
index 0980289..aa2a488 100644
--- a/src/window_manager.rs
+++ b/src/window_manager.rs
@@ -59,7 +59,7 @@ pub struct WindowManager {
window_monitor: std::collections::HashMap<Window, usize>,
window_geometries: std::collections::HashMap<Window, (i16, i16, u16, u16)>,
gaps_enabled: bool,
- fullscreen_window: Option<Window>,
+ fullscreen_enabled: bool,
floating_windows: HashSet<Window>,
bars: Vec<Bar>,
monitors: Vec<Monitor>,
@@ -168,7 +168,7 @@ impl WindowManager {
window_monitor: std::collections::HashMap::new(),
window_geometries: std::collections::HashMap::new(),
gaps_enabled,
- fullscreen_window: None,
+ fullscreen_enabled: false,
floating_windows: HashSet::new(),
bars,
monitors,
@@ -388,6 +388,17 @@ impl WindowManager {
{
if self.floating_windows.contains(&focused) {
self.floating_windows.remove(&focused);
+
+ let selected_tags = self
+ .monitors
+ .get(self.selected_monitor)
+ .map(|m| m.selected_tags)
+ .unwrap_or(tag_mask(0));
+
+ self.window_tags.insert(focused, selected_tags);
+ self.window_monitor.insert(focused, self.selected_monitor);
+ let _ = self.save_client_tag(focused, selected_tags);
+
self.apply_layout()?;
} else {
let float_width = (self.screen.width_in_pixels / 2) as u32;
@@ -428,10 +439,6 @@ impl WindowManager {
None => return Ok(()),
};
- if self.fullscreen_window == Some(focused) {
- return Ok(());
- }
-
if !self.floating_windows.contains(&focused) {
let float_width = (self.screen.width_in_pixels / 2) as u32;
let float_height = (self.screen.height_in_pixels / 2) as u32;
@@ -690,7 +697,7 @@ impl WindowManager {
None => return Ok(()),
};
- if self.fullscreen_window == Some(focused) || self.floating_windows.contains(&focused) {
+ if self.floating_windows.contains(&focused) {
return Ok(());
}
@@ -750,44 +757,19 @@ impl WindowManager {
}
fn toggle_fullscreen(&mut self) -> WmResult<()> {
- if let Some(focused) = self
- .monitors
- .get(self.selected_monitor)
- .and_then(|m| m.focused_window)
- {
- if self.fullscreen_window == Some(focused) {
- self.fullscreen_window = None;
-
- for bar in &self.bars {
- self.connection.map_window(bar.window())?;
- }
+ self.fullscreen_enabled = !self.fullscreen_enabled;
- self.apply_layout()?;
- } else {
- self.fullscreen_window = Some(focused);
-
- if let Some(bar) = self.bars.get(self.selected_monitor) {
- self.connection.unmap_window(bar.window())?;
- }
-
- let monitor = &self.monitors[self.selected_monitor];
- let screen_width = monitor.width;
- let screen_height = monitor.height;
-
- self.connection.configure_window(
- focused,
- &ConfigureWindowAux::new()
- .x(monitor.x)
- .y(monitor.y)
- .width(screen_width)
- .height(screen_height)
- .border_width(0)
- .stack_mode(StackMode::ABOVE),
- )?;
-
- self.connection.flush()?;
+ if self.fullscreen_enabled {
+ for bar in &self.bars {
+ self.connection.unmap_window(bar.window())?;
+ }
+ } else {
+ for bar in &self.bars {
+ self.connection.map_window(bar.window())?;
}
}
+
+ self.apply_layout()?;
Ok(())
}
@@ -822,7 +804,7 @@ impl WindowManager {
indicator.push('+');
}
- indicator.push_str(&self.format_keycode(key_press.key));
+ indicator.push_str(&self.format_keysym(key_press.keysym));
}
indicator.push('-');
@@ -841,10 +823,58 @@ impl WindowManager {
}
}
- fn format_keycode(&self, keycode: Keycode) -> String {
- crate::config::KeyData::from_keycode(keycode)
- .unwrap_or("?")
- .to_string()
+ fn format_keysym(&self, keysym: keyboard::keysyms::Keysym) -> String {
+ use keyboard::keysyms::*;
+
+ match keysym {
+ XK_RETURN => "Return",
+ XK_ESCAPE => "Esc",
+ XK_SPACE => "Space",
+ XK_TAB => "Tab",
+ XK_BACKSPACE => "Backspace",
+ XK_DELETE => "Del",
+ XK_F1 => "F1",
+ XK_F2 => "F2",
+ XK_F3 => "F3",
+ XK_F4 => "F4",
+ XK_F5 => "F5",
+ XK_F6 => "F6",
+ XK_F7 => "F7",
+ XK_F8 => "F8",
+ XK_F9 => "F9",
+ XK_F10 => "F10",
+ XK_F11 => "F11",
+ XK_F12 => "F12",
+ XK_A..=XK_Z | XK_0..=XK_9 => {
+ return char::from_u32(keysym).unwrap_or('?').to_string();
+ }
+ XK_LEFT => "Left",
+ XK_RIGHT => "Right",
+ XK_UP => "Up",
+ XK_DOWN => "Down",
+ XK_HOME => "Home",
+ XK_END => "End",
+ XK_PAGE_UP => "PgUp",
+ XK_PAGE_DOWN => "PgDn",
+ XK_INSERT => "Ins",
+ XK_MINUS => "-",
+ XK_EQUAL => "=",
+ XK_LEFT_BRACKET => "[",
+ XK_RIGHT_BRACKET => "]",
+ XK_SEMICOLON => ";",
+ XK_APOSTROPHE => "'",
+ XK_GRAVE => "`",
+ XK_BACKSLASH => "\\",
+ XK_COMMA => ",",
+ XK_PERIOD => ".",
+ XK_SLASH => "/",
+ XF86_AUDIO_RAISE_VOLUME => "Vol+",
+ XF86_AUDIO_LOWER_VOLUME => "Vol-",
+ XF86_AUDIO_MUTE => "Mute",
+ XF86_MON_BRIGHTNESS_UP => "Bri+",
+ XF86_MON_BRIGHTNESS_DOWN => "Bri-",
+ _ => "?",
+ }.to_string()
}
fn update_bar(&mut self) -> WmResult<()> {
@@ -1070,13 +1100,6 @@ impl WindowManager {
return Ok(());
}
- if self.fullscreen_window.is_some() {
- self.fullscreen_window = None;
- for bar in &self.bars {
- self.connection.map_window(bar.window())?;
- }
- }
-
if let Some(monitor) = self.monitors.get_mut(self.selected_monitor) {
monitor.selected_tags = tag_mask(tag_index);
}
@@ -1175,6 +1198,32 @@ impl WindowManager {
}
fn grab_next_keys(&self, candidates: &[usize], keys_pressed: usize) -> WmResult<()> {
+ use std::collections::HashMap;
+ use x11rb::protocol::xproto::Keycode;
+
+ let setup = self.connection.setup();
+ let min_keycode = setup.min_keycode;
+ let max_keycode = setup.max_keycode;
+
+ let keyboard_mapping = self.connection.get_keyboard_mapping(
+ min_keycode,
+ max_keycode - min_keycode + 1,
+ )?.reply()?;
+
+ let mut keysym_to_keycode: HashMap<keyboard::keysyms::Keysym, Vec<Keycode>> = HashMap::new();
+ let keysyms_per_keycode = keyboard_mapping.keysyms_per_keycode;
+
+ for keycode in min_keycode..=max_keycode {
+ let index = (keycode - min_keycode) as usize * keysyms_per_keycode as usize;
+ for i in 0..keysyms_per_keycode as usize {
+ if let Some(&keysym) = keyboard_mapping.keysyms.get(index + i) {
+ if keysym != 0 {
+ keysym_to_keycode.entry(keysym).or_insert_with(Vec::new).push(keycode);
+ }
+ }
+ }
+ }
+
let mut grabbed_keys: HashSet<(u16, Keycode)> = HashSet::new();
for &candidate_index in candidates {
@@ -1182,20 +1231,39 @@ impl WindowManager {
if keys_pressed < binding.keys.len() {
let next_key = &binding.keys[keys_pressed];
let modifier_mask = keyboard::handlers::modifiers_to_mask(&next_key.modifiers);
- let key_tuple = (modifier_mask, next_key.key);
-
- if grabbed_keys.insert(key_tuple) {
- self.connection.grab_key(
- false,
- self.root,
- modifier_mask.into(),
- next_key.key,
- GrabMode::ASYNC,
- GrabMode::ASYNC,
- )?;
+
+ if let Some(keycodes) = keysym_to_keycode.get(&next_key.keysym) {
+ if let Some(&keycode) = keycodes.first() {
+ let key_tuple = (modifier_mask, keycode);
+
+ if grabbed_keys.insert(key_tuple) {
+ self.connection.grab_key(
+ false,
+ self.root,
+ modifier_mask.into(),
+ keycode,
+ GrabMode::ASYNC,
+ GrabMode::ASYNC,
+ )?;
+ }
+ }
}
}
}
+
+ if let Some(keycodes) = keysym_to_keycode.get(&keyboard::keysyms::XK_ESCAPE) {
+ if let Some(&keycode) = keycodes.first() {
+ self.connection.grab_key(
+ false,
+ self.root,
+ ModMask::from(0u16),
+ keycode,
+ GrabMode::ASYNC,
+ GrabMode::ASYNC,
+ )?;
+ }
+ }
+
self.connection.flush()?;
Ok(())
}
@@ -1459,7 +1527,8 @@ impl WindowManager {
event,
&self.config.keybindings,
&self.keychord_state,
- );
+ &self.connection,
+ )?;
match result {
keyboard::handlers::KeychordResult::Completed(action, arg) => {
@@ -1533,17 +1602,13 @@ impl WindowManager {
}
fn apply_layout(&self) -> WmResult<()> {
- if self.fullscreen_window.is_some() {
- return Ok(());
- }
-
if self.layout.name() == LayoutType::Normie.as_str() {
return Ok(());
}
- let border_width = self.config.border_width;
+ let border_width = if self.fullscreen_enabled { 0 } else { self.config.border_width };
- let gaps = if self.gaps_enabled {
+ let gaps = if self.gaps_enabled && !self.fullscreen_enabled {
GapConfig {
inner_horizontal: self.config.gap_inner_horizontal,
inner_vertical: self.config.gap_inner_vertical,
@@ -1580,11 +1645,14 @@ impl WindowManager {
.copied()
.collect();
- let bar_height = self
- .bars
- .get(monitor_index)
- .map(|b| b.height() as u32)
- .unwrap_or(0);
+ let bar_height = if self.fullscreen_enabled {
+ 0
+ } else {
+ self.bars
+ .get(monitor_index)
+ .map(|b| b.height() as u32)
+ .unwrap_or(0)
+ };
let usable_height = monitor.height.saturating_sub(bar_height);
let geometries = self
@@ -1627,13 +1695,6 @@ impl WindowManager {
self.window_geometries.remove(&window);
self.floating_windows.remove(&window);
- if self.fullscreen_window == Some(window) {
- self.fullscreen_window = None;
- for bar in &self.bars {
- self.connection.map_window(bar.window())?;
- }
- }
-
if self.windows.len() < initial_count {
let focused = self
.monitors