This commit is contained in:
Olie 2024-07-12 06:29:30 +01:00 committed by GitHub
commit 008601a5ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 252 additions and 186 deletions

View File

@ -48,8 +48,8 @@ pub struct Config {
pub environment: Environment, pub environment: Environment,
#[knuffel(children(name = "window-rule"))] #[knuffel(children(name = "window-rule"))]
pub window_rules: Vec<WindowRule>, pub window_rules: Vec<WindowRule>,
#[knuffel(child, default)] #[knuffel(children(name = "binds"))]
pub binds: Binds, pub binds: Vec<Binds>,
#[knuffel(child, default)] #[knuffel(child, default)]
pub debug: DebugConfig, pub debug: DebugConfig,
#[knuffel(children(name = "workspace"))] #[knuffel(children(name = "workspace"))]
@ -906,8 +906,8 @@ pub struct BorderRule {
pub inactive_gradient: Option<Gradient>, pub inactive_gradient: Option<Gradient>,
} }
#[derive(Debug, Default, PartialEq)] #[derive(Debug, Default, PartialEq, Clone)]
pub struct Binds(pub Vec<Bind>); pub struct Binds(pub String, pub Vec<Bind>);
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Bind { pub struct Bind {
@ -1041,6 +1041,7 @@ pub enum Action {
MoveWorkspaceToMonitorRight, MoveWorkspaceToMonitorRight,
MoveWorkspaceToMonitorDown, MoveWorkspaceToMonitorDown,
MoveWorkspaceToMonitorUp, MoveWorkspaceToMonitorUp,
BindingMode(#[knuffel(argument, str)] String),
} }
impl From<niri_ipc::Action> for Action { impl From<niri_ipc::Action> for Action {
@ -2193,7 +2194,11 @@ where
node: &knuffel::ast::SpannedNode<S>, node: &knuffel::ast::SpannedNode<S>,
ctx: &mut knuffel::decode::Context<S>, ctx: &mut knuffel::decode::Context<S>,
) -> Result<Self, DecodeError<S>> { ) -> Result<Self, DecodeError<S>> {
expect_only_children(node, ctx); let mode_name = node
.arguments
.first()
.map(|e| knuffel::DecodeScalar::decode(e, ctx))
.unwrap_or_else(|| Ok(String::from("default")))?;
let mut seen_keys = HashSet::new(); let mut seen_keys = HashSet::new();
@ -2243,7 +2248,7 @@ where
} }
} }
Ok(Self(binds)) Ok(Self(mode_name, binds))
} }
} }
@ -2921,100 +2926,105 @@ mod tests {
open_on_output: None, open_on_output: None,
}, },
], ],
binds: Binds(vec![ binds: vec![Binds(
Bind { "default".to_string(),
key: Key { vec![
trigger: Trigger::Keysym(Keysym::t), Bind {
modifiers: Modifiers::COMPOSITOR, key: Key {
trigger: Trigger::Keysym(Keysym::t),
modifiers: Modifiers::COMPOSITOR,
},
action: Action::Spawn(vec!["alacritty".to_owned()]),
repeat: true,
cooldown: None,
allow_when_locked: true,
}, },
action: Action::Spawn(vec!["alacritty".to_owned()]), Bind {
repeat: true, key: Key {
cooldown: None, trigger: Trigger::Keysym(Keysym::q),
allow_when_locked: true, modifiers: Modifiers::COMPOSITOR,
}, },
Bind { action: Action::CloseWindow,
key: Key { repeat: true,
trigger: Trigger::Keysym(Keysym::q), cooldown: None,
modifiers: Modifiers::COMPOSITOR, allow_when_locked: false,
}, },
action: Action::CloseWindow, Bind {
repeat: true, key: Key {
cooldown: None, trigger: Trigger::Keysym(Keysym::h),
allow_when_locked: false, modifiers: Modifiers::COMPOSITOR | Modifiers::SHIFT,
}, },
Bind { action: Action::FocusMonitorLeft,
key: Key { repeat: true,
trigger: Trigger::Keysym(Keysym::h), cooldown: None,
modifiers: Modifiers::COMPOSITOR | Modifiers::SHIFT, allow_when_locked: false,
}, },
action: Action::FocusMonitorLeft, Bind {
repeat: true, key: Key {
cooldown: None, trigger: Trigger::Keysym(Keysym::l),
allow_when_locked: false, modifiers: Modifiers::COMPOSITOR
}, | Modifiers::SHIFT
Bind { | Modifiers::CTRL,
key: Key { },
trigger: Trigger::Keysym(Keysym::l), action: Action::MoveWindowToMonitorRight,
modifiers: Modifiers::COMPOSITOR | Modifiers::SHIFT | Modifiers::CTRL, repeat: true,
cooldown: None,
allow_when_locked: false,
}, },
action: Action::MoveWindowToMonitorRight, Bind {
repeat: true, key: Key {
cooldown: None, trigger: Trigger::Keysym(Keysym::comma),
allow_when_locked: false, modifiers: Modifiers::COMPOSITOR,
}, },
Bind { action: Action::ConsumeWindowIntoColumn,
key: Key { repeat: true,
trigger: Trigger::Keysym(Keysym::comma), cooldown: None,
modifiers: Modifiers::COMPOSITOR, allow_when_locked: false,
}, },
action: Action::ConsumeWindowIntoColumn, Bind {
repeat: true, key: Key {
cooldown: None, trigger: Trigger::Keysym(Keysym::_1),
allow_when_locked: false, modifiers: Modifiers::COMPOSITOR,
}, },
Bind { action: Action::FocusWorkspace(WorkspaceReference::Index(1)),
key: Key { repeat: true,
trigger: Trigger::Keysym(Keysym::_1), cooldown: None,
modifiers: Modifiers::COMPOSITOR, allow_when_locked: false,
}, },
action: Action::FocusWorkspace(WorkspaceReference::Index(1)), Bind {
repeat: true, key: Key {
cooldown: None, trigger: Trigger::Keysym(Keysym::_1),
allow_when_locked: false, modifiers: Modifiers::COMPOSITOR | Modifiers::SHIFT,
}, },
Bind { action: Action::FocusWorkspace(WorkspaceReference::Name(
key: Key { "workspace-1".to_string(),
trigger: Trigger::Keysym(Keysym::_1), )),
modifiers: Modifiers::COMPOSITOR | Modifiers::SHIFT, repeat: true,
cooldown: None,
allow_when_locked: false,
}, },
action: Action::FocusWorkspace(WorkspaceReference::Name( Bind {
"workspace-1".to_string(), key: Key {
)), trigger: Trigger::Keysym(Keysym::e),
repeat: true, modifiers: Modifiers::COMPOSITOR | Modifiers::SHIFT,
cooldown: None, },
allow_when_locked: false, action: Action::Quit(true),
}, repeat: true,
Bind { cooldown: None,
key: Key { allow_when_locked: false,
trigger: Trigger::Keysym(Keysym::e),
modifiers: Modifiers::COMPOSITOR | Modifiers::SHIFT,
}, },
action: Action::Quit(true), Bind {
repeat: true, key: Key {
cooldown: None, trigger: Trigger::WheelScrollDown,
allow_when_locked: false, modifiers: Modifiers::COMPOSITOR,
}, },
Bind { action: Action::FocusWorkspaceDown,
key: Key { repeat: true,
trigger: Trigger::WheelScrollDown, cooldown: Some(Duration::from_millis(150)),
modifiers: Modifiers::COMPOSITOR, allow_when_locked: false,
}, },
action: Action::FocusWorkspaceDown, ],
repeat: true, )],
cooldown: Some(Duration::from_millis(150)),
allow_when_locked: false,
},
]),
debug: DebugConfig { debug: DebugConfig {
render_drm_device: Some(PathBuf::from("/dev/dri/renderD129")), render_drm_device: Some(PathBuf::from("/dev/dri/renderD129")),
..Default::default() ..Default::default()
@ -3109,4 +3119,20 @@ mod tests {
assert_eq!(config.input.keyboard.repeat_delay, 600); assert_eq!(config.input.keyboard.repeat_delay, 600);
assert_eq!(config.input.keyboard.repeat_rate, 25); assert_eq!(config.input.keyboard.repeat_rate, 25);
} }
#[test]
fn binding_modes() {
Config::parse(
"",
r##"
binds {
A { binding-mode "test"; }
}
binds "test" {
B { binding-mode "default"; }
}
"##,
)
.unwrap();
}
} }

