1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-22 22:42:48 +03:00

add window:keyboard_modifiers() method

This commit is contained in:
Wez Furlong 2023-04-16 19:41:59 -07:00
parent 572c31fb30
commit 075388fbe5
No known key found for this signature in database
GPG Key ID: 7A7F66A31EC9B387
9 changed files with 111 additions and 1 deletions

View File

@ -21,6 +21,10 @@ usually the best available version.
As features stabilize some brief notes about them will accumulate here.
#### New
* [window:keyboard_modifiers](config/lua/window/keyboard_modifiers.md) #3444
#### Fixed
* Modals, such as `CharSelect` and `CommandPalette` did not respect alternative

View File

@ -0,0 +1,30 @@
# window:keyboard_modifiers()
{{since('nightly')}}
Returns two values; the keyboard modifiers and the key status leds.
Both values are exposed to lua as strings with `|`-delimited values
representing the various modifier keys and keyboard led states:
* Modifiers - is the same form as keyboard assignment modifiers
* Leds - possible flags are `"CAPS_LOCK"` and `"NUM_LOCK"`. Note that macOS
doesn't have a num lock concept.
This example shows the current modifier and led status in the right status
area:
```lua
local wezterm = require 'wezterm'
local config = wezterm.config_builder()
config.debug_key_events = true
wezterm.on('update-status', function(window, pane)
local mods, leds = window:keyboard_modifiers()
window:set_right_status('mods=' .. mods .. ' leds=' .. leds)
end)
return config
```

View File

@ -257,6 +257,21 @@ impl UserData for GuiWin {
Ok(result)
});
methods.add_async_method("keyboard_modifiers", |_, this, _: ()| async move {
let (tx, rx) = smol::channel::bounded(1);
this.window
.notify(TermWindowNotif::Apply(Box::new(move |term_window| {
tx.try_send(term_window.current_modifier_and_led_state())
.ok();
})));
let (mods, leds) = rx
.recv()
.await
.map_err(|e| anyhow::anyhow!("{:#}", e))
.map_err(luaerr)?;
Ok((mods.to_string(), leds.to_string()))
});
methods.add_async_method("active_pane", |_, this, _: ()| async move {
let (tx, rx) = smol::channel::bounded(1);
this.window

View File

@ -1,5 +1,7 @@
use crate::termwindow::InputMap;
use ::window::{DeadKeyStatus, KeyCode, KeyEvent, Modifiers, RawKeyEvent, WindowOps};
use ::window::{
DeadKeyStatus, KeyCode, KeyEvent, KeyboardLedStatus, Modifiers, RawKeyEvent, WindowOps,
};
use anyhow::Context;
use config::keyassignment::{KeyAssignment, KeyTableEntry};
use mux::pane::{Pane, PerformAssignmentResult};
@ -448,6 +450,12 @@ impl super::TermWindow {
);
}
let modifier_and_leds = (key.modifiers, key.leds);
if self.current_modifier_and_leds != modifier_and_leds {
self.current_modifier_and_leds = modifier_and_leds;
self.schedule_next_status_update();
}
let pane = match self.get_active_pane_or_overlay() {
Some(pane) => pane,
None => return,
@ -517,6 +525,10 @@ impl super::TermWindow {
}
}
pub fn current_modifier_and_led_state(&self) -> (Modifiers, KeyboardLedStatus) {
self.current_modifier_and_leds
}
pub fn leader_is_active(&self) -> bool {
match self.leader_is_down.as_ref() {
Some(expiry) if *expiry > std::time::Instant::now() => {

View File

@ -395,6 +395,7 @@ pub struct TermWindow {
window_background: Vec<LoadedBackgroundLayer>,
current_modifier_and_leds: (Modifiers, KeyboardLedStatus),
current_mouse_buttons: Vec<MousePress>,
current_mouse_capture: Option<MouseCapture>,
@ -694,6 +695,7 @@ impl TermWindow {
last_mouse_coords: (0, -1),
window_drag_position: None,
current_mouse_event: None,
current_modifier_and_leds: Default::default(),
prev_cursor: PrevCursorPos::new(),
last_scroll_info: RenderableDimensions::default(),
tab_state: RefCell::new(HashMap::new()),
@ -925,6 +927,12 @@ impl TermWindow {
self.resize(dimensions, window_state, window, live_resizing);
Ok(true)
}
WindowEvent::AdviseModifiersLedStatus(modifiers, leds) => {
self.current_modifier_and_leds = (modifiers, leds);
self.update_title();
window.invalidate();
Ok(true)
}
WindowEvent::RawKeyEvent(event) => {
self.raw_key_event_impl(event, window);
Ok(true)

View File

@ -459,6 +459,22 @@ bitflags! {
}
}
impl ToString for KeyboardLedStatus {
fn to_string(&self) -> String {
let mut s = String::new();
if self.contains(Self::CAPS_LOCK) {
s.push_str("CAPS_LOCK");
}
if self.contains(Self::NUM_LOCK) {
if !s.is_empty() {
s.push('|');
}
s.push_str("NUM_LOCK");
}
s
}
}
bitflags! {
#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
#[derive(Default, FromDynamic, ToDynamic)]

View File

@ -80,6 +80,7 @@ impl MyWindow {
}
WindowEvent::AppearanceChanged(_)
| WindowEvent::AdviseDeadKeyStatus(_)
| WindowEvent::AdviseModifiersLedStatus(_, _)
| WindowEvent::Notification(_)
| WindowEvent::FocusChanged(_)
| WindowEvent::DraggedFile(_)

View File

@ -189,6 +189,8 @@ pub enum WindowEvent {
/// Called by menubar dispatching stuff on some systems
PerformKeyAssignment(config::keyassignment::KeyAssignment),
AdviseModifiersLedStatus(Modifiers, KeyboardLedStatus),
}
pub struct WindowEventSender {

View File

@ -2657,6 +2657,23 @@ impl WindowView {
}
}
extern "C" fn flags_changed(this: &mut Object, _sel: Sel, nsevent: id) {
let modifier_flags = unsafe { nsevent.modifierFlags() };
let modifiers = key_modifiers(modifier_flags);
let leds = if modifier_flags.bits() & (1 << 16) != 0 {
KeyboardLedStatus::CAPS_LOCK
} else {
KeyboardLedStatus::empty()
};
if let Some(myself) = Self::get_this(this) {
let mut inner = myself.inner.borrow_mut();
inner
.events
.dispatch(WindowEvent::AdviseModifiersLedStatus(modifiers, leds));
}
}
extern "C" fn key_down(this: &mut Object, _sel: Sel, nsevent: id) {
Self::key_common(this, nsevent, true);
}
@ -3101,6 +3118,11 @@ impl WindowView {
Self::update_tracking_areas as extern "C" fn(&mut Object, Sel),
);
cls.add_method(
sel!(flagsChanged:),
Self::flags_changed as extern "C" fn(&mut Object, Sel, id),
);
// NSTextInputClient
cls.add_method(