Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions rootshell/App/UIApplication+CommandFallback.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ extension UIApplication {

@MainActor
private func ghostty_postNotification(_ name: Notification.Name, userInfo: [String: Any] = [:]) {
// App-wide chords arrive here when TerminalView is out of the responder
// chain, so its `pressesBegan` hook never sees them.
noteAlwaysOnDisplayInteraction()

var info = userInfo
if let sceneID = ghostty_activeWindowSceneSessionID() {
info[GhosttyCommandRouting.windowSceneSessionIDKey] = sceneID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ struct WindowSettingsView: View {

/// Whether the "Display" Section has anything to show. On Catalyst the
/// brightness controls are its only rows, so the whole Section is hidden
/// pre-26; on iOS the Full Screen / Always On Display toggles keep it alive.
/// pre-26; on iOS the Full Screen toggle and Always On Display slider keep it
/// alive.
private var showDisplaySection: Bool {
#if targetEnvironment(macCatalyst)
return brightnessBoostAvailable
Expand Down Expand Up @@ -469,8 +470,8 @@ struct WindowSettingsView: View {
}

// EDR is meaningless on visionOS, so the Display section (and its HDR
// brightness boost) is excluded there. The Full Screen / Always On
// Display / home-indicator toggles are iOS-only concepts, so they stay
// brightness boost) is excluded there. The Full Screen / home-indicator
// toggles and the Always On Display slider are iOS-only concepts, so they stay
// gated to non-Catalyst; the brightness boost shows on both iOS and
// Catalyst (HDR-capable built-in and external displays) — but only on
// OS 26+, where the EDR APIs exist. On Catalyst the boost is the
Expand All @@ -487,8 +488,42 @@ struct WindowSettingsView: View {
)
.themedRow()

Toggle("Always On Display", isOn: $alwaysOnDisplayManager.isEnabled)
.themedRow()
VStack(alignment: .leading, spacing: 8) {
HStack {
Text("Always On Display")
Spacer()
Text(alwaysOnDisplayManager.duration.displayValue)
.foregroundColor(.secondary)
.monospacedDigit()
// A floor, not a fixed width: it keeps the slider from
// shifting as the value changes without clipping
// "Always" at large Dynamic Type sizes.
.frame(minWidth: 68, alignment: .trailing)
}
HStack(spacing: 12) {
Image(systemName: "moon.zzz")
.foregroundStyle(.secondary)
.accessibilityHidden(true)
Slider(
value: $alwaysOnDisplayManager.sliderValue,
in: AlwaysOnDisplayDuration.sliderRange,
step: 1
)
// The row title is a sibling in the HStack above, so the
// slider needs its own name for VoiceOver.
.accessibilityLabel(Text("Always On Display"))
.accessibilityValue(alwaysOnDisplayManager.duration.displayValue)
Image(systemName: "infinity")
.foregroundStyle(.secondary)
.accessibilityHidden(true)
}
Text(alwaysOnDisplayManager.duration.explanation)
.font(.caption)
.foregroundColor(.secondary)
.fixedSize(horizontal: false, vertical: true)
}
.padding(.vertical, 4)
.themedRow()

if deviceHasHomeIndicator {
DescribedToggle(
Expand Down
4 changes: 4 additions & 0 deletions rootshell/UI/Terminal/TerminalView+Keyboard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,10 @@ extension Ghostty.TerminalView {
extension Ghostty.TerminalView {

override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
// Hardware keys reach the responder chain, not the window-level touch
// observer, so typing has to restart the always-on-display window here.
noteAlwaysOnDisplayInteraction()

var handled = false
var shouldSkipSuper = false

Expand Down
7 changes: 7 additions & 0 deletions rootshell/UI/Terminal/TerminalView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3708,6 +3708,13 @@ extension Ghostty {
#endif

func insertText(_ text: String) {
// Software-keyboard and input-method text arrives here, not through
// `pressesBegan`, and the terminal is not a UITextField, so this is
// the only path that sees it. It has to restart the always-on-display
// window before any of the early returns below: a suppressed
// duplicate or a sentinel key is still the user typing.
noteAlwaysOnDisplayInteraction()

// Sentinel key names are not text. Drop before any flag is consumed.
if let sentinel = KeyCode.sentinelKey(for: text) {
if sentinel == .escape {
Expand Down
Loading