Fix keybind hints flickering in certain scenarios (#40927)

Closes #39172

This refactors when we resolve UI keybindings in an effort to reduce
flickering whilst painting these: Previously, we would always resolve
these upon creating the binding. This could lead to cases where the
corresponding context was not yet available and no binding could be
resolved, even if the binding was then available on the next presented
frame. Following that, on the next rerender of whatever requested this
keybinding, the keybind for that context would then be found, we would
render that and then also win a layout shift in that process, as we went
from nothing rendered to something rendered between these frames.

With these changes, this now happens less often, because we only look
for the keybinding once the context can actually be resolved in the
window.

| Before | After | 
| --- | --- |
|
https://github.com/user-attachments/assets/adebf8ac-217d-4c7f-ae5a-bab3aa0b0ee8
|
https://github.com/user-attachments/assets/70a82b4b-488f-4a9f-94d7-b6d0a49aada9
|

Also reduced cloning in the keymap editor in this process, since that
requiered changing due to this anyway.

Release Notes:

- Fixed some cases where keybinds would appear with a slight delay,
causing a flicker in the process
This commit is contained in:
Finn Evers
2025-10-22 19:52:38 +00:00
committed by GitHub
parent ed5b9a4705
commit f393138711
80 changed files with 662 additions and 975 deletions
+16 -23
View File
@@ -834,9 +834,9 @@ impl ContextMenu {
.disabled(true)
.child(Label::new(label.clone()))
.into_any_element(),
ContextMenuItem::Entry(entry) => self
.render_menu_entry(ix, entry, window, cx)
.into_any_element(),
ContextMenuItem::Entry(entry) => {
self.render_menu_entry(ix, entry, cx).into_any_element()
}
ContextMenuItem::CustomEntry {
entry_render,
handler,
@@ -883,7 +883,6 @@ impl ContextMenu {
&self,
ix: usize,
entry: &ContextMenuEntry,
window: &mut Window,
cx: &mut Context<Self>,
) -> impl IntoElement {
let ContextMenuEntry {
@@ -980,18 +979,18 @@ impl ContextMenu {
.justify_between()
.child(label_element)
.debug_selector(|| format!("MENU_ITEM-{}", label))
.children(action.as_ref().and_then(|action| {
self.action_context
.children(action.as_ref().map(|action| {
let binding = self
.action_context
.as_ref()
.and_then(|focus| {
KeyBinding::for_action_in(&**action, focus, window, cx)
})
.or_else(|| KeyBinding::for_action(&**action, window, cx))
.map(|binding| {
div().ml_4().child(binding.disabled(*disabled)).when(
*disabled && documentation_aside.is_some(),
|parent| parent.invisible(),
)
.map(|focus| KeyBinding::for_action_in(&**action, focus, cx))
.unwrap_or_else(|| KeyBinding::for_action(&**action, cx));
div()
.ml_4()
.child(binding.disabled(*disabled))
.when(*disabled && documentation_aside.is_some(), |parent| {
parent.invisible()
})
}))
.when(*disabled && documentation_aside.is_some(), |parent| {
@@ -1016,7 +1015,7 @@ impl ContextMenu {
let action_context = self.action_context.clone();
let title = title.clone();
let action = action.boxed_clone();
move |window, cx| {
move |_window, cx| {
action_context
.as_ref()
.map(|focus| {
@@ -1024,17 +1023,11 @@ impl ContextMenu {
title.clone(),
&*action,
focus,
window,
cx,
)
})
.unwrap_or_else(|| {
Tooltip::for_action(
title.clone(),
&*action,
window,
cx,
)
Tooltip::for_action(title.clone(), &*action, cx)
})
}
})
+177 -137
View File
@@ -1,3 +1,5 @@
use std::rc::Rc;
use crate::PlatformStyle;
use crate::{Icon, IconName, IconSize, h_flex, prelude::*};
use gpui::{
@@ -5,23 +7,49 @@ use gpui::{
Modifiers, Window, relative,
};
use itertools::Itertools;
use settings::KeybindSource;
#[derive(Debug, IntoElement, Clone, RegisterComponent)]
#[derive(Debug)]
enum Source {
Action {
action: Box<dyn Action>,
focus_handle: Option<FocusHandle>,
},
Keystrokes {
/// A keybinding consists of a set of keystrokes,
/// where each keystroke is a key and a set of modifier keys.
/// More than one keystroke produces a chord.
///
/// This should always contain at least one keystroke.
keystrokes: Rc<[KeybindingKeystroke]>,
},
}
impl Clone for Source {
fn clone(&self) -> Self {
match self {
Source::Action {
action,
focus_handle,
} => Source::Action {
action: action.boxed_clone(),
focus_handle: focus_handle.clone(),
},
Source::Keystrokes { keystrokes } => Source::Keystrokes {
keystrokes: keystrokes.clone(),
},
}
}
}
#[derive(Clone, Debug, IntoElement, RegisterComponent)]
pub struct KeyBinding {
/// A keybinding consists of a set of keystrokes,
/// where each keystroke is a key and a set of modifier keys.
/// More than one keystroke produces a chord.
///
/// This should always contain at least one keystroke.
pub keystrokes: Vec<KeybindingKeystroke>,
source: Source,
size: Option<AbsoluteLength>,
/// The [`PlatformStyle`] to use when displaying this keybinding.
platform_style: PlatformStyle,
size: Option<AbsoluteLength>,
/// Determines whether the keybinding is meant for vim mode.
vim_mode: bool,
/// Indicates whether the keybinding is currently disabled.
disabled: bool,
}
@@ -32,23 +60,13 @@ impl Global for VimStyle {}
impl KeyBinding {
/// Returns the highest precedence keybinding for an action. This is the last binding added to
/// the keymap. User bindings are added after built-in bindings so that they take precedence.
pub fn for_action(action: &dyn Action, window: &mut Window, cx: &App) -> Option<Self> {
if let Some(focused) = window.focused(cx) {
return Self::for_action_in(action, &focused, window, cx);
}
let key_binding = window.highest_precedence_binding_for_action(action)?;
Some(Self::new_from_gpui(key_binding, cx))
pub fn for_action(action: &dyn Action, cx: &App) -> Self {
Self::new(action, None, cx)
}
/// Like `for_action`, but lets you specify the context from which keybindings are matched.
pub fn for_action_in(
action: &dyn Action,
focus: &FocusHandle,
window: &Window,
cx: &App,
) -> Option<Self> {
let key_binding = window.highest_precedence_binding_for_action_in(action, focus)?;
Some(Self::new_from_gpui(key_binding, cx))
pub fn for_action_in(action: &dyn Action, focus: &FocusHandle, cx: &App) -> Self {
Self::new(action, Some(focus.clone()), cx)
}
pub fn set_vim_mode(cx: &mut App, enabled: bool) {
@@ -59,18 +77,27 @@ impl KeyBinding {
cx.try_global::<VimStyle>().is_some_and(|g| g.0)
}
pub fn new(keystrokes: Vec<KeybindingKeystroke>, cx: &App) -> Self {
pub fn new(action: &dyn Action, focus_handle: Option<FocusHandle>, cx: &App) -> Self {
Self {
keystrokes,
platform_style: PlatformStyle::platform(),
source: Source::Action {
action: action.boxed_clone(),
focus_handle,
},
size: None,
vim_mode: KeyBinding::is_vim_mode(cx),
platform_style: PlatformStyle::platform(),
disabled: false,
}
}
pub fn new_from_gpui(key_binding: gpui::KeyBinding, cx: &App) -> Self {
Self::new(key_binding.keystrokes().to_vec(), cx)
pub fn from_keystrokes(keystrokes: Rc<[KeybindingKeystroke]>, source: KeybindSource) -> Self {
Self {
source: Source::Keystrokes { keystrokes },
size: None,
vim_mode: source == KeybindSource::Vim,
platform_style: PlatformStyle::platform(),
disabled: false,
}
}
/// Sets the [`PlatformStyle`] for this [`KeyBinding`].
@@ -91,11 +118,6 @@ impl KeyBinding {
self.disabled = disabled;
self
}
pub fn vim_mode(mut self, enabled: bool) -> Self {
self.vim_mode = enabled;
self
}
}
fn render_key(
@@ -115,36 +137,54 @@ fn render_key(
}
impl RenderOnce for KeyBinding {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let color = self.disabled.then_some(Color::Disabled);
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let render_keybinding = |keystrokes: &[KeybindingKeystroke]| {
let color = self.disabled.then_some(Color::Disabled);
h_flex()
.debug_selector(|| {
format!(
"KEY_BINDING-{}",
self.keystrokes
.iter()
.map(|k| k.key().to_string())
.collect::<Vec<_>>()
.join(" ")
)
})
.gap(DynamicSpacing::Base04.rems(cx))
.flex_none()
.children(self.keystrokes.iter().map(|keystroke| {
h_flex()
.flex_none()
.py_0p5()
.rounded_xs()
.text_color(cx.theme().colors().text_muted)
.children(render_keybinding_keystroke(
keystroke,
color,
self.size,
self.platform_style,
self.vim_mode,
))
}))
h_flex()
.debug_selector(|| {
format!(
"KEY_BINDING-{}",
keystrokes
.iter()
.map(|k| k.key().to_string())
.collect::<Vec<_>>()
.join(" ")
)
})
.gap(DynamicSpacing::Base04.rems(cx))
.flex_none()
.children(keystrokes.iter().map(|keystroke| {
h_flex()
.flex_none()
.py_0p5()
.rounded_xs()
.text_color(cx.theme().colors().text_muted)
.children(render_keybinding_keystroke(
keystroke,
color,
self.size,
PlatformStyle::platform(),
self.vim_mode,
))
}))
.into_any_element()
};
match self.source {
Source::Action {
action,
focus_handle,
} => focus_handle
.or_else(|| window.focused(cx))
.and_then(|focus| {
window.highest_precedence_binding_for_action_in(action.as_ref(), &focus)
})
.or_else(|| window.highest_precedence_binding_for_action(action.as_ref()))
.map(|binding| render_keybinding(binding.keystrokes())),
Source::Keystrokes { keystrokes } => Some(render_keybinding(keystrokes.as_ref())),
}
.unwrap_or_else(|| gpui::Empty.into_any_element())
}
}
@@ -517,79 +557,79 @@ impl Component for KeyBinding {
)
}
fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
Some(
v_flex()
.gap_6()
.children(vec![
example_group_with_title(
"Basic Usage",
vec![
single_example(
"Default",
KeyBinding::new_from_gpui(
gpui::KeyBinding::new("ctrl-s", gpui::NoAction, None),
cx,
)
.into_any_element(),
),
single_example(
"Mac Style",
KeyBinding::new_from_gpui(
gpui::KeyBinding::new("cmd-s", gpui::NoAction, None),
cx,
)
.platform_style(PlatformStyle::Mac)
.into_any_element(),
),
single_example(
"Windows Style",
KeyBinding::new_from_gpui(
gpui::KeyBinding::new("ctrl-s", gpui::NoAction, None),
cx,
)
.platform_style(PlatformStyle::Windows)
.into_any_element(),
),
],
),
example_group_with_title(
"Vim Mode",
vec![single_example(
"Vim Mode Enabled",
KeyBinding::new_from_gpui(
gpui::KeyBinding::new("dd", gpui::NoAction, None),
cx,
)
.vim_mode(true)
.into_any_element(),
)],
),
example_group_with_title(
"Complex Bindings",
vec![
single_example(
"Multiple Keys",
KeyBinding::new_from_gpui(
gpui::KeyBinding::new("ctrl-k ctrl-b", gpui::NoAction, None),
cx,
)
.into_any_element(),
),
single_example(
"With Shift",
KeyBinding::new_from_gpui(
gpui::KeyBinding::new("shift-cmd-p", gpui::NoAction, None),
cx,
)
.into_any_element(),
),
],
),
])
.into_any_element(),
)
}
// fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
// Some(
// v_flex()
// .gap_6()
// .children(vec![
// example_group_with_title(
// "Basic Usage",
// vec![
// single_example(
// "Default",
// KeyBinding::new_from_gpui(
// gpui::KeyBinding::new("ctrl-s", gpui::NoAction, None),
// cx,
// )
// .into_any_element(),
// ),
// single_example(
// "Mac Style",
// KeyBinding::new_from_gpui(
// gpui::KeyBinding::new("cmd-s", gpui::NoAction, None),
// cx,
// )
// .platform_style(PlatformStyle::Mac)
// .into_any_element(),
// ),
// single_example(
// "Windows Style",
// KeyBinding::new_from_gpui(
// gpui::KeyBinding::new("ctrl-s", gpui::NoAction, None),
// cx,
// )
// .platform_style(PlatformStyle::Windows)
// .into_any_element(),
// ),
// ],
// ),
// example_group_with_title(
// "Vim Mode",
// vec![single_example(
// "Vim Mode Enabled",
// KeyBinding::new_from_gpui(
// gpui::KeyBinding::new("dd", gpui::NoAction, None),
// cx,
// )
// .vim_mode(true)
// .into_any_element(),
// )],
// ),
// example_group_with_title(
// "Complex Bindings",
// vec![
// single_example(
// "Multiple Keys",
// KeyBinding::new_from_gpui(
// gpui::KeyBinding::new("ctrl-k ctrl-b", gpui::NoAction, None),
// cx,
// )
// .into_any_element(),
// ),
// single_example(
// "With Shift",
// KeyBinding::new_from_gpui(
// gpui::KeyBinding::new("shift-cmd-p", gpui::NoAction, None),
// cx,
// )
// .into_any_element(),
// ),
// ],
// ),
// ])
// .into_any_element(),
// )
// }
}
#[cfg(test)]
+16 -11
View File
@@ -14,10 +14,11 @@ use theme::Appearance;
/// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};
/// use ui::prelude::*;
/// use ui::{KeyBinding, KeybindingHint};
/// use settings::KeybindSource;
///
/// # fn example(cx: &App) {
/// let hint = KeybindingHint::new(
/// KeyBinding::new(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-s").unwrap())], cx),
/// KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-s").unwrap())].into(), KeybindSource::Base),
/// Hsla::black()
/// )
/// .prefix("Save:")
@@ -45,10 +46,11 @@ impl KeybindingHint {
/// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};
/// use ui::prelude::*;
/// use ui::{KeyBinding, KeybindingHint};
/// use settings::KeybindSource;
///
/// # fn example(cx: &App) {
/// let hint = KeybindingHint::new(
/// KeyBinding::new(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-c").unwrap())], cx),
/// KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-c").unwrap())].into(), KeybindSource::Base),
/// Hsla::black()
/// );
/// # }
@@ -74,11 +76,12 @@ impl KeybindingHint {
/// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};
/// use ui::prelude::*;
/// use ui::{KeyBinding, KeybindingHint};
/// use settings::KeybindSource;
///
/// # fn example(cx: &App) {
/// let hint = KeybindingHint::with_prefix(
/// "Copy:",
/// KeyBinding::new(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-c").unwrap())], cx),
/// KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-c").unwrap())].into(), KeybindSource::Base),
/// Hsla::black()
/// );
/// # }
@@ -108,10 +111,11 @@ impl KeybindingHint {
/// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};
/// use ui::prelude::*;
/// use ui::{KeyBinding, KeybindingHint};
/// use settings::KeybindSource;
///
/// # fn example(cx: &App) {
/// let hint = KeybindingHint::with_suffix(
/// KeyBinding::new(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-v").unwrap())], cx),
/// KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-v").unwrap())].into(), KeybindSource::Base),
/// "Paste",
/// Hsla::black()
/// );
@@ -141,10 +145,11 @@ impl KeybindingHint {
/// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};
/// use ui::prelude::*;
/// use ui::{KeyBinding, KeybindingHint};
/// use settings::KeybindSource;
///
/// # fn example(cx: &App) {
/// let hint = KeybindingHint::new(
/// KeyBinding::new(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-x").unwrap())], cx),
/// KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-x").unwrap())].into(), KeybindSource::Base),
/// Hsla::black()
/// )
/// .prefix("Cut:");
@@ -165,10 +170,11 @@ impl KeybindingHint {
/// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};
/// use ui::prelude::*;
/// use ui::{KeyBinding, KeybindingHint};
/// use settings::KeybindSource;
///
/// # fn example(cx: &App) {
/// let hint = KeybindingHint::new(
/// KeyBinding::new(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-f").unwrap())], cx),
/// KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-f").unwrap())].into(), KeybindSource::Base),
/// Hsla::black()
/// )
/// .suffix("Find");
@@ -189,10 +195,11 @@ impl KeybindingHint {
/// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};
/// use ui::prelude::*;
/// use ui::{KeyBinding, KeybindingHint};
/// use settings::KeybindSource;
///
/// # fn example(cx: &App) {
/// let hint = KeybindingHint::new(
/// KeyBinding::new(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-z").unwrap())], cx),
/// KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-z").unwrap())].into(), KeybindSource::Base),
/// Hsla::black()
/// )
/// .size(Pixels::from(16.0));
@@ -265,10 +272,8 @@ impl Component for KeybindingHint {
Some("Displays a keyboard shortcut hint with optional prefix and suffix text")
}
fn preview(window: &mut Window, cx: &mut App) -> Option<AnyElement> {
let enter_fallback = gpui::KeyBinding::new("enter", menu::Confirm, None);
let enter = KeyBinding::for_action(&menu::Confirm, window, cx)
.unwrap_or(KeyBinding::new_from_gpui(enter_fallback, cx));
fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
let enter = KeyBinding::for_action(&menu::Confirm, cx);
let bg_color = cx.theme().colors().surface_background;
+61 -24
View File
@@ -1,6 +1,7 @@
use gpui::NoAction;
use gpui::Render;
use itertools::Itertools;
use settings::KeybindSource;
use story::Story;
use crate::{KeyBinding, prelude::*};
@@ -15,19 +16,36 @@ impl Render for KeybindingStory {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let all_modifier_permutations = ["ctrl", "alt", "cmd", "shift"].into_iter().permutations(2);
const SOURCE: KeybindSource = KeybindSource::Base;
Story::container(cx)
.child(Story::title_for::<KeyBinding>(cx))
.child(Story::label("Single Key", cx))
.child(KeyBinding::new_from_gpui(binding("Z"), cx))
.child(KeyBinding::from_keystrokes(
binding("Z").keystrokes().into(),
SOURCE,
))
.child(Story::label("Single Key with Modifier", cx))
.child(
div()
.flex()
.gap_3()
.child(KeyBinding::new_from_gpui(binding("ctrl-c"), cx))
.child(KeyBinding::new_from_gpui(binding("alt-c"), cx))
.child(KeyBinding::new_from_gpui(binding("cmd-c"), cx))
.child(KeyBinding::new_from_gpui(binding("shift-c"), cx)),
.child(KeyBinding::from_keystrokes(
binding("ctrl-c").keystrokes().into(),
SOURCE,
))
.child(KeyBinding::from_keystrokes(
binding("alt-c").keystrokes().into(),
SOURCE,
))
.child(KeyBinding::from_keystrokes(
binding("cmd-c").keystrokes().into(),
SOURCE,
))
.child(KeyBinding::from_keystrokes(
binding("shift-c").keystrokes().into(),
SOURCE,
)),
)
.child(Story::label("Single Key with Modifier (Permuted)", cx))
.child(
@@ -41,58 +59,77 @@ impl Render for KeybindingStory {
.gap_4()
.py_3()
.children(chunk.map(|permutation| {
KeyBinding::new_from_gpui(
binding(&(permutation.join("-") + "-x")),
cx,
KeyBinding::from_keystrokes(
binding(&(permutation.join("-") + "-x"))
.keystrokes()
.into(),
SOURCE,
)
}))
}),
),
)
.child(Story::label("Single Key with All Modifiers", cx))
.child(KeyBinding::new_from_gpui(
binding("ctrl-alt-cmd-shift-z"),
cx,
.child(KeyBinding::from_keystrokes(
binding("ctrl-alt-cmd-shift-z").keystrokes().into(),
SOURCE,
))
.child(Story::label("Chord", cx))
.child(KeyBinding::new_from_gpui(binding("a z"), cx))
.child(KeyBinding::from_keystrokes(
binding("a z").keystrokes().into(),
SOURCE,
))
.child(Story::label("Chord with Modifier", cx))
.child(KeyBinding::new_from_gpui(binding("ctrl-a shift-z"), cx))
.child(KeyBinding::new_from_gpui(binding("fn-s"), cx))
.child(KeyBinding::from_keystrokes(
binding("ctrl-a shift-z").keystrokes().into(),
SOURCE,
))
.child(KeyBinding::from_keystrokes(
binding("fn-s").keystrokes().into(),
SOURCE,
))
.child(Story::label("Single Key with All Modifiers (Linux)", cx))
.child(
KeyBinding::new_from_gpui(binding("ctrl-alt-cmd-shift-z"), cx)
.platform_style(PlatformStyle::Linux),
KeyBinding::from_keystrokes(
binding("ctrl-alt-cmd-shift-z").keystrokes().into(),
SOURCE,
)
.platform_style(PlatformStyle::Linux),
)
.child(Story::label("Chord (Linux)", cx))
.child(
KeyBinding::new_from_gpui(binding("a z"), cx).platform_style(PlatformStyle::Linux),
KeyBinding::from_keystrokes(binding("a z").keystrokes().into(), SOURCE)
.platform_style(PlatformStyle::Linux),
)
.child(Story::label("Chord with Modifier (Linux)", cx))
.child(
KeyBinding::new_from_gpui(binding("ctrl-a shift-z"), cx)
KeyBinding::from_keystrokes(binding("ctrl-a shift-z").keystrokes().into(), SOURCE)
.platform_style(PlatformStyle::Linux),
)
.child(
KeyBinding::new_from_gpui(binding("fn-s"), cx).platform_style(PlatformStyle::Linux),
KeyBinding::from_keystrokes(binding("fn-s").keystrokes().into(), SOURCE)
.platform_style(PlatformStyle::Linux),
)
.child(Story::label("Single Key with All Modifiers (Windows)", cx))
.child(
KeyBinding::new_from_gpui(binding("ctrl-alt-cmd-shift-z"), cx)
.platform_style(PlatformStyle::Windows),
KeyBinding::from_keystrokes(
binding("ctrl-alt-cmd-shift-z").keystrokes().into(),
SOURCE,
)
.platform_style(PlatformStyle::Windows),
)
.child(Story::label("Chord (Windows)", cx))
.child(
KeyBinding::new_from_gpui(binding("a z"), cx)
KeyBinding::from_keystrokes(binding("a z").keystrokes().into(), SOURCE)
.platform_style(PlatformStyle::Windows),
)
.child(Story::label("Chord with Modifier (Windows)", cx))
.child(
KeyBinding::new_from_gpui(binding("ctrl-a shift-z"), cx)
KeyBinding::from_keystrokes(binding("ctrl-a shift-z").keystrokes().into(), SOURCE)
.platform_style(PlatformStyle::Windows),
)
.child(
KeyBinding::new_from_gpui(binding("fn-s"), cx)
KeyBinding::from_keystrokes(binding("fn-s").keystrokes().into(), SOURCE)
.platform_style(PlatformStyle::Windows),
)
}
+12 -13
View File
@@ -64,11 +64,11 @@ impl Tooltip {
) -> impl Fn(&mut Window, &mut App) -> AnyView + use<T> {
let title = title.into();
let action = action.boxed_clone();
move |window, cx| {
move |_, cx| {
cx.new(|cx| Self {
title: Title::Str(title.clone()),
meta: None,
key_binding: KeyBinding::for_action(action.as_ref(), window, cx),
key_binding: Some(KeyBinding::for_action(action.as_ref(), cx)),
})
.into()
}
@@ -82,11 +82,15 @@ impl Tooltip {
let title = title.into();
let action = action.boxed_clone();
let focus_handle = focus_handle.clone();
move |window, cx| {
move |_, cx| {
cx.new(|cx| Self {
title: Title::Str(title.clone()),
meta: None,
key_binding: KeyBinding::for_action_in(action.as_ref(), &focus_handle, window, cx),
key_binding: Some(KeyBinding::for_action_in(
action.as_ref(),
&focus_handle,
cx,
)),
})
.into()
}
@@ -95,13 +99,12 @@ impl Tooltip {
pub fn for_action(
title: impl Into<SharedString>,
action: &dyn Action,
window: &mut Window,
cx: &mut App,
) -> AnyView {
cx.new(|cx| Self {
title: Title::Str(title.into()),
meta: None,
key_binding: KeyBinding::for_action(action, window, cx),
key_binding: Some(KeyBinding::for_action(action, cx)),
})
.into()
}
@@ -110,13 +113,12 @@ impl Tooltip {
title: impl Into<SharedString>,
action: &dyn Action,
focus_handle: &FocusHandle,
window: &mut Window,
cx: &mut App,
) -> AnyView {
cx.new(|cx| Self {
title: title.into().into(),
meta: None,
key_binding: KeyBinding::for_action_in(action, focus_handle, window, cx),
key_binding: Some(KeyBinding::for_action_in(action, focus_handle, cx)),
})
.into()
}
@@ -125,13 +127,12 @@ impl Tooltip {
title: impl Into<SharedString>,
action: Option<&dyn Action>,
meta: impl Into<SharedString>,
window: &mut Window,
cx: &mut App,
) -> AnyView {
cx.new(|cx| Self {
title: title.into().into(),
meta: Some(meta.into()),
key_binding: action.and_then(|action| KeyBinding::for_action(action, window, cx)),
key_binding: action.map(|action| KeyBinding::for_action(action, cx)),
})
.into()
}
@@ -141,14 +142,12 @@ impl Tooltip {
action: Option<&dyn Action>,
meta: impl Into<SharedString>,
focus_handle: &FocusHandle,
window: &mut Window,
cx: &mut App,
) -> AnyView {
cx.new(|cx| Self {
title: title.into().into(),
meta: Some(meta.into()),
key_binding: action
.and_then(|action| KeyBinding::for_action_in(action, focus_handle, window, cx)),
key_binding: action.map(|action| KeyBinding::for_action_in(action, focus_handle, cx)),
})
.into()
}