@@ -32,9 +32,9 @@ use crate::settings::{
3232 EnforceMinimumContrast , FocusPaneOnHover , FontSettings , FontSettingsChangedEvent , InputBoxType ,
3333 InputModeSettings , InputModeState , MarkdownHeadingH1Scale , MarkdownHeadingH2Scale ,
3434 MarkdownHeadingH3Scale , MarkdownHeadingH4Scale , MarkdownHeadingH5Scale , MarkdownHeadingH6Scale ,
35- MonospaceFontName , PaneSettings , ShouldDimInactivePanes , ThemeSettings , UiFontName ,
36- UseSystemTheme , DEFAULT_MONOSPACE_FONT_NAME , MARKDOWN_HEADING_SCALE_MAX ,
37- MARKDOWN_HEADING_SCALE_MIN , UI_FONT_SIZE_MAX , UI_FONT_SIZE_MIN ,
35+ MonospaceFallbackFontName , MonospaceFontName , PaneSettings , ShouldDimInactivePanes ,
36+ ThemeSettings , UiFontName , UseSystemTheme , DEFAULT_MONOSPACE_FONT_NAME ,
37+ MARKDOWN_HEADING_SCALE_MAX , MARKDOWN_HEADING_SCALE_MIN , UI_FONT_SIZE_MAX , UI_FONT_SIZE_MIN ,
3838} ;
3939use crate :: settings:: { CursorDisplayType , GPUSettings , InputSettings , InputSettingsChangedEvent } ;
4040use crate :: terminal:: block_list_viewport:: InputMode ;
@@ -139,6 +139,17 @@ fn default_font_label(is_ai_font: bool) -> String {
139139 }
140140}
141141
142+ fn fallback_font_dropdown_should_include_font (
143+ name : & str ,
144+ font_type : FontType ,
145+ view_font_type : FontType ,
146+ selected_font_name : & str ,
147+ ) -> bool {
148+ matches ! ( view_font_type, FontType :: Any )
149+ || matches ! ( font_type, FontType :: Monospace )
150+ || name == selected_font_name
151+ }
152+
142153pub fn init_actions_from_parent_view < T : Action + Clone > (
143154 app : & mut AppContext ,
144155 context : & ContextPredicate ,
@@ -440,6 +451,7 @@ pub enum AppearancePageAction {
440451 OpacitySliderDragged ( f32 ) ,
441452 BlurSliderDragged ( f32 ) ,
442453 SetFontFamily ( String ) ,
454+ SetFallbackFontFamily ( String ) ,
443455 SetAIFontFamily ( String ) ,
444456 SetUIFontFamily ( String ) ,
445457 SetUIFontSize ,
@@ -514,6 +526,7 @@ pub struct AppearanceSettingsPageView {
514526 opacity_state : SliderStateHandle ,
515527 blur_state : SliderStateHandle ,
516528 font_family_dropdown : ViewHandle < FilterableDropdown < AppearancePageAction > > ,
529+ fallback_font_family_dropdown : ViewHandle < FilterableDropdown < AppearancePageAction > > ,
517530 font_weight_dropdown : ViewHandle < Dropdown < AppearancePageAction > > ,
518531 #[ allow( dead_code) ]
519532 thin_strokes_dropdown : ViewHandle < Dropdown < AppearancePageAction > > ,
@@ -575,6 +588,7 @@ impl TypedActionView for AppearanceSettingsPageView {
575588 SetOpacity ( value) => self . set_opacity ( * value, true , ctx) ,
576589 SetBlur ( value) => self . set_blur ( * value, true , ctx) ,
577590 SetFontFamily ( name) => self . set_font_family ( name, ctx) ,
591+ SetFallbackFontFamily ( name) => self . set_fallback_font_family ( name, ctx) ,
578592 SetAIFontFamily ( name) => {
579593 self . set_ai_font_family ( name, ctx) ;
580594 FontSettings :: handle ( ctx) . update ( ctx, |font_settings, ctx| {
@@ -1106,6 +1120,16 @@ impl AppearanceSettingsPageView {
11061120 dropdown
11071121 } ) ;
11081122
1123+ let fallback_font_family_dropdown = ctx. add_typed_action_view ( |ctx| {
1124+ let mut dropdown = FilterableDropdown :: new ( ctx) ;
1125+ dropdown. set_top_bar_max_width ( FONT_FAMILY_DROPDOWN_WIDTH ) ;
1126+ dropdown. set_menu_width ( FONT_FAMILY_DROPDOWN_WIDTH , ctx) ;
1127+
1128+ dropdown. add_items ( vec ! [ Self :: default_fallback_font_item( ) ] , ctx) ;
1129+ dropdown. set_selected_by_index ( 0 , ctx) ;
1130+ dropdown
1131+ } ) ;
1132+
11091133 let ai_font_family_dropdown = ctx. add_typed_action_view ( |ctx| {
11101134 let mut dropdown = FilterableDropdown :: new ( ctx) ;
11111135 dropdown. set_top_bar_max_width ( FONT_FAMILY_DROPDOWN_WIDTH ) ;
@@ -1365,6 +1389,7 @@ impl AppearanceSettingsPageView {
13651389 opacity_state : Default :: default ( ) ,
13661390 blur_state : Default :: default ( ) ,
13671391 font_family_dropdown,
1392+ fallback_font_family_dropdown,
13681393 font_weight_dropdown,
13691394 thin_strokes_dropdown,
13701395 input_mode_dropdown,
@@ -1612,6 +1637,9 @@ impl AppearanceSettingsPageView {
16121637 AppearanceEvent :: MonospaceFontFamilyChanged { .. } => {
16131638 self . update_font_dropdown ( ctx) ;
16141639 }
1640+ AppearanceEvent :: TerminalFallbackFontFamilyChanged { .. } => {
1641+ self . update_font_dropdown ( ctx) ;
1642+ }
16151643 AppearanceEvent :: MonospaceFontSizeChanged { .. } => {
16161644 let font_size = handle. as_ref ( ctx) . monospace_font_size ( ) ;
16171645 self . font_size_editor . update ( ctx, move |editor, ctx| {
@@ -1722,6 +1750,13 @@ impl AppearanceSettingsPageView {
17221750 initial_dropdown_item
17231751 }
17241752
1753+ fn default_fallback_font_item ( ) -> DropdownItem < AppearancePageAction > {
1754+ DropdownItem :: new (
1755+ crate :: t!( "settings-appearance-font-fallback-system" ) ,
1756+ AppearancePageAction :: SetFallbackFontFamily ( MonospaceFallbackFontName :: default_value ( ) ) ,
1757+ )
1758+ }
1759+
17251760 fn input_mode_dropdown_item_label ( val : InputMode ) -> String {
17261761 match val {
17271762 InputMode :: PinnedToBottom => crate :: t!( "settings-appearance-input-mode-pinned-bottom" ) ,
@@ -2219,6 +2254,7 @@ impl AppearanceSettingsPageView {
22192254
22202255 fn update_font_dropdown ( & mut self , ctx : & mut ViewContext < Self > ) {
22212256 let monospace_font_family = Appearance :: as_ref ( ctx) . monospace_font_family ( ) ;
2257+ let fallback_font_family = Appearance :: as_ref ( ctx) . terminal_fallback_font_family ( ) ;
22222258 let ai_font_family = Appearance :: as_ref ( ctx) . ai_font_family ( ) ;
22232259 let ui_font_family = Appearance :: as_ref ( ctx) . ui_font_family ( ) ;
22242260
@@ -2290,6 +2326,69 @@ impl AppearanceSettingsPageView {
22902326 }
22912327 } ) ;
22922328
2329+ self . fallback_font_family_dropdown
2330+ . update ( ctx, |dropdown, ctx| {
2331+ let font_name = FontSettings :: as_ref ( ctx)
2332+ . monospace_fallback_font_name
2333+ . value ( )
2334+ . clone ( ) ;
2335+
2336+ if let Some ( fallback_font_family) = fallback_font_family {
2337+ if let Some ( loaded_font_name) = ctx
2338+ . font_cache ( )
2339+ . load_family_name_from_id ( fallback_font_family)
2340+ {
2341+ self . available_families
2342+ . entry ( loaded_font_name)
2343+ . and_modify ( |entry| entry. 0 = Some ( fallback_font_family) )
2344+ . or_insert ( ( Some ( fallback_font_family) , FontType :: Monospace ) ) ;
2345+ }
2346+ }
2347+
2348+ let mut items = self
2349+ . available_families
2350+ . iter ( )
2351+ . filter_map ( |( name, ( family, font_type) ) | {
2352+ let include_in_dropdown = fallback_font_dropdown_should_include_font (
2353+ name,
2354+ * font_type,
2355+ self . view_font_type ,
2356+ & font_name,
2357+ ) ;
2358+ if include_in_dropdown {
2359+ let name_move = name. clone ( ) ;
2360+ let mut dropdown = DropdownItem :: new (
2361+ name,
2362+ AppearancePageAction :: SetFallbackFontFamily ( name_move) ,
2363+ ) ;
2364+
2365+ if cfg ! ( not( any( target_os = "linux" , target_os = "freebsd" ) ) ) {
2366+ if let Some ( family_id) = family {
2367+ dropdown = dropdown. with_font_override ( * family_id)
2368+ }
2369+ }
2370+
2371+ Some ( dropdown)
2372+ } else {
2373+ None
2374+ }
2375+ } )
2376+ . collect :: < Vec < _ > > ( ) ;
2377+
2378+ items. sort_by ( |a, b| a. display_text . cmp ( & b. display_text ) ) ;
2379+ items. insert ( 0 , Self :: default_fallback_font_item ( ) ) ;
2380+ dropdown. set_items ( items, ctx) ;
2381+
2382+ if font_name. is_empty ( ) {
2383+ dropdown. set_selected_by_name (
2384+ crate :: t!( "settings-appearance-font-fallback-system" ) ,
2385+ ctx,
2386+ ) ;
2387+ } else {
2388+ dropdown. set_selected_by_name ( & font_name, ctx) ;
2389+ }
2390+ } ) ;
2391+
22932392 self . ai_font_family_dropdown . update ( ctx, |dropdown, ctx| {
22942393 // Get the family name of the current agent mode font.
22952394 // We check the font_cache for the current agent mode family.
@@ -2441,6 +2540,14 @@ impl AppearanceSettingsPageView {
24412540 } ) ;
24422541 }
24432542
2543+ pub fn set_fallback_font_family ( & mut self , name : & str , ctx : & mut ViewContext < Self > ) {
2544+ FontSettings :: handle ( ctx) . update ( ctx, |font_settings, ctx| {
2545+ report_if_error ! ( font_settings
2546+ . monospace_fallback_font_name
2547+ . set_value( name. to_string( ) , ctx) ) ;
2548+ } ) ;
2549+ }
2550+
24442551 pub fn toggle_match_ai_font_to_terminal_font ( & mut self , ctx : & mut ViewContext < Self > ) {
24452552 FontSettings :: handle ( ctx) . update ( ctx, |font_settings, ctx| {
24462553 report_if_error ! ( font_settings
@@ -4480,7 +4587,7 @@ impl SettingsWidget for TerminalFontWidget {
44804587 type View = AppearanceSettingsPageView ;
44814588
44824589 fn search_terms ( & self ) -> & str {
4483- "text terminal font family font size line height monospace"
4590+ "text terminal font family fallback font size line height monospace"
44844591 }
44854592
44864593 fn render (
@@ -4512,6 +4619,24 @@ impl SettingsWidget for TerminalFontWidget {
45124619 . with_margin_bottom ( 10. )
45134620 . finish ( ) ,
45144621 ) ;
4622+ terminal_font. add_child ( render_body_item_label :: < AppearancePageAction > (
4623+ crate :: t!( "settings-appearance-font-terminal-fallback-label" ) ,
4624+ None ,
4625+ None ,
4626+ LocalOnlyIconState :: for_setting (
4627+ MonospaceFallbackFontName :: storage_key ( ) ,
4628+ MonospaceFallbackFontName :: sync_to_cloud ( ) ,
4629+ & mut view. local_only_icon_tooltip_states . borrow_mut ( ) ,
4630+ app,
4631+ ) ,
4632+ ToggleState :: Enabled ,
4633+ appearance,
4634+ ) ) ;
4635+ terminal_font. add_child (
4636+ Container :: new ( ChildView :: new ( & view. fallback_font_family_dropdown ) . finish ( ) )
4637+ . with_margin_bottom ( 10. )
4638+ . finish ( ) ,
4639+ ) ;
45154640 terminal_font. add_child (
45164641 Container :: new (
45174642 Flex :: row ( )
@@ -5987,3 +6112,7 @@ impl From<ViewHandle<AppearanceSettingsPageView>> for SettingsPageViewHandle {
59876112 SettingsPageViewHandle :: Appearance ( view_handle)
59886113 }
59896114}
6115+
6116+ #[ cfg( test) ]
6117+ #[ path = "appearance_page_tests.rs" ]
6118+ mod tests;
0 commit comments