Fix keys not being sent to terminal (#35979)
Fixes #35057 Release Notes: - Fix input being sent to editor/terminal when pending keystrokes are resolved
This commit is contained in:
parent
6478e66e7a
commit
12084b6677
2 changed files with 173 additions and 3 deletions
|
@ -611,9 +611,17 @@ impl DispatchTree {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use crate::{
|
||||||
|
self as gpui, Element, ElementId, GlobalElementId, InspectorElementId, LayoutId, Style,
|
||||||
|
};
|
||||||
|
use core::panic;
|
||||||
|
use std::{cell::RefCell, ops::Range, rc::Rc};
|
||||||
|
|
||||||
use crate::{Action, ActionRegistry, DispatchTree, KeyBinding, KeyContext, Keymap};
|
use crate::{
|
||||||
|
Action, ActionRegistry, App, Bounds, Context, DispatchTree, FocusHandle, InputHandler,
|
||||||
|
IntoElement, KeyBinding, KeyContext, Keymap, Pixels, Point, Render, TestAppContext,
|
||||||
|
UTF16Selection, Window,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
struct TestAction;
|
struct TestAction;
|
||||||
|
@ -674,4 +682,165 @@ mod tests {
|
||||||
|
|
||||||
assert!(keybinding[0].action.partial_eq(&TestAction))
|
assert!(keybinding[0].action.partial_eq(&TestAction))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[crate::test]
|
||||||
|
fn test_input_handler_pending(cx: &mut TestAppContext) {
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct CustomElement {
|
||||||
|
focus_handle: FocusHandle,
|
||||||
|
text: Rc<RefCell<String>>,
|
||||||
|
}
|
||||||
|
impl CustomElement {
|
||||||
|
fn new(cx: &mut Context<Self>) -> Self {
|
||||||
|
Self {
|
||||||
|
focus_handle: cx.focus_handle(),
|
||||||
|
text: Rc::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Element for CustomElement {
|
||||||
|
type RequestLayoutState = ();
|
||||||
|
|
||||||
|
type PrepaintState = ();
|
||||||
|
|
||||||
|
fn id(&self) -> Option<ElementId> {
|
||||||
|
Some("custom".into())
|
||||||
|
}
|
||||||
|
fn source_location(&self) -> Option<&'static panic::Location<'static>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn request_layout(
|
||||||
|
&mut self,
|
||||||
|
_: Option<&GlobalElementId>,
|
||||||
|
_: Option<&InspectorElementId>,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut App,
|
||||||
|
) -> (LayoutId, Self::RequestLayoutState) {
|
||||||
|
(window.request_layout(Style::default(), [], cx), ())
|
||||||
|
}
|
||||||
|
fn prepaint(
|
||||||
|
&mut self,
|
||||||
|
_: Option<&GlobalElementId>,
|
||||||
|
_: Option<&InspectorElementId>,
|
||||||
|
_: Bounds<Pixels>,
|
||||||
|
_: &mut Self::RequestLayoutState,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut App,
|
||||||
|
) -> Self::PrepaintState {
|
||||||
|
window.set_focus_handle(&self.focus_handle, cx);
|
||||||
|
}
|
||||||
|
fn paint(
|
||||||
|
&mut self,
|
||||||
|
_: Option<&GlobalElementId>,
|
||||||
|
_: Option<&InspectorElementId>,
|
||||||
|
_: Bounds<Pixels>,
|
||||||
|
_: &mut Self::RequestLayoutState,
|
||||||
|
_: &mut Self::PrepaintState,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut App,
|
||||||
|
) {
|
||||||
|
let mut key_context = KeyContext::default();
|
||||||
|
key_context.add("Terminal");
|
||||||
|
window.set_key_context(key_context);
|
||||||
|
window.handle_input(&self.focus_handle, self.clone(), cx);
|
||||||
|
window.on_action(std::any::TypeId::of::<TestAction>(), |_, _, _, _| {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl IntoElement for CustomElement {
|
||||||
|
type Element = Self;
|
||||||
|
|
||||||
|
fn into_element(self) -> Self::Element {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InputHandler for CustomElement {
|
||||||
|
fn selected_text_range(
|
||||||
|
&mut self,
|
||||||
|
_: bool,
|
||||||
|
_: &mut Window,
|
||||||
|
_: &mut App,
|
||||||
|
) -> Option<UTF16Selection> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn marked_text_range(&mut self, _: &mut Window, _: &mut App) -> Option<Range<usize>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn text_for_range(
|
||||||
|
&mut self,
|
||||||
|
_: Range<usize>,
|
||||||
|
_: &mut Option<Range<usize>>,
|
||||||
|
_: &mut Window,
|
||||||
|
_: &mut App,
|
||||||
|
) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn replace_text_in_range(
|
||||||
|
&mut self,
|
||||||
|
replacement_range: Option<Range<usize>>,
|
||||||
|
text: &str,
|
||||||
|
_: &mut Window,
|
||||||
|
_: &mut App,
|
||||||
|
) {
|
||||||
|
if replacement_range.is_some() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
self.text.borrow_mut().push_str(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn replace_and_mark_text_in_range(
|
||||||
|
&mut self,
|
||||||
|
replacement_range: Option<Range<usize>>,
|
||||||
|
new_text: &str,
|
||||||
|
_: Option<Range<usize>>,
|
||||||
|
_: &mut Window,
|
||||||
|
_: &mut App,
|
||||||
|
) {
|
||||||
|
if replacement_range.is_some() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
self.text.borrow_mut().push_str(new_text)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unmark_text(&mut self, _: &mut Window, _: &mut App) {}
|
||||||
|
|
||||||
|
fn bounds_for_range(
|
||||||
|
&mut self,
|
||||||
|
_: Range<usize>,
|
||||||
|
_: &mut Window,
|
||||||
|
_: &mut App,
|
||||||
|
) -> Option<Bounds<Pixels>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn character_index_for_point(
|
||||||
|
&mut self,
|
||||||
|
_: Point<Pixels>,
|
||||||
|
_: &mut Window,
|
||||||
|
_: &mut App,
|
||||||
|
) -> Option<usize> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Render for CustomElement {
|
||||||
|
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cx.update(|cx| {
|
||||||
|
cx.bind_keys([KeyBinding::new("ctrl-b", TestAction, Some("Terminal"))]);
|
||||||
|
cx.bind_keys([KeyBinding::new("ctrl-b h", TestAction, Some("Terminal"))]);
|
||||||
|
});
|
||||||
|
let (test, cx) = cx.add_window_view(|_, cx| CustomElement::new(cx));
|
||||||
|
cx.update(|window, cx| {
|
||||||
|
window.focus(&test.read(cx).focus_handle);
|
||||||
|
window.activate_window();
|
||||||
|
});
|
||||||
|
cx.simulate_keystrokes("ctrl-b [");
|
||||||
|
test.update(cx, |test, _| assert_eq!(test.text.borrow().as_str(), "["))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3688,7 +3688,8 @@ impl Window {
|
||||||
);
|
);
|
||||||
|
|
||||||
if !match_result.to_replay.is_empty() {
|
if !match_result.to_replay.is_empty() {
|
||||||
self.replay_pending_input(match_result.to_replay, cx)
|
self.replay_pending_input(match_result.to_replay, cx);
|
||||||
|
cx.propagate_event = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !match_result.pending.is_empty() {
|
if !match_result.pending.is_empty() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue