Reduce ghost emoji flash in title bar (#4804)

Fixes #4799

This PR attempts to reduce the flash caused by the ghost emoji in the
title bar when opening new windows.

## Changes:

- Initialize `SurfaceView.title` with empty string instead of ghost
emoji

- Simplify title computation logic in `TerminalView`

- Adding a 500ms fallback timer for "👻"

	- Canceling timer if title is set

## Current Status:

While these changes reduce the initial ghost emoji flash, there's still
a brief moment where a folder emoji appears alone in the title bar when
opening a new window. This suggests there might be a race condition or
timing issue with how the title is being set and updated.


https://github.com/user-attachments/assets/3688c9f3-1727-4379-b04d-0bd6ac105728

Would appreciate feedback on the remaining flash issue and suggestions
for further improvements.
This commit is contained in:
Mitchell Hashimoto
2025-01-10 13:46:45 -08:00
committed by GitHub
2 changed files with 23 additions and 11 deletions

View File

@ -10,7 +10,7 @@ protocol TerminalViewDelegate: AnyObject {
/// The title of the terminal should change.
func titleDidChange(to: String)
/// The URL of the pwd should change.
func pwdDidChange(to: URL?)
@ -56,15 +56,10 @@ struct TerminalView<ViewModel: TerminalViewModel>: View {
// The title for our window
private var title: String {
var title = "👻"
if let surfaceTitle = surfaceTitle {
if (surfaceTitle.count > 0) {
title = surfaceTitle
}
if let surfaceTitle, !surfaceTitle.isEmpty {
return surfaceTitle
}
return title
return "👻"
}
// The pwd of the focused surface as a URL
@ -72,7 +67,7 @@ struct TerminalView<ViewModel: TerminalViewModel>: View {
guard let surfacePwd, surfacePwd != "" else { return nil }
return URL(fileURLWithPath: surfacePwd)
}
var body: some View {
switch ghostty.readiness {
case .loading:

View File

@ -12,7 +12,14 @@ extension Ghostty {
// The current title of the surface as defined by the pty. This can be
// changed with escape codes. This is public because the callbacks go
// to the app level and it is set from there.
@Published private(set) var title: String = "👻"
@Published private(set) var title: String = "" {
didSet {
if !title.isEmpty {
titleFallbackTimer?.invalidate()
titleFallbackTimer = nil
}
}
}
// The current pwd of the surface as defined by the pty. This can be
// changed with escape codes.
@ -113,6 +120,9 @@ extension Ghostty {
// A small delay that is introduced before a title change to avoid flickers
private var titleChangeTimer: Timer?
// A timer to fallback to ghost emoji if no title is set within the grace period
private var titleFallbackTimer: Timer?
/// Event monitor (see individual events for why)
private var eventMonitor: Any? = nil
@ -139,6 +149,13 @@ extension Ghostty {
// can do SOMETHING.
super.init(frame: NSMakeRect(0, 0, 800, 600))
// Set a timer to show the ghost emoji after 500ms if no title is set
titleFallbackTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { [weak self] _ in
if let self = self, self.title.isEmpty {
self.title = "👻"
}
}
// Before we initialize the surface we want to register our notifications
// so there is no window where we can't receive them.
let center = NotificationCenter.default