View File

@ -38,6 +38,8 @@ pub enum Request {
FocusedOutput, FocusedOutput,
/// Respond with an error (for testing error handling). /// Respond with an error (for testing error handling).
ReturnError, ReturnError,
/// Request name of the current binding mode.
BindingMode,
} }
/// Reply from niri to client. /// Reply from niri to client.
@ -70,6 +72,8 @@ pub enum Response {
Workspaces(Vec<Workspace>), Workspaces(Vec<Workspace>),
/// Information about the focused output. /// Information about the focused output.
FocusedOutput(Option<Output>), FocusedOutput(Option<Output>),
/// Name of the current binding mode.
BindingMode(String),
} }
/// Actions that niri can perform. /// Actions that niri can perform.

View File

@ -90,4 +90,6 @@ pub enum Msg {
Version, Version,
/// Request an error from the running niri instance. /// Request an error from the running niri instance.
RequestError, RequestError,
/// Get the binding mode name.
BindingMode,
} }

View File

@ -314,7 +314,7 @@ impl State {
serial, serial,
time, time,
|this, mods, keysym| { |this, mods, keysym| {
let bindings = &this.niri.config.borrow().binds; let bindings = &this.niri.binding_mode;
let key_code = event.key_code(); let key_code = event.key_code();
let modified = keysym.modified_sym(); let modified = keysym.modified_sym();
let raw = keysym.raw_latin_sym_or_raw_current_sym(); let raw = keysym.raw_latin_sym_or_raw_current_sym();
@ -1077,6 +1077,11 @@ impl State {
} }
} }
} }
Action::BindingMode(name) => {
if let Some(mode) = self.niri.config.borrow().binds.iter().find(|e| e.0 == name) {
self.niri.binding_mode = mode.clone();
}
}
} }
} }
@ -1500,13 +1505,11 @@ impl State {
let horizontal = horizontal_amount_v120.unwrap_or(0.); let horizontal = horizontal_amount_v120.unwrap_or(0.);
let ticks = self.niri.horizontal_wheel_tracker.accumulate(horizontal); let ticks = self.niri.horizontal_wheel_tracker.accumulate(horizontal);
if ticks != 0 { if ticks != 0 {
let config = self.niri.config.borrow(); let bindings = &self.niri.binding_mode;
let bindings = &config.binds;
let bind_left = let bind_left =
find_configured_bind(bindings, comp_mod, Trigger::WheelScrollLeft, mods); find_configured_bind(bindings, comp_mod, Trigger::WheelScrollLeft, mods);
let bind_right = let bind_right =
find_configured_bind(bindings, comp_mod, Trigger::WheelScrollRight, mods); find_configured_bind(bindings, comp_mod, Trigger::WheelScrollRight, mods);
drop(config);
if let Some(right) = bind_right { if let Some(right) = bind_right {
for _ in 0..ticks { for _ in 0..ticks {
@ -1523,13 +1526,11 @@ impl State {
let vertical = vertical_amount_v120.unwrap_or(0.); let vertical = vertical_amount_v120.unwrap_or(0.);
let ticks = self.niri.vertical_wheel_tracker.accumulate(vertical); let ticks = self.niri.vertical_wheel_tracker.accumulate(vertical);
if ticks != 0 { if ticks != 0 {
let config = self.niri.config.borrow(); let bindings = &self.niri.binding_mode;
let bindings = &config.binds;
let bind_up = let bind_up =
find_configured_bind(bindings, comp_mod, Trigger::WheelScrollUp, mods); find_configured_bind(bindings, comp_mod, Trigger::WheelScrollUp, mods);
let bind_down = let bind_down =
find_configured_bind(bindings, comp_mod, Trigger::WheelScrollDown, mods); find_configured_bind(bindings, comp_mod, Trigger::WheelScrollDown, mods);
drop(config);
if let Some(down) = bind_down { if let Some(down) = bind_down {
for _ in 0..ticks { for _ in 0..ticks {
@ -1566,8 +1567,7 @@ impl State {
.horizontal_finger_scroll_tracker .horizontal_finger_scroll_tracker
.accumulate(horizontal); .accumulate(horizontal);
if ticks != 0 { if ticks != 0 {
let config = self.niri.config.borrow(); let bindings = &self.niri.binding_mode;
let bindings = &config.binds;
let bind_left = let bind_left =
find_configured_bind(bindings, comp_mod, Trigger::TouchpadScrollLeft, mods); find_configured_bind(bindings, comp_mod, Trigger::TouchpadScrollLeft, mods);
let bind_right = find_configured_bind( let bind_right = find_configured_bind(
@ -1576,7 +1576,6 @@ impl State {
Trigger::TouchpadScrollRight, Trigger::TouchpadScrollRight,
mods, mods,
); );
drop(config);
if let Some(right) = bind_right { if let Some(right) = bind_right {
for _ in 0..ticks { for _ in 0..ticks {
@ -1596,13 +1595,11 @@ impl State {
.vertical_finger_scroll_tracker .vertical_finger_scroll_tracker
.accumulate(vertical); .accumulate(vertical);
if ticks != 0 { if ticks != 0 {
let config = self.niri.config.borrow(); let bindings = &self.niri.binding_mode;
let bindings = &config.binds;
let bind_up = let bind_up =
find_configured_bind(bindings, comp_mod, Trigger::TouchpadScrollUp, mods); find_configured_bind(bindings, comp_mod, Trigger::TouchpadScrollUp, mods);
let bind_down = let bind_down =
find_configured_bind(bindings, comp_mod, Trigger::TouchpadScrollDown, mods); find_configured_bind(bindings, comp_mod, Trigger::TouchpadScrollDown, mods);
drop(config);
if let Some(down) = bind_down { if let Some(down) = bind_down {
for _ in 0..ticks { for _ in 0..ticks {
@ -2290,7 +2287,7 @@ fn find_configured_bind(
modifiers |= Modifiers::COMPOSITOR; modifiers |= Modifiers::COMPOSITOR;
} }
for bind in &bindings.0 { for bind in &bindings.1 {
if bind.key.trigger != trigger { if bind.key.trigger != trigger {
continue; continue;
} }
@ -2539,7 +2536,7 @@ pub fn mods_with_binds(
}; };
let mut rv = HashSet::new(); let mut rv = HashSet::new();
for bind in &binds.0 { for bind in &binds.1 {
if !triggers.iter().any(|trigger| bind.key.trigger == *trigger) { if !triggers.iter().any(|trigger| bind.key.trigger == *trigger) {
continue; continue;
} }
@ -2589,16 +2586,19 @@ mod tests {
#[test] #[test]
fn bindings_suppress_keys() { fn bindings_suppress_keys() {
let close_keysym = Keysym::q; let close_keysym = Keysym::q;
let bindings = Binds(vec![Bind { let bindings = Binds(
key: Key { String::from("default"),
trigger: Trigger::Keysym(close_keysym), vec![Bind {
modifiers: Modifiers::COMPOSITOR | Modifiers::CTRL, key: Key {
}, trigger: Trigger::Keysym(close_keysym),
action: Action::CloseWindow, modifiers: Modifiers::COMPOSITOR | Modifiers::CTRL,
repeat: true, },
cooldown: None, action: Action::CloseWindow,
allow_when_locked: false, repeat: true,
}]); cooldown: None,
allow_when_locked: false,
}],
);
let comp_mod = CompositorMod::Super; let comp_mod = CompositorMod::Super;
let mut suppressed_keys = HashSet::new(); let mut suppressed_keys = HashSet::new();
@ -2722,58 +2722,61 @@ mod tests {
#[test] #[test]
fn comp_mod_handling() { fn comp_mod_handling() {
let bindings = Binds(vec![ let bindings = Binds(
Bind { String::from("default"),
key: Key { vec![
trigger: Trigger::Keysym(Keysym::q), Bind {
modifiers: Modifiers::COMPOSITOR, key: Key {
trigger: Trigger::Keysym(Keysym::q),
modifiers: Modifiers::COMPOSITOR,
},
action: Action::CloseWindow,
repeat: true,
cooldown: None,
allow_when_locked: false,
}, },
action: Action::CloseWindow, Bind {
repeat: true, key: Key {
cooldown: None, trigger: Trigger::Keysym(Keysym::h),
allow_when_locked: false, modifiers: Modifiers::SUPER,
}, },
Bind { action: Action::FocusColumnLeft,
key: Key { repeat: true,
trigger: Trigger::Keysym(Keysym::h), cooldown: None,
modifiers: Modifiers::SUPER, allow_when_locked: false,
}, },
action: Action::FocusColumnLeft, Bind {
repeat: true, key: Key {
cooldown: None, trigger: Trigger::Keysym(Keysym::j),
allow_when_locked: false, modifiers: Modifiers::empty(),
}, },
Bind { action: Action::FocusWindowDown,
key: Key { repeat: true,
trigger: Trigger::Keysym(Keysym::j), cooldown: None,
modifiers: Modifiers::empty(), allow_when_locked: false,
}, },
action: Action::FocusWindowDown, Bind {
repeat: true, key: Key {
cooldown: None, trigger: Trigger::Keysym(Keysym::k),
allow_when_locked: false, modifiers: Modifiers::COMPOSITOR | Modifiers::SUPER,
}, },
Bind { action: Action::FocusWindowUp,
key: Key { repeat: true,
trigger: Trigger::Keysym(Keysym::k), cooldown: None,
modifiers: Modifiers::COMPOSITOR | Modifiers::SUPER, allow_when_locked: false,
}, },
action: Action::FocusWindowUp, Bind {
repeat: true, key: Key {
cooldown: None, trigger: Trigger::Keysym(Keysym::l),
allow_when_locked: false, modifiers: Modifiers::SUPER | Modifiers::ALT,
}, },
Bind { action: Action::FocusColumnRight,
key: Key { repeat: true,
trigger: Trigger::Keysym(Keysym::l), cooldown: None,
modifiers: Modifiers::SUPER | Modifiers::ALT, allow_when_locked: false,
}, },
action: Action::FocusColumnRight, ],
repeat: true, );
cooldown: None,
allow_when_locked: false,
},
]);
assert_eq!( assert_eq!(
find_configured_bind( find_configured_bind(
@ -2786,7 +2789,7 @@ mod tests {
} }
) )
.as_ref(), .as_ref(),
Some(&bindings.0[0]) Some(&bindings.1[0])
); );
assert_eq!( assert_eq!(
find_configured_bind( find_configured_bind(
@ -2809,7 +2812,7 @@ mod tests {
} }
) )
.as_ref(), .as_ref(),
Some(&bindings.0[1]) Some(&bindings.1[1])
); );
assert_eq!( assert_eq!(
find_configured_bind( find_configured_bind(
@ -2841,7 +2844,7 @@ mod tests {
ModifiersState::default(), ModifiersState::default(),
) )
.as_ref(), .as_ref(),
Some(&bindings.0[2]) Some(&bindings.1[2])
); );
assert_eq!( assert_eq!(
@ -2855,7 +2858,7 @@ mod tests {
} }
) )
.as_ref(), .as_ref(),
Some(&bindings.0[3]) Some(&bindings.1[3])
); );
assert_eq!( assert_eq!(
find_configured_bind( find_configured_bind(
@ -2879,7 +2882,7 @@ mod tests {
} }
) )
.as_ref(), .as_ref(),
Some(&bindings.0[4]) Some(&bindings.1[4])
); );
assert_eq!( assert_eq!(
find_configured_bind( find_configured_bind(

View File

@ -20,6 +20,7 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
}, },
Msg::Workspaces => Request::Workspaces, Msg::Workspaces => Request::Workspaces,
Msg::RequestError => Request::ReturnError, Msg::RequestError => Request::ReturnError,
Msg::BindingMode => Request::BindingMode,
}; };
let socket = Socket::connect().context("error connecting to the niri socket")?; let socket = Socket::connect().context("error connecting to the niri socket")?;
@ -238,6 +239,19 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
println!("{is_active}{idx}{name}"); println!("{is_active}{idx}{name}");
} }
} }
Msg::BindingMode => {
let Response::BindingMode(response) = response else {
bail!("unexpected response: expected BindingMode, got {response:?}");
};
if json {
let response =
serde_json::to_string(&response).context("error formatting response")?;
println!("{response}");
return Ok(());
}
println!("{response}");
}
} }
Ok(()) Ok(())

View File

@ -235,6 +235,16 @@ async fn process(ctx: &ClientCtx, request: Request) -> Reply {
let output = result.map_err(|_| String::from("error getting active output info"))?; let output = result.map_err(|_| String::from("error getting active output info"))?;
Response::FocusedOutput(output) Response::FocusedOutput(output)
} }
Request::BindingMode => {
let (tx, rx) = async_channel::bounded(1);
ctx.event_loop.insert_idle(move |state| {
let workspaces = state.niri.binding_mode.0.clone();
let _ = tx.send_blocking(workspaces);
});
let result = rx.recv().await;
let mode = result.map_err(|_| String::from("error getting workspace info"))?;
Response::BindingMode(mode.clone())
}
}; };
Ok(response) Ok(response)

View File

@ -152,6 +152,8 @@ const FRAME_CALLBACK_THROTTLE: Option<Duration> = Some(Duration::from_millis(995
pub struct Niri { pub struct Niri {
pub config: Rc<RefCell<Config>>, pub config: Rc<RefCell<Config>>,
pub binding_mode: niri_config::Binds,
/// Output config from the config file. /// Output config from the config file.
/// ///
/// This does not include transient output config changes done via IPC. It is only used when /// This does not include transient output config changes done via IPC. It is only used when
@ -992,9 +994,9 @@ impl State {
if config.binds != old_config.binds { if config.binds != old_config.binds {
self.niri.hotkey_overlay.on_hotkey_config_updated(); self.niri.hotkey_overlay.on_hotkey_config_updated();
self.niri.mods_with_wheel_binds = self.niri.mods_with_wheel_binds =
mods_with_wheel_binds(self.backend.mod_key(), &config.binds); mods_with_wheel_binds(self.backend.mod_key(), &self.niri.binding_mode);
self.niri.mods_with_finger_scroll_binds = self.niri.mods_with_finger_scroll_binds =
mods_with_finger_scroll_binds(self.backend.mod_key(), &config.binds); mods_with_finger_scroll_binds(self.backend.mod_key(), &self.niri.binding_mode);
} }
if config.window_rules != old_config.window_rules { if config.window_rules != old_config.window_rules {
@ -1477,6 +1479,13 @@ impl Niri {
let config_ = config.borrow(); let config_ = config.borrow();
let config_file_output_config = config_.outputs.clone(); let config_file_output_config = config_.outputs.clone();
let binding_mode = config_
.binds
.iter()
.find(|e| e.0 == "default")
.cloned()
.unwrap_or_else(|| niri_config::Binds(String::from("default"), vec![]));
let layout = Layout::new(&config_); let layout = Layout::new(&config_);
let compositor_state = CompositorState::new_v6::<State>(&display_handle); let compositor_state = CompositorState::new_v6::<State>(&display_handle);
@ -1585,14 +1594,14 @@ impl Niri {
let cursor_manager = let cursor_manager =
CursorManager::new(&config_.cursor.xcursor_theme, config_.cursor.xcursor_size); CursorManager::new(&config_.cursor.xcursor_theme, config_.cursor.xcursor_size);
let mods_with_wheel_binds = mods_with_wheel_binds(backend.mod_key(), &config_.binds); let mods_with_wheel_binds = mods_with_wheel_binds(backend.mod_key(), &binding_mode);
let mods_with_finger_scroll_binds = let mods_with_finger_scroll_binds =
mods_with_finger_scroll_binds(backend.mod_key(), &config_.binds); mods_with_finger_scroll_binds(backend.mod_key(), &binding_mode);
let screenshot_ui = ScreenshotUi::new(config.clone()); let screenshot_ui = ScreenshotUi::new(config.clone());
let config_error_notification = ConfigErrorNotification::new(config.clone()); let config_error_notification = ConfigErrorNotification::new(config.clone());
let mut hotkey_overlay = HotkeyOverlay::new(config.clone(), backend.mod_key()); let mut hotkey_overlay = HotkeyOverlay::new(backend.mod_key());
if !config_.hotkey_overlay.skip_at_startup { if !config_.hotkey_overlay.skip_at_startup {
hotkey_overlay.show(); hotkey_overlay.show();
} }
@ -1674,6 +1683,7 @@ impl Niri {
drop(config_); drop(config_);
Self { Self {
config, config,
binding_mode,
config_file_output_config, config_file_output_config,
event_loop, event_loop,
@ -2880,7 +2890,10 @@ impl Niri {
} }
// Draw the hotkey overlay on top. // Draw the hotkey overlay on top.
if let Some(element) = self.hotkey_overlay.render(renderer, output) { if let Some(element) = self
.hotkey_overlay
.render(renderer, output, &self.binding_mode.1)
{
elements.push(element.into()); elements.push(element.into());
} }

View File

@ -2,9 +2,8 @@ use std::cell::RefCell;
use std::cmp::max; use std::cmp::max;
use std::collections::HashMap; use std::collections::HashMap;
use std::iter::zip; use std::iter::zip;
use std::rc::Rc;
use niri_config::{Action, Config, Key, Modifiers, Trigger}; use niri_config::{Action, Bind, Key, Modifiers, Trigger};
use pangocairo::cairo::{self, ImageSurface}; use pangocairo::cairo::{self, ImageSurface};
use pangocairo::pango::{AttrColor, AttrInt, AttrList, AttrString, FontDescription, Weight}; use pangocairo::pango::{AttrColor, AttrInt, AttrList, AttrString, FontDescription, Weight};
use smithay::backend::renderer::element::Kind; use smithay::backend::renderer::element::Kind;
@ -29,7 +28,6 @@ const TITLE: &str = "Important Hotkeys";
pub struct HotkeyOverlay { pub struct HotkeyOverlay {
is_open: bool, is_open: bool,
config: Rc<RefCell<Config>>,
comp_mod: CompositorMod, comp_mod: CompositorMod,
buffers: RefCell<HashMap<WeakOutput, RenderedOverlay>>, buffers: RefCell<HashMap<WeakOutput, RenderedOverlay>>,
} }
@ -39,10 +37,9 @@ pub struct RenderedOverlay {
} }
impl HotkeyOverlay { impl HotkeyOverlay {
pub fn new(config: Rc<RefCell<Config>>, comp_mod: CompositorMod) -> Self { pub fn new(comp_mod: CompositorMod) -> Self {
Self { Self {
is_open: false, is_open: false,
config,
comp_mod, comp_mod,
buffers: RefCell::new(HashMap::new()), buffers: RefCell::new(HashMap::new()),
} }
@ -78,6 +75,7 @@ impl HotkeyOverlay {
&self, &self,
renderer: &mut R, renderer: &mut R,
output: &Output, output: &Output,
binds: &[Bind],
) -> Option<PrimaryGpuTextureRenderElement> { ) -> Option<PrimaryGpuTextureRenderElement> {
if !self.is_open { if !self.is_open {
return None; return None;
@ -101,7 +99,7 @@ impl HotkeyOverlay {
let rendered = buffers.entry(weak).or_insert_with(|| { let rendered = buffers.entry(weak).or_insert_with(|| {
let renderer = renderer.as_gles_renderer(); let renderer = renderer.as_gles_renderer();
render(renderer, &self.config.borrow(), self.comp_mod, scale) render(renderer, binds, self.comp_mod, scale)
.unwrap_or_else(|_| RenderedOverlay { buffer: None }) .unwrap_or_else(|_| RenderedOverlay { buffer: None })
}); });
let buffer = rendered.buffer.as_ref()?; let buffer = rendered.buffer.as_ref()?;
@ -127,7 +125,7 @@ impl HotkeyOverlay {
fn render( fn render(
renderer: &mut GlesRenderer, renderer: &mut GlesRenderer,
config: &Config, binds: &[niri_config::Bind],
comp_mod: CompositorMod, comp_mod: CompositorMod,
scale: f64, scale: f64,
) -> anyhow::Result<RenderedOverlay> { ) -> anyhow::Result<RenderedOverlay> {
@ -143,8 +141,6 @@ fn render(
// target_size.h -= margin * 2; // target_size.h -= margin * 2;
// anyhow::ensure!(target_size.w > 0 && target_size.h > 0); // anyhow::ensure!(target_size.w > 0 && target_size.h > 0);
let binds = &config.binds.0;
// Collect actions that we want to show. // Collect actions that we want to show.
let mut actions = vec![&Action::ShowHotkeyOverlay]; let mut actions = vec![&Action::ShowHotkeyOverlay];
@ -232,9 +228,7 @@ fn render(
let strings = actions let strings = actions
.into_iter() .into_iter()
.map(|action| { .map(|action| {
let key = config let key = binds
.binds
.0
.iter() .iter()
.find(|bind| bind.action == *action) .find(|bind| bind.action == *action)
.map(|bind| key_name(comp_mod, &bind.key)) .map(|bind| key_name(comp_mod, &bind.key))