input: dispatch editing keys through actions

This commit is contained in:
2026-10-29 15:27:56 +07:00
parent e2331f2ba5
commit 5f53e0c89f
6 changed files with 656 additions and 184 deletions
+41 -4
View File
@@ -1,8 +1,10 @@
use gpui::{
Entity, Modifiers, MouseButton, MouseDownEvent, MouseUpEvent, ParentElement as _, Render,
Styled as _, TestAppContext, VisualTestContext, Window, div, point, px,
Entity, KeyBinding, Modifiers, MouseButton, MouseDownEvent, MouseUpEvent, ParentElement as _,
Render, Styled as _, TestAppContext, VisualTestContext, Window, div, point, px,
};
use gpui_native_core::input::{
INPUT_CONTEXT, Input, InputBindings, InputState, InputStateEvent, Submit, bind_input_keys,
};
use gpui_native_core::input::{Input, InputState, InputStateEvent};
use gpui_native_theme::Theme;
use std::cell::RefCell;
use std::rc::Rc;
@@ -30,9 +32,20 @@ impl Render for Harness {
fn input_window(
initial: &str,
disabled: bool,
) -> (TestAppContext, Entity<InputState>, VisualTestContext) {
input_window_with_bindings(initial, disabled, InputBindings::default())
}
fn input_window_with_bindings(
initial: &str,
disabled: bool,
bindings: InputBindings,
) -> (TestAppContext, Entity<InputState>, VisualTestContext) {
let mut cx = TestAppContext::single();
cx.update(Theme::init);
cx.update(|cx| {
Theme::init(cx);
bind_input_keys(cx, bindings);
});
let state = cx.update(|cx| InputState::new_with_text(initial, cx));
let state_for_window = state.clone();
let window = cx.add_window(move |_, _| Harness {
@@ -293,6 +306,30 @@ fn escape_blurs_the_field() {
assert_eq!(count(&sink, &InputStateEvent::Blurred), 1);
}
#[test]
fn custom_bindings_replace_and_unbind_keys() {
// Only submit is bound, and on a custom key.
let mut bindings = InputBindings::empty();
bindings.submit = Some(KeyBinding::new("cmd-enter", Submit, Some(INPUT_CONTEXT)));
let (mut cx, state, mut visual) = input_window_with_bindings("", false, bindings);
let (sink, _subscription) = record_events(&mut cx, &state);
focus(&mut visual, &state);
// The default enter binding is gone.
visual.simulate_keystrokes("enter");
assert_eq!(count(&sink, &InputStateEvent::Submitted), 0);
// The override fires.
visual.simulate_keystrokes("cmd-enter");
assert_eq!(count(&sink, &InputStateEvent::Submitted), 1);
// Unbound actions do nothing; unbound characters still type.
visual.simulate_keystrokes("cmd-z");
assert_eq!(value(&cx, &state), "");
visual.simulate_keystrokes("a");
assert_eq!(value(&cx, &state), "a");
}
#[test]
fn triple_click_selects_all_and_typing_replaces_it() {
let (cx, state, mut visual) = input_window("hello world", false);