title_bar: Add setting to always show menu for Linux and Windows (#34139)

Closes #22869

Release Notes:

- Added `show_menus` setting to always show menu bar for Linux and
Windows.

---------

Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
This commit is contained in:
Smit Barmase 2025-07-09 09:44:11 -07:00 committed by GitHub
parent 6d26f107dd
commit d5cc1cbaa9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 97 additions and 32 deletions

View file

@ -1,4 +1,5 @@
use gpui::{Entity, OwnedMenu, OwnedMenuItem};
use settings::Settings;
#[cfg(not(target_os = "macos"))]
use gpui::{Action, actions};
@ -11,6 +12,8 @@ use serde::Deserialize;
use smallvec::SmallVec;
use ui::{ContextMenu, PopoverMenu, PopoverMenuHandle, Tooltip, prelude::*};
use crate::title_bar_settings::TitleBarSettings;
#[cfg(not(target_os = "macos"))]
actions!(
app_menu,
@ -242,15 +245,21 @@ impl ApplicationMenu {
cx.defer_in(window, move |_, window, cx| next_handle.show(window, cx));
}
pub fn all_menus_shown(&self) -> bool {
self.entries.iter().any(|entry| entry.handle.is_deployed())
pub fn all_menus_shown(&self, cx: &mut Context<Self>) -> bool {
show_menus(cx)
|| self.entries.iter().any(|entry| entry.handle.is_deployed())
|| self.pending_menu_open.is_some()
}
}
pub(crate) fn show_menus(cx: &mut App) -> bool {
TitleBarSettings::get_global(cx).show_menus
&& (cfg!(not(target_os = "macos")) || option_env!("ZED_USE_CROSS_PLATFORM_MENU").is_some())
}
impl Render for ApplicationMenu {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let all_menus_shown = self.all_menus_shown();
let all_menus_shown = self.all_menus_shown(cx);
if let Some(pending_menu_open) = self.pending_menu_open.take() {
if let Some(entry) = self

View file

@ -1,6 +1,6 @@
use gpui::{
AnyElement, Context, Decorations, InteractiveElement, IntoElement, MouseButton, ParentElement,
Pixels, StatefulInteractiveElement, Styled, Window, WindowControlArea, div, px,
AnyElement, Context, Decorations, Hsla, InteractiveElement, IntoElement, MouseButton,
ParentElement, Pixels, StatefulInteractiveElement, Styled, Window, WindowControlArea, div, px,
};
use smallvec::SmallVec;
use std::mem;
@ -37,6 +37,18 @@ impl PlatformTitleBar {
px(32.)
}
pub fn title_bar_color(&self, window: &mut Window, cx: &mut Context<Self>) -> Hsla {
if cfg!(any(target_os = "linux", target_os = "freebsd")) {
if window.is_window_active() && !self.should_move {
cx.theme().colors().title_bar_background
} else {
cx.theme().colors().title_bar_inactive_background
}
} else {
cx.theme().colors().title_bar_background
}
}
pub fn set_children<T>(&mut self, children: T)
where
T: IntoIterator<Item = AnyElement>,
@ -50,15 +62,7 @@ impl Render for PlatformTitleBar {
let supported_controls = window.window_controls();
let decorations = window.window_decorations();
let height = Self::height(window);
let titlebar_color = if cfg!(any(target_os = "linux", target_os = "freebsd")) {
if window.is_window_active() && !self.should_move {
cx.theme().colors().title_bar_background
} else {
cx.theme().colors().title_bar_inactive_background
}
} else {
cx.theme().colors().title_bar_background
};
let titlebar_color = self.title_bar_color(window, cx);
let close_action = Box::new(workspace::CloseWindow);
let children = mem::take(&mut self.children);

View file

@ -8,7 +8,10 @@ mod title_bar_settings;
#[cfg(feature = "stories")]
mod stories;
use crate::{application_menu::ApplicationMenu, platform_title_bar::PlatformTitleBar};
use crate::{
application_menu::{ApplicationMenu, show_menus},
platform_title_bar::PlatformTitleBar,
};
#[cfg(not(target_os = "macos"))]
use crate::application_menu::{
@ -133,6 +136,8 @@ impl Render for TitleBar {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let title_bar_settings = *TitleBarSettings::get_global(cx);
let show_menus = show_menus(cx);
let mut children = Vec::new();
children.push(
@ -142,10 +147,14 @@ impl Render for TitleBar {
let mut render_project_items = title_bar_settings.show_branch_name
|| title_bar_settings.show_project_items;
title_bar
.when_some(self.application_menu.clone(), |title_bar, menu| {
render_project_items &= !menu.read(cx).all_menus_shown();
title_bar.child(menu)
})
.when_some(
self.application_menu.clone().filter(|_| !show_menus),
|title_bar, menu| {
render_project_items &=
!menu.update(cx, |menu, cx| menu.all_menus_shown(cx));
title_bar.child(menu)
},
)
.when(render_project_items, |title_bar| {
title_bar
.when(title_bar_settings.show_project_items, |title_bar| {
@ -190,11 +199,39 @@ impl Render for TitleBar {
.into_any_element(),
);
self.platform_titlebar.update(cx, |this, _| {
this.set_children(children);
});
if show_menus {
self.platform_titlebar.update(cx, |this, _| {
this.set_children(
self.application_menu
.clone()
.map(|menu| menu.into_any_element()),
);
});
self.platform_titlebar.clone().into_any_element()
let height = PlatformTitleBar::height(window);
let title_bar_color = self.platform_titlebar.update(cx, |platform_titlebar, cx| {
platform_titlebar.title_bar_color(window, cx)
});
v_flex()
.w_full()
.child(self.platform_titlebar.clone().into_any_element())
.child(
h_flex()
.bg(title_bar_color)
.h(height)
.pl_2()
.justify_between()
.w_full()
.children(children),
)
.into_any_element()
} else {
self.platform_titlebar.update(cx, |this, _| {
this.set_children(children);
});
self.platform_titlebar.clone().into_any_element()
}
}
}

View file

@ -11,6 +11,7 @@ pub struct TitleBarSettings {
pub show_branch_name: bool,
pub show_project_items: bool,
pub show_sign_in: bool,
pub show_menus: bool,
}
#[derive(Copy, Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
@ -39,6 +40,10 @@ pub struct TitleBarSettingsContent {
///
/// Default: true
pub show_sign_in: Option<bool>,
/// Whether to show the menus in the title bar.
///
/// Default: false
pub show_menus: Option<bool>,
}
impl Settings for TitleBarSettings {