fix(theme): avoid redundant GTK font resets
Skip resetting gtk-font-name when the effective scaled font has not changed. This keeps repeated theme reapplies from doing unnecessary display-wide font work.
- commit
- a5abb190af008a52ec412389d1c990a483144832
- author
- brice · · 2026-04-08 05:33 UTC
- parent
- c8834e5
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +15 -1
M internal/ui/theme/manager.go +9 -1
| @@ -23,6 +23,7 @@ type Manager struct { | |||
| 23 | 23 | fonts FontConfig | |
| 24 | 24 | modeColors ModeColors // Modal mode indicator colors | |
| 25 | 25 | cssProvider *gtk.CssProvider | |
| 26 | + | appliedFont string | |
| 26 | 27 | colorResolver port.ColorSchemeResolver // Resolver for dynamic detection | |
| 27 | 28 | } | |
| 28 | 29 | ||
| @@ -169,6 +170,10 @@ func formatGTKFontName(family string, uiScale float64) string { | |||
| 169 | 170 | return fmt.Sprintf("%s %d", family, size) | |
| 170 | 171 | } | |
| 171 | 172 | ||
| 173 | + | func shouldApplyGTKFontName(current, next string) bool { | |
| 174 | + | return next != "" && next != current | |
| 175 | + | } | |
| 176 | + | ||
| 172 | 177 | // ApplyToDisplay loads the theme CSS into the display. | |
| 173 | 178 | func (m *Manager) ApplyToDisplay(ctx context.Context, display *gdk.Display) { | |
| 174 | 179 | log := logging.FromContext(ctx) | |
| @@ -186,8 +191,11 @@ func (m *Manager) ApplyToDisplay(ctx context.Context, display *gdk.Display) { | |||
| 186 | 191 | settings := gtk.SettingsGetForDisplay(display) | |
| 187 | 192 | if settings == nil { | |
| 188 | 193 | log.Warn().Msg("cannot apply theme font scaling: settings unavailable") | |
| 189 | - | } else { | |
| 194 | + | } else if shouldApplyGTKFontName(m.appliedFont, fontName) { | |
| 190 | 195 | settings.SetPropertyGtkFontName(fontName) | |
| 196 | + | m.appliedFont = fontName | |
| 197 | + | settings.Unref() | |
| 198 | + | } else { | |
| 191 | 199 | settings.Unref() | |
| 192 | 200 | } | |
| 193 | 201 | ||
| @@ -23,6 +23,7 @@ type Manager struct { | |||||
| 23 | fonts FontConfig | 23 | fonts FontConfig | ||
| 24 | modeColors ModeColors // Modal mode indicator colors | 24 | modeColors ModeColors // Modal mode indicator colors | ||
| 25 | cssProvider *gtk.CssProvider | 25 | cssProvider *gtk.CssProvider | ||
| 26 | + | appliedFont string | |||
| 26 | colorResolver port.ColorSchemeResolver // Resolver for dynamic detection | 27 | colorResolver port.ColorSchemeResolver // Resolver for dynamic detection | ||
| 27 | } | 28 | } | ||
| 28 | 29 | ||||
| @@ -169,6 +170,10 @@ func formatGTKFontName(family string, uiScale float64) string { | |||||
| 169 | return fmt.Sprintf("%s %d", family, size) | 170 | return fmt.Sprintf("%s %d", family, size) | ||
| 170 | } | 171 | } | ||
| 171 | 172 | ||||
| 173 | + | func shouldApplyGTKFontName(current, next string) bool { | |||
| 174 | + | return next != "" && next != current | |||
| 175 | + | } | |||
| 176 | + | ||||
| 172 | // ApplyToDisplay loads the theme CSS into the display. | 177 | // ApplyToDisplay loads the theme CSS into the display. | ||
| 173 | func (m *Manager) ApplyToDisplay(ctx context.Context, display *gdk.Display) { | 178 | func (m *Manager) ApplyToDisplay(ctx context.Context, display *gdk.Display) { | ||
| 174 | log := logging.FromContext(ctx) | 179 | log := logging.FromContext(ctx) | ||
| @@ -186,8 +191,11 @@ func (m *Manager) ApplyToDisplay(ctx context.Context, display *gdk.Display) { | |||||
| 186 | settings := gtk.SettingsGetForDisplay(display) | 191 | settings := gtk.SettingsGetForDisplay(display) | ||
| 187 | if settings == nil { | 192 | if settings == nil { | ||
| 188 | log.Warn().Msg("cannot apply theme font scaling: settings unavailable") | 193 | log.Warn().Msg("cannot apply theme font scaling: settings unavailable") | ||
| 189 | - | } else { | 194 | + | } else if shouldApplyGTKFontName(m.appliedFont, fontName) { |
| 190 | settings.SetPropertyGtkFontName(fontName) | 195 | settings.SetPropertyGtkFontName(fontName) | ||
| 196 | + | m.appliedFont = fontName | |||
| 197 | + | settings.Unref() | |||
| 198 | + | } else { | |||
| 191 | settings.Unref() | 199 | settings.Unref() | ||
| 192 | } | 200 | } | ||
| 193 | 201 | ||||
M internal/ui/theme/manager_test.go +6 -0
| @@ -322,3 +322,9 @@ func TestFormatGTKFontName_DefaultsScaleAndRoundsToNearestPoint(t *testing.T) { | |||
| 322 | 322 | assert.Equal(t, "Inter 11", formatGTKFontName("Inter", 0)) | |
| 323 | 323 | assert.Equal(t, "Inter 12", formatGTKFontName("Inter", 1.05)) | |
| 324 | 324 | } | |
| 325 | + | ||
| 326 | + | func TestShouldApplyGTKFontName(t *testing.T) { | |
| 327 | + | assert.True(t, shouldApplyGTKFontName("", "Fira Sans 14")) | |
| 328 | + | assert.False(t, shouldApplyGTKFontName("Fira Sans 14", "Fira Sans 14")) | |
| 329 | + | assert.False(t, shouldApplyGTKFontName("Fira Sans 14", "")) | |
| 330 | + | } | |
| @@ -322,3 +322,9 @@ func TestFormatGTKFontName_DefaultsScaleAndRoundsToNearestPoint(t *testing.T) { | |||||
| 322 | assert.Equal(t, "Inter 11", formatGTKFontName("Inter", 0)) | 322 | assert.Equal(t, "Inter 11", formatGTKFontName("Inter", 0)) | ||
| 323 | assert.Equal(t, "Inter 12", formatGTKFontName("Inter", 1.05)) | 323 | assert.Equal(t, "Inter 12", formatGTKFontName("Inter", 1.05)) | ||
| 324 | } | 324 | } | ||
| 325 | + | ||||
| 326 | + | func TestShouldApplyGTKFontName(t *testing.T) { | |||
| 327 | + | assert.True(t, shouldApplyGTKFontName("", "Fira Sans 14")) | |||
| 328 | + | assert.False(t, shouldApplyGTKFontName("Fira Sans 14", "Fira Sans 14")) | |||
| 329 | + | assert.False(t, shouldApplyGTKFontName("Fira Sans 14", "")) | |||
| 330 | + | } | |||