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:
parent
6d26f107dd
commit
d5cc1cbaa9
7 changed files with 97 additions and 32 deletions
|
@ -362,7 +362,9 @@
|
||||||
// Whether to show user picture in the titlebar.
|
// Whether to show user picture in the titlebar.
|
||||||
"show_user_picture": true,
|
"show_user_picture": true,
|
||||||
// Whether to show the sign in button in the titlebar.
|
// Whether to show the sign in button in the titlebar.
|
||||||
"show_sign_in": true
|
"show_sign_in": true,
|
||||||
|
// Whether to show the menus in the titlebar.
|
||||||
|
"show_menus": false
|
||||||
},
|
},
|
||||||
// Scrollbar related settings
|
// Scrollbar related settings
|
||||||
"scrollbar": {
|
"scrollbar": {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use super::{
|
||||||
use crate::{
|
use crate::{
|
||||||
Action, AnyWindowHandle, BackgroundExecutor, ClipboardEntry, ClipboardItem, ClipboardString,
|
Action, AnyWindowHandle, BackgroundExecutor, ClipboardEntry, ClipboardItem, ClipboardString,
|
||||||
CursorStyle, ForegroundExecutor, Image, ImageFormat, KeyContext, Keymap, MacDispatcher,
|
CursorStyle, ForegroundExecutor, Image, ImageFormat, KeyContext, Keymap, MacDispatcher,
|
||||||
MacDisplay, MacWindow, Menu, MenuItem, PathPromptOptions, Platform, PlatformDisplay,
|
MacDisplay, MacWindow, Menu, MenuItem, OwnedMenu, PathPromptOptions, Platform, PlatformDisplay,
|
||||||
PlatformKeyboardLayout, PlatformTextSystem, PlatformWindow, Result, SemanticVersion, Task,
|
PlatformKeyboardLayout, PlatformTextSystem, PlatformWindow, Result, SemanticVersion, Task,
|
||||||
WindowAppearance, WindowParams, hash,
|
WindowAppearance, WindowParams, hash,
|
||||||
};
|
};
|
||||||
|
@ -170,6 +170,7 @@ pub(crate) struct MacPlatformState {
|
||||||
open_urls: Option<Box<dyn FnMut(Vec<String>)>>,
|
open_urls: Option<Box<dyn FnMut(Vec<String>)>>,
|
||||||
finish_launching: Option<Box<dyn FnOnce()>>,
|
finish_launching: Option<Box<dyn FnOnce()>>,
|
||||||
dock_menu: Option<id>,
|
dock_menu: Option<id>,
|
||||||
|
menus: Option<Vec<OwnedMenu>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MacPlatform {
|
impl Default for MacPlatform {
|
||||||
|
@ -207,6 +208,7 @@ impl MacPlatform {
|
||||||
finish_launching: None,
|
finish_launching: None,
|
||||||
dock_menu: None,
|
dock_menu: None,
|
||||||
on_keyboard_layout_change: None,
|
on_keyboard_layout_change: None,
|
||||||
|
menus: None,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +228,7 @@ impl MacPlatform {
|
||||||
|
|
||||||
unsafe fn create_menu_bar(
|
unsafe fn create_menu_bar(
|
||||||
&self,
|
&self,
|
||||||
menus: Vec<Menu>,
|
menus: &Vec<Menu>,
|
||||||
delegate: id,
|
delegate: id,
|
||||||
actions: &mut Vec<Box<dyn Action>>,
|
actions: &mut Vec<Box<dyn Action>>,
|
||||||
keymap: &Keymap,
|
keymap: &Keymap,
|
||||||
|
@ -241,7 +243,7 @@ impl MacPlatform {
|
||||||
menu.setTitle_(menu_title);
|
menu.setTitle_(menu_title);
|
||||||
menu.setDelegate_(delegate);
|
menu.setDelegate_(delegate);
|
||||||
|
|
||||||
for item_config in menu_config.items {
|
for item_config in &menu_config.items {
|
||||||
menu.addItem_(Self::create_menu_item(
|
menu.addItem_(Self::create_menu_item(
|
||||||
item_config,
|
item_config,
|
||||||
delegate,
|
delegate,
|
||||||
|
@ -277,7 +279,7 @@ impl MacPlatform {
|
||||||
dock_menu.setDelegate_(delegate);
|
dock_menu.setDelegate_(delegate);
|
||||||
for item_config in menu_items {
|
for item_config in menu_items {
|
||||||
dock_menu.addItem_(Self::create_menu_item(
|
dock_menu.addItem_(Self::create_menu_item(
|
||||||
item_config,
|
&item_config,
|
||||||
delegate,
|
delegate,
|
||||||
actions,
|
actions,
|
||||||
keymap,
|
keymap,
|
||||||
|
@ -289,7 +291,7 @@ impl MacPlatform {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_menu_item(
|
unsafe fn create_menu_item(
|
||||||
item: MenuItem,
|
item: &MenuItem,
|
||||||
delegate: id,
|
delegate: id,
|
||||||
actions: &mut Vec<Box<dyn Action>>,
|
actions: &mut Vec<Box<dyn Action>>,
|
||||||
keymap: &Keymap,
|
keymap: &Keymap,
|
||||||
|
@ -399,7 +401,7 @@ impl MacPlatform {
|
||||||
|
|
||||||
let tag = actions.len() as NSInteger;
|
let tag = actions.len() as NSInteger;
|
||||||
let _: () = msg_send![item, setTag: tag];
|
let _: () = msg_send![item, setTag: tag];
|
||||||
actions.push(action);
|
actions.push(action.boxed_clone());
|
||||||
item
|
item
|
||||||
}
|
}
|
||||||
MenuItem::Submenu(Menu { name, items }) => {
|
MenuItem::Submenu(Menu { name, items }) => {
|
||||||
|
@ -865,10 +867,15 @@ impl Platform for MacPlatform {
|
||||||
let app: id = msg_send![APP_CLASS, sharedApplication];
|
let app: id = msg_send![APP_CLASS, sharedApplication];
|
||||||
let mut state = self.0.lock();
|
let mut state = self.0.lock();
|
||||||
let actions = &mut state.menu_actions;
|
let actions = &mut state.menu_actions;
|
||||||
let menu = self.create_menu_bar(menus, NSWindow::delegate(app), actions, keymap);
|
let menu = self.create_menu_bar(&menus, NSWindow::delegate(app), actions, keymap);
|
||||||
drop(state);
|
drop(state);
|
||||||
app.setMainMenu_(menu);
|
app.setMainMenu_(menu);
|
||||||
}
|
}
|
||||||
|
self.0.lock().menus = Some(menus.into_iter().map(|menu| menu.owned()).collect());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_menus(&self) -> Option<Vec<OwnedMenu>> {
|
||||||
|
self.0.lock().menus.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_dock_menu(&self, menu: Vec<MenuItem>, keymap: &Keymap) {
|
fn set_dock_menu(&self, menu: Vec<MenuItem>, keymap: &Keymap) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use gpui::{Entity, OwnedMenu, OwnedMenuItem};
|
use gpui::{Entity, OwnedMenu, OwnedMenuItem};
|
||||||
|
use settings::Settings;
|
||||||
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
use gpui::{Action, actions};
|
use gpui::{Action, actions};
|
||||||
|
@ -11,6 +12,8 @@ use serde::Deserialize;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use ui::{ContextMenu, PopoverMenu, PopoverMenuHandle, Tooltip, prelude::*};
|
use ui::{ContextMenu, PopoverMenu, PopoverMenuHandle, Tooltip, prelude::*};
|
||||||
|
|
||||||
|
use crate::title_bar_settings::TitleBarSettings;
|
||||||
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
actions!(
|
actions!(
|
||||||
app_menu,
|
app_menu,
|
||||||
|
@ -242,15 +245,21 @@ impl ApplicationMenu {
|
||||||
cx.defer_in(window, move |_, window, cx| next_handle.show(window, cx));
|
cx.defer_in(window, move |_, window, cx| next_handle.show(window, cx));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn all_menus_shown(&self) -> bool {
|
pub fn all_menus_shown(&self, cx: &mut Context<Self>) -> bool {
|
||||||
self.entries.iter().any(|entry| entry.handle.is_deployed())
|
show_menus(cx)
|
||||||
|
|| self.entries.iter().any(|entry| entry.handle.is_deployed())
|
||||||
|| self.pending_menu_open.is_some()
|
|| 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 {
|
impl Render for ApplicationMenu {
|
||||||
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 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(pending_menu_open) = self.pending_menu_open.take() {
|
||||||
if let Some(entry) = self
|
if let Some(entry) = self
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyElement, Context, Decorations, InteractiveElement, IntoElement, MouseButton, ParentElement,
|
AnyElement, Context, Decorations, Hsla, InteractiveElement, IntoElement, MouseButton,
|
||||||
Pixels, StatefulInteractiveElement, Styled, Window, WindowControlArea, div, px,
|
ParentElement, Pixels, StatefulInteractiveElement, Styled, Window, WindowControlArea, div, px,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -37,6 +37,18 @@ impl PlatformTitleBar {
|
||||||
px(32.)
|
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)
|
pub fn set_children<T>(&mut self, children: T)
|
||||||
where
|
where
|
||||||
T: IntoIterator<Item = AnyElement>,
|
T: IntoIterator<Item = AnyElement>,
|
||||||
|
@ -50,15 +62,7 @@ impl Render for PlatformTitleBar {
|
||||||
let supported_controls = window.window_controls();
|
let supported_controls = window.window_controls();
|
||||||
let decorations = window.window_decorations();
|
let decorations = window.window_decorations();
|
||||||
let height = Self::height(window);
|
let height = Self::height(window);
|
||||||
let titlebar_color = if cfg!(any(target_os = "linux", target_os = "freebsd")) {
|
let titlebar_color = self.title_bar_color(window, cx);
|
||||||
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 close_action = Box::new(workspace::CloseWindow);
|
let close_action = Box::new(workspace::CloseWindow);
|
||||||
let children = mem::take(&mut self.children);
|
let children = mem::take(&mut self.children);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,10 @@ mod title_bar_settings;
|
||||||
#[cfg(feature = "stories")]
|
#[cfg(feature = "stories")]
|
||||||
mod 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"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
use crate::application_menu::{
|
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 {
|
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
let title_bar_settings = *TitleBarSettings::get_global(cx);
|
let title_bar_settings = *TitleBarSettings::get_global(cx);
|
||||||
|
|
||||||
|
let show_menus = show_menus(cx);
|
||||||
|
|
||||||
let mut children = Vec::new();
|
let mut children = Vec::new();
|
||||||
|
|
||||||
children.push(
|
children.push(
|
||||||
|
@ -142,10 +147,14 @@ impl Render for TitleBar {
|
||||||
let mut render_project_items = title_bar_settings.show_branch_name
|
let mut render_project_items = title_bar_settings.show_branch_name
|
||||||
|| title_bar_settings.show_project_items;
|
|| title_bar_settings.show_project_items;
|
||||||
title_bar
|
title_bar
|
||||||
.when_some(self.application_menu.clone(), |title_bar, menu| {
|
.when_some(
|
||||||
render_project_items &= !menu.read(cx).all_menus_shown();
|
self.application_menu.clone().filter(|_| !show_menus),
|
||||||
title_bar.child(menu)
|
|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| {
|
.when(render_project_items, |title_bar| {
|
||||||
title_bar
|
title_bar
|
||||||
.when(title_bar_settings.show_project_items, |title_bar| {
|
.when(title_bar_settings.show_project_items, |title_bar| {
|
||||||
|
@ -190,11 +199,39 @@ impl Render for TitleBar {
|
||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.platform_titlebar.update(cx, |this, _| {
|
if show_menus {
|
||||||
this.set_children(children);
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ pub struct TitleBarSettings {
|
||||||
pub show_branch_name: bool,
|
pub show_branch_name: bool,
|
||||||
pub show_project_items: bool,
|
pub show_project_items: bool,
|
||||||
pub show_sign_in: bool,
|
pub show_sign_in: bool,
|
||||||
|
pub show_menus: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
|
#[derive(Copy, Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
|
||||||
|
@ -39,6 +40,10 @@ pub struct TitleBarSettingsContent {
|
||||||
///
|
///
|
||||||
/// Default: true
|
/// Default: true
|
||||||
pub show_sign_in: Option<bool>,
|
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 {
|
impl Settings for TitleBarSettings {
|
||||||
|
|
|
@ -112,7 +112,8 @@ To disable this behavior use:
|
||||||
"show_project_items": true, // Show/hide project host and name
|
"show_project_items": true, // Show/hide project host and name
|
||||||
"show_onboarding_banner": true, // Show/hide onboarding banners
|
"show_onboarding_banner": true, // Show/hide onboarding banners
|
||||||
"show_user_picture": true, // Show/hide user avatar
|
"show_user_picture": true, // Show/hide user avatar
|
||||||
"show_sign_in": true // Show/hide sign-in button
|
"show_sign_in": true, // Show/hide sign-in button
|
||||||
|
"show_menus": false // Show/hide menus
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue