Revert "Add setting to show/hide title bar (#37428)" (#38756)

Conrad Irwin and Kirill Bulatov created

Closes https://github.com/zed-industries/zed/issues/38547

Release Notes:

- Reverted the ability to show/hide the titlebar. This caused rendering
bugs on
macOS, and we're preparing for the redesign which requires the toolbar
being present.

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>

Change summary

assets/settings/default.json               |   2 
crates/settings/src/settings_content.rs    |  12 --
crates/settings/src/settings_store.rs      | 118 ++++++++++-------------
crates/title_bar/src/title_bar.rs          |  49 ---------
crates/title_bar/src/title_bar_settings.rs |   3 
crates/workspace/src/workspace.rs          |   5 -
docs/src/configuring-zed.md                |   1 
docs/src/visual-customization.md           |   1 
8 files changed, 58 insertions(+), 133 deletions(-)

Detailed changes

assets/settings/default.json 🔗

@@ -391,8 +391,6 @@
   "use_system_window_tabs": false,
   // Titlebar related settings
   "title_bar": {
-    // When to show the title bar: "always" | "never" | "hide_in_full_screen".
-    "show": "always",
     // Whether to show the branch icon beside branch switcher in the titlebar.
     "show_branch_icon": false,
     // Whether to show the branch name button in the titlebar.

crates/settings/src/settings_content.rs 🔗

@@ -237,10 +237,6 @@ pub enum BaseKeymapContent {
 #[skip_serializing_none]
 #[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
 pub struct TitleBarSettingsContent {
-    /// Controls when the title bar is visible: "always" | "never" | "hide_in_full_screen".
-    ///
-    /// Default: "always"
-    pub show: Option<TitleBarVisibility>,
     /// Whether to show the branch icon beside branch switcher in the title bar.
     ///
     /// Default: false
@@ -271,14 +267,6 @@ pub struct TitleBarSettingsContent {
     pub show_menus: Option<bool>,
 }
 
-#[derive(Copy, Clone, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
-#[serde(rename_all = "snake_case")]
-pub enum TitleBarVisibility {
-    Always,
-    Never,
-    HideInFullScreen,
-}
-
 /// Configuration of audio in Zed.
 #[skip_serializing_none]
 #[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]

crates/settings/src/settings_store.rs 🔗

@@ -1022,7 +1022,7 @@ mod tests {
     use std::num::NonZeroU32;
 
     use crate::{
-        TitleBarSettingsContent, TitleBarVisibility, VsCodeSettingsSource, default_settings,
+        ClosePosition, ItemSettingsContent, VsCodeSettingsSource, default_settings,
         settings_content::LanguageSettingsContent, test_settings,
     };
 
@@ -1043,30 +1043,30 @@ mod tests {
     }
 
     #[derive(Debug, PartialEq)]
-    struct TitleBarSettings {
-        show: TitleBarVisibility,
-        show_branch_name: bool,
+    struct ItemSettings {
+        close_position: ClosePosition,
+        git_status: bool,
     }
 
-    impl Settings for TitleBarSettings {
+    impl Settings for ItemSettings {
         fn from_settings(content: &SettingsContent, _: &mut App) -> Self {
-            let content = content.title_bar.clone().unwrap();
-            TitleBarSettings {
-                show: content.show.unwrap(),
-                show_branch_name: content.show_branch_name.unwrap(),
+            let content = content.tabs.clone().unwrap();
+            ItemSettings {
+                close_position: content.close_position.unwrap(),
+                git_status: content.git_status.unwrap(),
             }
         }
 
         fn import_from_vscode(vscode: &VsCodeSettings, content: &mut SettingsContent) {
             let mut show = None;
 
-            vscode.enum_setting("window.titleBarStyle", &mut show, |value| match value {
-                "never" => Some(TitleBarVisibility::Never),
-                "always" => Some(TitleBarVisibility::Always),
-                _ => None,
-            });
+            vscode.bool_setting("workbench.editor.decorations.colors", &mut show);
             if let Some(show) = show {
-                content.title_bar.get_or_insert_default().show.replace(show);
+                content
+                    .tabs
+                    .get_or_insert_default()
+                    .git_status
+                    .replace(show);
             }
         }
     }
@@ -1103,7 +1103,7 @@ mod tests {
     fn test_settings_store_basic(cx: &mut App) {
         let mut store = SettingsStore::new(cx, &default_settings());
         store.register_setting::<AutoUpdateSetting>(cx);
-        store.register_setting::<TitleBarSettings>(cx);
+        store.register_setting::<ItemSettings>(cx);
         store.register_setting::<DefaultLanguageSettings>(cx);
 
         assert_eq!(
@@ -1111,16 +1111,16 @@ mod tests {
             &AutoUpdateSetting { auto_update: true }
         );
         assert_eq!(
-            store.get::<TitleBarSettings>(None).show,
-            TitleBarVisibility::Always
+            store.get::<ItemSettings>(None).close_position,
+            ClosePosition::Right
         );
 
         store
             .set_user_settings(
                 r#"{
                     "auto_update": false,
-                    "title_bar": {
-                      "show": "never"
+                    "tabs": {
+                      "close_position": "left"
                     }
                 }"#,
                 cx,
@@ -1132,8 +1132,8 @@ mod tests {
             &AutoUpdateSetting { auto_update: false }
         );
         assert_eq!(
-            store.get::<TitleBarSettings>(None).show,
-            TitleBarVisibility::Never
+            store.get::<ItemSettings>(None).close_position,
+            ClosePosition::Left
         );
 
         store
@@ -1160,7 +1160,7 @@ mod tests {
                 WorktreeId::from_usize(1),
                 Path::new("/root2").into(),
                 LocalSettingsKind::Settings,
-                Some(r#"{ "tab_size": 9, "title_bar": { "show_branch_name": false } }"#),
+                Some(r#"{ "tab_size": 9, "auto_update": true}"#),
                 cx,
             )
             .unwrap();
@@ -1196,14 +1196,11 @@ mod tests {
             }
         );
         assert_eq!(
-            store.get::<TitleBarSettings>(Some(SettingsLocation {
+            store.get::<AutoUpdateSetting>(Some(SettingsLocation {
                 worktree_id: WorktreeId::from_usize(1),
                 path: Path::new("/root2/something")
             })),
-            &TitleBarSettings {
-                show: TitleBarVisibility::Never,
-                show_branch_name: true,
-            }
+            &AutoUpdateSetting { auto_update: false }
         );
     }
 
@@ -1214,16 +1211,11 @@ mod tests {
             .set_user_settings(r#"{ "auto_update": false }"#, cx)
             .unwrap();
         store.register_setting::<AutoUpdateSetting>(cx);
-        store.register_setting::<TitleBarSettings>(cx);
 
         assert_eq!(
             store.get::<AutoUpdateSetting>(None),
             &AutoUpdateSetting { auto_update: false }
         );
-        assert_eq!(
-            store.get::<TitleBarSettings>(None).show,
-            TitleBarVisibility::Always,
-        );
     }
 
     #[track_caller]
@@ -1346,14 +1338,14 @@ mod tests {
         check_settings_update(
             &mut store,
             r#"{
-                "title_bar":   { "show": "always", "name": "Max"  }
+                "tabs":   { "close_position": "left", "name": "Max"  }
                 }"#
             .unindent(),
             |settings| {
-                settings.title_bar.as_mut().unwrap().show = Some(TitleBarVisibility::Never);
+                settings.tabs.as_mut().unwrap().close_position = Some(ClosePosition::Left);
             },
             r#"{
-                "title_bar":   { "show": "never", "name": "Max"  }
+                "tabs":   { "close_position": "left", "name": "Max"  }
                 }"#
             .unindent(),
             cx,
@@ -1372,13 +1364,13 @@ mod tests {
         check_settings_update(
             &mut store,
             r#"{
-                "title_bar": {}
+                "tabs": {}
             }"#
             .unindent(),
-            |settings| settings.title_bar.as_mut().unwrap().show_menus = Some(true),
+            |settings| settings.tabs.as_mut().unwrap().close_position = Some(ClosePosition::Left),
             r#"{
-                "title_bar": {
-                    "show_menus": true
+                "tabs": {
+                    "close_position": "left"
                 }
             }"#
             .unindent(),
@@ -1390,14 +1382,14 @@ mod tests {
             &mut store,
             r#""#.unindent(),
             |settings| {
-                settings.title_bar = Some(TitleBarSettingsContent {
-                    show_branch_name: Some(true),
+                settings.tabs = Some(ItemSettingsContent {
+                    git_status: Some(true),
                     ..Default::default()
                 })
             },
             r#"{
-                "title_bar": {
-                    "show_branch_name": true
+                "tabs": {
+                    "git_status": true
                 }
             }
             "#
@@ -1427,7 +1419,7 @@ mod tests {
     fn test_vscode_import(cx: &mut App) {
         let mut store = SettingsStore::new(cx, &test_settings());
         store.register_setting::<DefaultLanguageSettings>(cx);
-        store.register_setting::<TitleBarSettings>(cx);
+        store.register_setting::<ItemSettings>(cx);
         store.register_setting::<AutoUpdateSetting>(cx);
 
         // create settings that werent present
@@ -1487,16 +1479,13 @@ mod tests {
         check_vscode_import(
             &mut store,
             r#"{
-                "title_bar": {
-                "show": "always"
-                }
             }
             "#
             .unindent(),
-            r#"{ "window.titleBarStyle": "never" }"#.to_owned(),
+            r#"{ "workbench.editor.decorations.colors": true }"#.to_owned(),
             r#"{
-                "title_bar": {
-                "show": "never"
+                "tabs": {
+                    "git_status": true
                 }
             }
             "#
@@ -1550,14 +1539,15 @@ mod tests {
     #[gpui::test]
     fn test_global_settings(cx: &mut App) {
         let mut store = SettingsStore::new(cx, &test_settings());
-        store.register_setting::<TitleBarSettings>(cx);
+        store.register_setting::<ItemSettings>(cx);
 
         // Set global settings - these should override defaults but not user settings
         store
             .set_global_settings(
                 r#"{
-                    "title_bar": {
-                        "show": "never",
+                    "tabs": {
+                        "close_position": "right",
+                        "git_status": true,
                     }
                 }"#,
                 cx,
@@ -1566,10 +1556,10 @@ mod tests {
 
         // Before user settings, global settings should apply
         assert_eq!(
-            store.get::<TitleBarSettings>(None),
-            &TitleBarSettings {
-                show: TitleBarVisibility::Never,
-                show_branch_name: true,
+            store.get::<ItemSettings>(None),
+            &ItemSettings {
+                close_position: ClosePosition::Right,
+                git_status: true,
             }
         );
 
@@ -1577,8 +1567,8 @@ mod tests {
         store
             .set_user_settings(
                 r#"{
-                    "title_bar": {
-                        "show": "always"
+                    "tabs": {
+                        "close_position": "left"
                     }
                 }"#,
                 cx,
@@ -1587,10 +1577,10 @@ mod tests {
 
         // User settings should override global settings
         assert_eq!(
-            store.get::<TitleBarSettings>(None),
-            &TitleBarSettings {
-                show: TitleBarVisibility::Always,
-                show_branch_name: true, // Staff from global settings
+            store.get::<ItemSettings>(None),
+            &ItemSettings {
+                close_position: ClosePosition::Left,
+                git_status: true, // Staff from global settings
             }
         );
     }

crates/title_bar/src/title_bar.rs 🔗

@@ -4,7 +4,7 @@ mod onboarding_banner;
 pub mod platform_title_bar;
 mod platforms;
 mod system_window_tabs;
-pub mod title_bar_settings;
+mod title_bar_settings;
 
 #[cfg(feature = "stories")]
 mod stories;
@@ -35,7 +35,7 @@ use remote::RemoteConnectionOptions;
 use settings::{Settings, SettingsLocation};
 use std::{path::Path, sync::Arc};
 use theme::ActiveTheme;
-use title_bar_settings::{TitleBarSettings, TitleBarVisibility};
+use title_bar_settings::TitleBarSettings;
 use ui::{
     Avatar, Button, ButtonLike, ButtonStyle, Chip, ContextMenu, Icon, IconName, IconSize,
     IconWithIndicator, Indicator, PopoverMenu, PopoverMenuHandle, Tooltip, h_flex, prelude::*,
@@ -73,49 +73,8 @@ pub fn init(cx: &mut App) {
         let Some(window) = window else {
             return;
         };
-        let should_show = match TitleBarSettings::get_global(cx).show {
-            TitleBarVisibility::Always => true,
-            TitleBarVisibility::Never => false,
-            TitleBarVisibility::HideInFullScreen => !window.is_fullscreen(),
-        };
-        if should_show {
-            let item = cx.new(|cx| TitleBar::new("title-bar", workspace, window, cx));
-            workspace.set_titlebar_item(item.into(), window, cx);
-        }
-
-        cx.observe_global_in::<settings::SettingsStore>(window, |workspace, window, cx| {
-            let should_show = match TitleBarSettings::get_global(cx).show {
-                TitleBarVisibility::Always => true,
-                TitleBarVisibility::Never => false,
-                TitleBarVisibility::HideInFullScreen => !window.is_fullscreen(),
-            };
-            if should_show {
-                if workspace.titlebar_item().is_none() {
-                    let item = cx.new(|cx| TitleBar::new("title-bar", workspace, window, cx));
-                    workspace.set_titlebar_item(item.into(), window, cx);
-                }
-            } else {
-                workspace.clear_titlebar_item(window, cx);
-            }
-        })
-        .detach();
-
-        cx.observe_window_bounds(window, |workspace, window, cx| {
-            let should_show = match TitleBarSettings::get_global(cx).show {
-                TitleBarVisibility::Always => true,
-                TitleBarVisibility::Never => false,
-                TitleBarVisibility::HideInFullScreen => !window.is_fullscreen(),
-            };
-            if should_show {
-                if workspace.titlebar_item().is_none() {
-                    let item = cx.new(|cx| TitleBar::new("title-bar", workspace, window, cx));
-                    workspace.set_titlebar_item(item.into(), window, cx);
-                }
-            } else {
-                workspace.clear_titlebar_item(window, cx);
-            }
-        })
-        .detach();
+        let item = cx.new(|cx| TitleBar::new("title-bar", workspace, window, cx));
+        workspace.set_titlebar_item(item.into(), window, cx);
 
         #[cfg(not(target_os = "macos"))]
         workspace.register_action(|workspace, action: &OpenApplicationMenu, window, cx| {

crates/title_bar/src/title_bar_settings.rs 🔗

@@ -1,10 +1,8 @@
-pub use settings::TitleBarVisibility;
 use settings::{Settings, SettingsContent};
 use ui::App;
 
 #[derive(Copy, Clone, Debug)]
 pub struct TitleBarSettings {
-    pub show: TitleBarVisibility,
     pub show_branch_icon: bool,
     pub show_onboarding_banner: bool,
     pub show_user_picture: bool,
@@ -18,7 +16,6 @@ impl Settings for TitleBarSettings {
     fn from_settings(s: &SettingsContent, _: &mut App) -> Self {
         let content = s.title_bar.clone().unwrap();
         TitleBarSettings {
-            show: content.show.unwrap(),
             show_branch_icon: content.show_branch_icon.unwrap(),
             show_onboarding_banner: content.show_onboarding_banner.unwrap(),
             show_user_picture: content.show_user_picture.unwrap(),

crates/workspace/src/workspace.rs 🔗

@@ -2040,11 +2040,6 @@ impl Workspace {
         cx.notify();
     }
 
-    pub fn clear_titlebar_item(&mut self, _: &mut Window, cx: &mut Context<Self>) {
-        self.titlebar_item = None;
-        cx.notify();
-    }
-
     pub fn set_prompt_for_new_path(&mut self, prompt: PromptForNewPath) {
         self.on_prompt_for_new_path = Some(prompt)
     }

docs/src/configuring-zed.md 🔗

@@ -4140,7 +4140,6 @@ Run the {#action theme_selector::Toggle} action in the command palette to see a
 
 ```json
 "title_bar": {
-  "show": "always",
   "show_branch_icon": false,
   "show_branch_name": true,
   "show_project_items": true,

docs/src/visual-customization.md 🔗

@@ -108,7 +108,6 @@ To disable this behavior use:
 ```json
   // Control which items are shown/hidden in the title bar
   "title_bar": {
-    "show": "always",               // When to show: always | never | hide_in_full_screen
     "show_branch_icon": false,      // Show/hide branch icon beside branch switcher
     "show_branch_name": true,       // Show/hide branch name
     "show_project_items": true,     // Show/hide project host and name