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:
@@ -466,11 +466,10 @@ impl PickerDelegate for BranchListDelegate {
|
||||
this.delegate.set_selected_index(ix, window, cx);
|
||||
this.delegate.confirm(true, window, cx);
|
||||
}))
|
||||
.tooltip(move |window, cx| {
|
||||
.tooltip(move |_window, cx| {
|
||||
Tooltip::for_action(
|
||||
format!("Create branch based off default: {default_branch}"),
|
||||
&menu::SecondaryConfirm,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
|
||||
@@ -327,7 +327,7 @@ impl CommitModal {
|
||||
.anchor(Corner::TopRight)
|
||||
}
|
||||
|
||||
pub fn render_footer(&self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
pub fn render_footer(&self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let (
|
||||
can_commit,
|
||||
tooltip,
|
||||
@@ -388,7 +388,7 @@ impl CommitModal {
|
||||
});
|
||||
let focus_handle = self.focus_handle(cx);
|
||||
|
||||
let close_kb_hint = ui::KeyBinding::for_action(&menu::Cancel, window, cx).map(|close_kb| {
|
||||
let close_kb_hint = ui::KeyBinding::for_action(&menu::Cancel, cx).map(|close_kb| {
|
||||
KeybindingHint::new(close_kb, cx.theme().colors().editor_background).suffix("Cancel")
|
||||
});
|
||||
|
||||
@@ -423,7 +423,7 @@ impl CommitModal {
|
||||
.flex_none()
|
||||
.px_1()
|
||||
.gap_4()
|
||||
.children(close_kb_hint)
|
||||
.child(close_kb_hint)
|
||||
.child(SplitButton::new(
|
||||
ui::ButtonLike::new_rounded_left(ElementId::Name(
|
||||
format!("split-button-left-{}", commit_label).into(),
|
||||
@@ -452,7 +452,7 @@ impl CommitModal {
|
||||
.disabled(!can_commit)
|
||||
.tooltip({
|
||||
let focus_handle = focus_handle.clone();
|
||||
move |window, cx| {
|
||||
move |_window, cx| {
|
||||
if can_commit {
|
||||
Tooltip::with_meta_in(
|
||||
tooltip,
|
||||
@@ -467,7 +467,6 @@ impl CommitModal {
|
||||
if is_signoff_enabled { " --signoff" } else { "" }
|
||||
),
|
||||
&focus_handle.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
|
||||
@@ -3091,13 +3091,12 @@ impl GitPanel {
|
||||
IconButton::new("generate-commit-message", IconName::AiEdit)
|
||||
.shape(ui::IconButtonShape::Square)
|
||||
.icon_color(Color::Muted)
|
||||
.tooltip(move |window, cx| {
|
||||
.tooltip(move |_window, cx| {
|
||||
if can_commit {
|
||||
Tooltip::for_action_in(
|
||||
"Generate Commit Message",
|
||||
&git::GenerateCommitMessage,
|
||||
&editor_focus_handle,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
@@ -3459,12 +3458,11 @@ impl GitPanel {
|
||||
panel_icon_button("expand-commit-editor", IconName::Maximize)
|
||||
.icon_size(IconSize::Small)
|
||||
.size(ui::ButtonSize::Default)
|
||||
.tooltip(move |window, cx| {
|
||||
.tooltip(move |_window, cx| {
|
||||
Tooltip::for_action_in(
|
||||
"Open Commit Modal",
|
||||
&git::ExpandCommitEditor,
|
||||
&expand_tooltip_focus_handle,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
@@ -3526,7 +3524,7 @@ impl GitPanel {
|
||||
.disabled(!can_commit || self.modal_open)
|
||||
.tooltip({
|
||||
let handle = commit_tooltip_focus_handle.clone();
|
||||
move |window, cx| {
|
||||
move |_window, cx| {
|
||||
if can_commit {
|
||||
Tooltip::with_meta_in(
|
||||
tooltip,
|
||||
@@ -3537,7 +3535,6 @@ impl GitPanel {
|
||||
if signoff { " --signoff" } else { "" }
|
||||
),
|
||||
&handle.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
@@ -3640,7 +3637,7 @@ impl GitPanel {
|
||||
panel_icon_button("undo", IconName::Undo)
|
||||
.icon_size(IconSize::XSmall)
|
||||
.icon_color(Color::Muted)
|
||||
.tooltip(move |window, cx| {
|
||||
.tooltip(move |_window, cx| {
|
||||
Tooltip::with_meta(
|
||||
"Uncommit",
|
||||
Some(&git::Uncommit),
|
||||
@@ -3649,7 +3646,6 @@ impl GitPanel {
|
||||
} else {
|
||||
"git reset HEAD^"
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
@@ -4120,13 +4116,13 @@ impl GitPanel {
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.tooltip(move |window, cx| {
|
||||
.tooltip(move |_window, cx| {
|
||||
let is_staged = entry_staging.is_fully_staged();
|
||||
|
||||
let action = if is_staged { "Unstage" } else { "Stage" };
|
||||
let tooltip_name = action.to_string();
|
||||
|
||||
Tooltip::for_action(tooltip_name, &ToggleStaged, window, cx)
|
||||
Tooltip::for_action(tooltip_name, &ToggleStaged, cx)
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -435,13 +435,12 @@ mod remote_button {
|
||||
move |_, window, cx| {
|
||||
window.dispatch_action(Box::new(git::Fetch), cx);
|
||||
},
|
||||
move |window, cx| {
|
||||
move |_window, cx| {
|
||||
git_action_tooltip(
|
||||
"Fetch updates from remote",
|
||||
&git::Fetch,
|
||||
"git fetch",
|
||||
keybinding_target.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
},
|
||||
@@ -463,13 +462,12 @@ mod remote_button {
|
||||
move |_, window, cx| {
|
||||
window.dispatch_action(Box::new(git::Push), cx);
|
||||
},
|
||||
move |window, cx| {
|
||||
move |_window, cx| {
|
||||
git_action_tooltip(
|
||||
"Push committed changes to remote",
|
||||
&git::Push,
|
||||
"git push",
|
||||
keybinding_target.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
},
|
||||
@@ -492,13 +490,12 @@ mod remote_button {
|
||||
move |_, window, cx| {
|
||||
window.dispatch_action(Box::new(git::Pull), cx);
|
||||
},
|
||||
move |window, cx| {
|
||||
move |_window, cx| {
|
||||
git_action_tooltip(
|
||||
"Pull",
|
||||
&git::Pull,
|
||||
"git pull",
|
||||
keybinding_target.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
},
|
||||
@@ -519,13 +516,12 @@ mod remote_button {
|
||||
move |_, window, cx| {
|
||||
window.dispatch_action(Box::new(git::Push), cx);
|
||||
},
|
||||
move |window, cx| {
|
||||
move |_window, cx| {
|
||||
git_action_tooltip(
|
||||
"Publish branch to remote",
|
||||
&git::Push,
|
||||
"git push --set-upstream",
|
||||
keybinding_target.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
},
|
||||
@@ -546,13 +542,12 @@ mod remote_button {
|
||||
move |_, window, cx| {
|
||||
window.dispatch_action(Box::new(git::Push), cx);
|
||||
},
|
||||
move |window, cx| {
|
||||
move |_window, cx| {
|
||||
git_action_tooltip(
|
||||
"Re-publish branch to remote",
|
||||
&git::Push,
|
||||
"git push --set-upstream",
|
||||
keybinding_target.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
},
|
||||
@@ -564,16 +559,15 @@ mod remote_button {
|
||||
action: &dyn Action,
|
||||
command: impl Into<SharedString>,
|
||||
focus_handle: Option<FocusHandle>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> AnyView {
|
||||
let label = label.into();
|
||||
let command = command.into();
|
||||
|
||||
if let Some(handle) = focus_handle {
|
||||
Tooltip::with_meta_in(label, Some(action), command, &handle, window, cx)
|
||||
Tooltip::with_meta_in(label, Some(action), command, &handle, cx)
|
||||
} else {
|
||||
Tooltip::with_meta(label, Some(action), command, window, cx)
|
||||
Tooltip::with_meta(label, Some(action), command, cx)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -714,7 +714,7 @@ impl Item for ProjectDiff {
|
||||
}
|
||||
|
||||
impl Render for ProjectDiff {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let is_empty = self.multibuffer.read(cx).is_empty();
|
||||
|
||||
div()
|
||||
@@ -759,7 +759,6 @@ impl Render for ProjectDiff {
|
||||
.key_binding(KeyBinding::for_action_in(
|
||||
&CloseActiveItem::default(),
|
||||
&keybinding_focus_handle,
|
||||
window,
|
||||
cx,
|
||||
))
|
||||
.on_click(move |_, window, cx| {
|
||||
|
||||
@@ -523,11 +523,7 @@ impl PickerDelegate for StashListDelegate {
|
||||
Some("No stashes found".into())
|
||||
}
|
||||
|
||||
fn render_footer(
|
||||
&self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
) -> Option<AnyElement> {
|
||||
fn render_footer(&self, _: &mut Window, cx: &mut Context<Picker<Self>>) -> Option<AnyElement> {
|
||||
let focus_handle = self.focus_handle.clone();
|
||||
|
||||
Some(
|
||||
@@ -541,7 +537,7 @@ impl PickerDelegate for StashListDelegate {
|
||||
.child(
|
||||
Button::new("apply-stash", "Apply")
|
||||
.key_binding(
|
||||
KeyBinding::for_action_in(&menu::Confirm, &focus_handle, window, cx)
|
||||
KeyBinding::for_action_in(&menu::Confirm, &focus_handle, cx)
|
||||
.map(|kb| kb.size(rems_from_px(12.))),
|
||||
)
|
||||
.on_click(|_, window, cx| {
|
||||
@@ -551,13 +547,8 @@ impl PickerDelegate for StashListDelegate {
|
||||
.child(
|
||||
Button::new("pop-stash", "Pop")
|
||||
.key_binding(
|
||||
KeyBinding::for_action_in(
|
||||
&menu::SecondaryConfirm,
|
||||
&focus_handle,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.map(|kb| kb.size(rems_from_px(12.))),
|
||||
KeyBinding::for_action_in(&menu::SecondaryConfirm, &focus_handle, cx)
|
||||
.map(|kb| kb.size(rems_from_px(12.))),
|
||||
)
|
||||
.on_click(|_, window, cx| {
|
||||
window.dispatch_action(menu::SecondaryConfirm.boxed_clone(), cx)
|
||||
@@ -569,7 +560,6 @@ impl PickerDelegate for StashListDelegate {
|
||||
KeyBinding::for_action_in(
|
||||
&stash_picker::DropStashItem,
|
||||
&focus_handle,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.map(|kb| kb.size(rems_from_px(12.))),
|
||||
|
||||
Reference in New Issue
Block a user