mirror of
https://github.com/zed-industries/zed.git
synced 2026-08-17 21:14:45 +00:00
editor: Fix buffer header context menu line height in multibuffers (#61923)
Some checks are pending
Congratsbot / check-author (push) Waiting to run
Congratsbot / congrats (push) Blocked by required conditions
deploy_nightly_docs / deploy_docs (push) Waiting to run
run_tests / orchestrate (push) Waiting to run
run_tests / check_style (push) Waiting to run
run_tests / clippy_windows (push) Blocked by required conditions
run_tests / clippy_linux (push) Blocked by required conditions
run_tests / clippy_mac (push) Blocked by required conditions
run_tests / clippy_mac_x86_64 (push) Blocked by required conditions
run_tests / run_tests_windows (push) Blocked by required conditions
run_tests / run_tests_linux (push) Blocked by required conditions
run_tests / run_tests_mac (push) Blocked by required conditions
run_tests / miri_scheduler (push) Blocked by required conditions
run_tests / doctests (push) Blocked by required conditions
run_tests / check_workspace_binaries (push) Blocked by required conditions
run_tests / build_visual_tests_binary (push) Blocked by required conditions
run_tests / check_wasm (push) Blocked by required conditions
run_tests / check_dependencies (push) Blocked by required conditions
run_tests / check_docs (push) Blocked by required conditions
run_tests / check_licenses (push) Blocked by required conditions
run_tests / check_scripts (push) Blocked by required conditions
run_tests / check_postgres_and_protobuf_migrations (push) Blocked by required conditions
run_tests / extension_tests (push) Blocked by required conditions
run_tests / tests_pass (push) Blocked by required conditions
Some checks are pending
Congratsbot / check-author (push) Waiting to run
Congratsbot / congrats (push) Blocked by required conditions
deploy_nightly_docs / deploy_docs (push) Waiting to run
run_tests / orchestrate (push) Waiting to run
run_tests / check_style (push) Waiting to run
run_tests / clippy_windows (push) Blocked by required conditions
run_tests / clippy_linux (push) Blocked by required conditions
run_tests / clippy_mac (push) Blocked by required conditions
run_tests / clippy_mac_x86_64 (push) Blocked by required conditions
run_tests / run_tests_windows (push) Blocked by required conditions
run_tests / run_tests_linux (push) Blocked by required conditions
run_tests / run_tests_mac (push) Blocked by required conditions
run_tests / miri_scheduler (push) Blocked by required conditions
run_tests / doctests (push) Blocked by required conditions
run_tests / check_workspace_binaries (push) Blocked by required conditions
run_tests / build_visual_tests_binary (push) Blocked by required conditions
run_tests / check_wasm (push) Blocked by required conditions
run_tests / check_dependencies (push) Blocked by required conditions
run_tests / check_docs (push) Blocked by required conditions
run_tests / check_licenses (push) Blocked by required conditions
run_tests / check_scripts (push) Blocked by required conditions
run_tests / check_postgres_and_protobuf_migrations (push) Blocked by required conditions
run_tests / extension_tests (push) Blocked by required conditions
run_tests / tests_pass (push) Blocked by required conditions
## Objective Right-clicking a buffer header in a multibuffer showed a context menu whose item spacing did not match other context menus. The menu is drawn via a deferred draw, which inherits the editor's text style stack, so its line height followed `buffer_line_height` instead of the default UI line height. This is the same root cause as #24504, which #25172 fixed for the editor's mouse context menu and completion popovers. The buffer header menu was a remaining call site. ## Solution `ContextMenu` now applies the default (`comfortable`) line height itself in `render`, next to its existing rem size and font family normalization, so menus render the same regardless of where they are opened from. This fixes the all workarounds and the need for them too: the workaround in `layout_mouse_context_menu` is removed, and the buffer header ends up needing no changes at all. The completions and code actions popovers keep their override in `element.rs`: they are not `ui::ContextMenu`s and compute their sizes with eager `window.line_height()` reads while being built, so styling on the elements they return cannot cover them. Migrating them could be a follow-up. ## Testing - `cargo check --workspace` passes, `./script/clippy` on the touched crates passes. - Manual: set `"buffer_line_height": "standard"` (or any extreme custom value to see it better), open a multibuffer (e.g. project search), right-click a buffer header, and compare the menu with another context menu (e.g. a tab's) — spacing matches. The editor's mouse context menu, which lost its own override, renders as before, and with default settings there is no visual change anywhere. - Tested on macOS, change is platform-independent styling. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [ ] Tests cover the new/changed behavior (visual styling fix; menu text styles have no existing test coverage) - [x] Performance impact has been considered and is acceptable ## Showcase Regular context menu: <img width="425" height="164" alt="A context menu elsewhere in the app, showing normal item spacing" src="https://github.com/user-attachments/assets/1fc13981-b394-444f-883a-ce3ef462c386" /> Before: <img width="425" height="164" alt="Buffer header context menu before the fix, with tighter item spacing following the custom buffer_line_height" src="https://github.com/user-attachments/assets/9774076c-7e0c-41dd-b54f-53de58b24336" /> After: <img width="425" height="164" alt="Buffer header context menu after the fix, with item spacing matching other context menus" src="https://github.com/user-attachments/assets/ae76e37c-8e39-474c-8a5e-e229e69173fb" /> --- Release Notes: - Fixed the file header context menu in multibuffers not matching other context menus' spacing when a custom `buffer_line_height` is set. --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
This commit is contained in:
parent
bc538def45
commit
bc6095f2c0
7 changed files with 69 additions and 68 deletions
|
|
@ -4,17 +4,16 @@ use std::time::{Duration, Instant};
|
|||
use collections::HashMap;
|
||||
use feature_flags::{DiffReviewFeatureFlag, FeatureFlagAppExt as _};
|
||||
use gpui::{
|
||||
AnyElement, App, AvailableSpace, ClickEvent, Context, DefiniteLength, DispatchPhase, Element,
|
||||
MouseButton, MouseClickEvent, MouseDownEvent, MouseMoveEvent, MousePressureEvent, MouseUpEvent,
|
||||
ParentElement, Pixels, PressureStage, ScrollDelta, ScrollWheelEvent, TextStyleRefinement,
|
||||
Window, anchored, deferred, point, px,
|
||||
AnyElement, App, AvailableSpace, ClickEvent, Context, DispatchPhase, Element, MouseButton,
|
||||
MouseClickEvent, MouseDownEvent, MouseMoveEvent, MousePressureEvent, MouseUpEvent,
|
||||
ParentElement, Pixels, PressureStage, ScrollDelta, ScrollWheelEvent, Window, anchored,
|
||||
deferred, point, px,
|
||||
};
|
||||
use multi_buffer::MultiBufferRow;
|
||||
use project::DisableAiSettings;
|
||||
use settings::Settings;
|
||||
use sum_tree::Bias;
|
||||
use text::SelectionGoal;
|
||||
use theme_settings::BufferLineHeight;
|
||||
use util::{RangeExt, debug_panic, post_inc};
|
||||
|
||||
use super::{EditorElement, EditorLayout, LineNumberLayout, PositionMap, SplitSide};
|
||||
|
|
@ -322,33 +321,25 @@ impl EditorElement {
|
|||
}
|
||||
})?;
|
||||
|
||||
let text_style = TextStyleRefinement {
|
||||
line_height: Some(DefiniteLength::Fraction(
|
||||
BufferLineHeight::Comfortable.value(),
|
||||
)),
|
||||
..Default::default()
|
||||
};
|
||||
window.with_text_style(Some(text_style), |window| {
|
||||
let mut element = self.editor.read_with(cx, |editor, _| {
|
||||
let mouse_context_menu = editor.mouse_context_menu.as_ref()?;
|
||||
let context_menu = mouse_context_menu.context_menu.clone();
|
||||
let mut element = self.editor.read_with(cx, |editor, _| {
|
||||
let mouse_context_menu = editor.mouse_context_menu.as_ref()?;
|
||||
let context_menu = mouse_context_menu.context_menu.clone();
|
||||
|
||||
Some(
|
||||
deferred(
|
||||
anchored()
|
||||
.position(position)
|
||||
.child(context_menu)
|
||||
.anchor(gpui::Anchor::TopLeft)
|
||||
.snap_to_window_with_margin(px(8.)),
|
||||
)
|
||||
.with_priority(1)
|
||||
.into_any(),
|
||||
Some(
|
||||
deferred(
|
||||
anchored()
|
||||
.position(position)
|
||||
.child(context_menu)
|
||||
.anchor(gpui::Anchor::TopLeft)
|
||||
.snap_to_window_with_margin(px(8.)),
|
||||
)
|
||||
})?;
|
||||
.with_priority(1)
|
||||
.into_any(),
|
||||
)
|
||||
})?;
|
||||
|
||||
element.prepaint_as_root(position, AvailableSpace::min_size(), window, cx);
|
||||
Some(element)
|
||||
})
|
||||
element.prepaint_as_root(position, AvailableSpace::min_size(), window, cx);
|
||||
Some(element)
|
||||
}
|
||||
|
||||
pub(super) fn paint_mouse_listeners(
|
||||
|
|
|
|||
|
|
@ -952,8 +952,10 @@ fn appearance_page() -> SettingsPage {
|
|||
}
|
||||
settings::BufferLineHeightDiscriminants::Custom => {
|
||||
let custom_value =
|
||||
theme_settings::BufferLineHeight::from(*settings_value)
|
||||
.value();
|
||||
theme_settings::buffer_line_height_from_settings(
|
||||
*settings_value,
|
||||
)
|
||||
.value();
|
||||
settings::BufferLineHeight::Custom(custom_value)
|
||||
}
|
||||
};
|
||||
|
|
|
|||
22
crates/theme/src/buffer_line_height.rs
Normal file
22
crates/theme/src/buffer_line_height.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/// The buffer's line height.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Default)]
|
||||
pub enum BufferLineHeight {
|
||||
/// A less dense line height.
|
||||
#[default]
|
||||
Comfortable,
|
||||
/// The default line height.
|
||||
Standard,
|
||||
/// A custom line height, where 1.0 is the font's height. Must be at least 1.0.
|
||||
Custom(f32),
|
||||
}
|
||||
|
||||
impl BufferLineHeight {
|
||||
/// Returns the value of the line height.
|
||||
pub fn value(&self) -> f32 {
|
||||
match self {
|
||||
BufferLineHeight::Comfortable => 1.618,
|
||||
BufferLineHeight::Standard => 1.3,
|
||||
BufferLineHeight::Custom(line_height) => *line_height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
//!
|
||||
//! A theme is a collection of colors used to build a consistent appearance for UI components across the application.
|
||||
|
||||
mod buffer_line_height;
|
||||
mod color_space;
|
||||
mod default_colors;
|
||||
mod fallback_themes;
|
||||
|
|
@ -31,6 +32,7 @@ use gpui::{
|
|||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
pub use crate::buffer_line_height::*;
|
||||
pub use crate::color_space::*;
|
||||
pub use crate::default_colors::*;
|
||||
pub use crate::fallback_themes::{apply_status_color_defaults, apply_theme_color_defaults};
|
||||
|
|
|
|||
|
|
@ -359,38 +359,13 @@ pub fn set_mode(content: &mut SettingsContent, mode: ThemeAppearanceMode) {
|
|||
}
|
||||
}
|
||||
|
||||
/// The buffer's line height.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Default)]
|
||||
pub enum BufferLineHeight {
|
||||
/// A less dense line height.
|
||||
#[default]
|
||||
Comfortable,
|
||||
/// The default line height.
|
||||
Standard,
|
||||
/// A custom line height, where 1.0 is the font's height. Must be at least 1.0.
|
||||
Custom(f32),
|
||||
}
|
||||
pub use theme::BufferLineHeight;
|
||||
|
||||
impl From<settings::BufferLineHeight> for BufferLineHeight {
|
||||
fn from(value: settings::BufferLineHeight) -> Self {
|
||||
match value {
|
||||
settings::BufferLineHeight::Comfortable => BufferLineHeight::Comfortable,
|
||||
settings::BufferLineHeight::Standard => BufferLineHeight::Standard,
|
||||
settings::BufferLineHeight::Custom(line_height) => {
|
||||
BufferLineHeight::Custom(line_height)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BufferLineHeight {
|
||||
/// Returns the value of the line height.
|
||||
pub fn value(&self) -> f32 {
|
||||
match self {
|
||||
BufferLineHeight::Comfortable => 1.618,
|
||||
BufferLineHeight::Standard => 1.3,
|
||||
BufferLineHeight::Custom(line_height) => *line_height,
|
||||
}
|
||||
pub fn buffer_line_height_from_settings(value: settings::BufferLineHeight) -> BufferLineHeight {
|
||||
match value {
|
||||
settings::BufferLineHeight::Comfortable => BufferLineHeight::Comfortable,
|
||||
settings::BufferLineHeight::Standard => BufferLineHeight::Standard,
|
||||
settings::BufferLineHeight::Custom(line_height) => BufferLineHeight::Custom(line_height),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -754,7 +729,9 @@ impl settings::Settings for ThemeSettings {
|
|||
style: FontStyle::default(),
|
||||
},
|
||||
buffer_font_size: clamp_font_size(content.buffer_font_size.unwrap().into_gpui()),
|
||||
buffer_line_height: content.buffer_line_height.unwrap().into(),
|
||||
buffer_line_height: buffer_line_height_from_settings(
|
||||
content.buffer_line_height.unwrap(),
|
||||
),
|
||||
agent_ui_font_family: content
|
||||
.agent_ui_font_family
|
||||
.as_ref()
|
||||
|
|
|
|||
|
|
@ -33,10 +33,10 @@ pub use crate::settings::{
|
|||
ThemeAppearanceMode, ThemeName, ThemeSelection, ThemeSettings, adjust_agent_buffer_font_size,
|
||||
adjust_agent_ui_font_size, adjust_git_commit_buffer_font_size,
|
||||
adjust_markdown_preview_font_size, adjust_ui_font_size, adjusted_font_size, appearance_to_mode,
|
||||
clamp_font_size, default_theme, observe_buffer_font_size_adjustment,
|
||||
reset_agent_buffer_font_size, reset_agent_ui_font_size, reset_buffer_font_size,
|
||||
reset_git_commit_buffer_font_size, reset_markdown_preview_font_size, reset_ui_font_size,
|
||||
set_icon_theme, set_mode, set_theme, setup_ui_font,
|
||||
buffer_line_height_from_settings, clamp_font_size, default_theme,
|
||||
observe_buffer_font_size_adjustment, reset_agent_buffer_font_size, reset_agent_ui_font_size,
|
||||
reset_buffer_font_size, reset_git_commit_buffer_font_size, reset_markdown_preview_font_size,
|
||||
reset_ui_font_size, set_icon_theme, set_mode, set_theme, setup_ui_font,
|
||||
};
|
||||
pub use theme::UiDensity;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
use gpui::{
|
||||
Action, Anchor, AnyElement, App, Bounds, DismissEvent, Entity, EventEmitter, FocusHandle,
|
||||
Focusable, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Point, Role,
|
||||
Size, Subscription, TaskExt, anchored, canvas, prelude::*, px,
|
||||
Size, Subscription, TaskExt, anchored, canvas, prelude::*, px, relative,
|
||||
};
|
||||
use menu::{SelectChild, SelectFirst, SelectLast, SelectNext, SelectParent, SelectPrevious};
|
||||
use std::{
|
||||
|
|
@ -14,6 +14,7 @@ use std::{
|
|||
rc::Rc,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use theme::BufferLineHeight;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
enum SubmenuOpenTrigger {
|
||||
|
|
@ -2194,6 +2195,10 @@ impl Render for ContextMenu {
|
|||
let theme_settings = theme::theme_settings(cx);
|
||||
let ui_font_size = theme_settings.ui_font_size(cx);
|
||||
let ui_font_family = theme_settings.ui_font(cx).family.clone();
|
||||
// Menus can be deferred from inside elements that override the text
|
||||
// style (e.g. the editor with a custom `buffer_line_height`), so always
|
||||
// apply the default line height to render the same everywhere.
|
||||
let line_height = relative(BufferLineHeight::Comfortable.value());
|
||||
let window_size = window.viewport_size();
|
||||
let rem_size = window.rem_size();
|
||||
let is_wide_window = window_size.width / rem_size > rems_from_px(800_f32).0;
|
||||
|
|
@ -2244,6 +2249,7 @@ impl Render for ContextMenu {
|
|||
WithRemSize::new(ui_font_size)
|
||||
.occlude()
|
||||
.font_family(ui_font_family.clone())
|
||||
.line_height(line_height)
|
||||
.elevation_2(cx)
|
||||
.w_full()
|
||||
.p_2()
|
||||
|
|
@ -2271,6 +2277,7 @@ impl Render for ContextMenu {
|
|||
WithRemSize::new(ui_font_size)
|
||||
.occlude()
|
||||
.font_family(ui_font_family.clone())
|
||||
.line_height(line_height)
|
||||
.elevation_2(cx)
|
||||
.flex()
|
||||
.flex_row()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue