Restore re-rendering of editors on buffer font size changes (#4064)

Max Brunsfeld created

Now that views are cached, we need to explicitly `.notify()` text
editors when the buffer font size changes.

* [x] Notify editors when settings change, or adjusting buffer font size
* [x] Figure out why non-focused editors still do not re-render when
adjusting buffer font size
* [x] Reset buffer font size adjustment when the size is updated in the
user's settings

Change summary

crates/editor/src/editor.rs  |  7 ++++++-
crates/gpui/src/app.rs       |  1 +
crates/gpui/src/window.rs    |  2 ++
crates/theme/src/settings.rs | 11 ++++++++++-
crates/theme/src/theme.rs    | 15 ++++++++++++---
5 files changed, 31 insertions(+), 5 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -97,7 +97,10 @@ use std::{
 pub use sum_tree::Bias;
 use sum_tree::TreeMap;
 use text::{OffsetUtf16, Rope};
-use theme::{ActiveTheme, PlayerColor, StatusColors, SyntaxTheme, ThemeColors, ThemeSettings};
+use theme::{
+    observe_buffer_font_size_adjustment, ActiveTheme, PlayerColor, StatusColors, SyntaxTheme,
+    ThemeColors, ThemeSettings,
+};
 use ui::{
     h_flex, prelude::*, ButtonSize, ButtonStyle, IconButton, IconName, IconSize, ListItem, Popover,
     Tooltip,
@@ -1812,6 +1815,7 @@ impl Editor {
                 cx.observe(&display_map, Self::on_display_map_changed),
                 cx.observe(&blink_manager, |_, _, cx| cx.notify()),
                 cx.observe_global::<SettingsStore>(Self::settings_changed),
+                observe_buffer_font_size_adjustment(cx, |_, cx| cx.notify()),
                 cx.observe_window_activation(|editor, cx| {
                     let active = cx.is_window_active();
                     editor.blink_manager.update(cx, |blink_manager, cx| {
@@ -8741,6 +8745,7 @@ impl Editor {
             )),
             cx,
         );
+        cx.notify();
     }
 
     pub fn set_searchable(&mut self, searchable: bool) {

crates/gpui/src/app.rs 🔗

@@ -843,6 +843,7 @@ impl AppContext {
     /// Remove the global of the given type from the app context. Does not notify global observers.
     pub fn remove_global<G: Any>(&mut self) -> G {
         let global_type = TypeId::of::<G>();
+        self.push_effect(Effect::NotifyGlobalObservers { global_type });
         *self
             .globals_by_type
             .remove(&global_type)

crates/gpui/src/window.rs 🔗

@@ -2761,6 +2761,8 @@ impl<'a, V: 'static> ViewContext<'a, V> {
             .rendered_frame
             .dispatch_tree
             .view_path(self.view.entity_id())
+            .into_iter()
+            .rev()
         {
             if !self.window.dirty_views.insert(view_id) {
                 break;

crates/theme/src/settings.rs 🔗

@@ -1,7 +1,9 @@
 use crate::one_themes::one_dark;
 use crate::{Theme, ThemeRegistry};
 use anyhow::Result;
-use gpui::{px, AppContext, Font, FontFeatures, FontStyle, FontWeight, Pixels};
+use gpui::{
+    px, AppContext, Font, FontFeatures, FontStyle, FontWeight, Pixels, Subscription, ViewContext,
+};
 use schemars::{
     gen::SchemaGenerator,
     schema::{InstanceType, Schema, SchemaObject},
@@ -80,6 +82,13 @@ impl ThemeSettings {
     }
 }
 
+pub fn observe_buffer_font_size_adjustment<V: 'static>(
+    cx: &mut ViewContext<V>,
+    f: impl 'static + Fn(&mut V, &mut ViewContext<V>),
+) -> Subscription {
+    cx.observe_global::<AdjustedBufferFontSize>(f)
+}
+
 pub fn adjusted_font_size(size: Pixels, cx: &mut AppContext) -> Pixels {
     if let Some(AdjustedBufferFontSize(adjusted_size)) = cx.try_global::<AdjustedBufferFontSize>() {
         let buffer_font_size = ThemeSettings::get_global(cx).buffer_font_size;

crates/theme/src/theme.rs 🔗

@@ -20,7 +20,7 @@ mod user_theme;
 
 use std::sync::Arc;
 
-use ::settings::Settings;
+use ::settings::{Settings, SettingsStore};
 pub use default_colors::*;
 pub use default_theme::*;
 pub use registry::*;
@@ -62,13 +62,22 @@ pub enum LoadThemes {
 
 pub fn init(themes_to_load: LoadThemes, cx: &mut AppContext) {
     cx.set_global(ThemeRegistry::default());
+    ThemeSettings::register(cx);
+
+    let mut prev_buffer_font_size = ThemeSettings::get_global(cx).buffer_font_size;
+    cx.observe_global::<SettingsStore>(move |cx| {
+        let buffer_font_size = ThemeSettings::get_global(cx).buffer_font_size;
+        if buffer_font_size != prev_buffer_font_size {
+            prev_buffer_font_size = buffer_font_size;
+            reset_font_size(cx);
+        }
+    })
+    .detach();
 
     match themes_to_load {
         LoadThemes::JustBase => (),
         LoadThemes::All => cx.global_mut::<ThemeRegistry>().load_user_themes(),
     }
-
-    ThemeSettings::register(cx);
 }
 
 pub trait ActiveTheme {