Private Mode for Terminal Visibility Reports
Terminal applications may perform expensive rendering work even when their output cannot be seen. Focus reports do not solve this problem: an unfocused terminal may remain visible, while a focused terminal may be occluded, suspended, or displayed in a background tab.
This specification defines a new DEC Private Mode that enables terminal visibility reports:
2033- Enable or disable terminal visibility reports
Visibility is an advisory, conservative state. It combines the terminal’s own knowledge of its tabs, panes, and views with visibility information provided by the host platform. Applications can use the report to reduce expensive visual updates while their terminal view is not visible.
Detection and Enabling #
Support is detected with a standard DECRQM query:
CSI ? 2033 $ p
The terminal responds with a DECRPM response:
CSI ? 2033 ; Ps $ y
A Ps value of 0 or 4 means the mode is not supported. A value of 1
means reports are enabled, and a value of 2 means reports are disabled.
Reports are enabled and disabled using DECSET and DECRST:
CSI ? 2033 henables visibility reports.CSI ? 2033 ldisables visibility reports.
Whenever the terminal receives CSI ? 2033 h, it MUST immediately report the
current visibility state, even if the mode was already enabled. While the mode
is enabled, the terminal MUST send another report whenever the effective
visibility state changes. It SHOULD NOT send duplicate reports at other times.
Querying Visibility #
The current visibility state can be requested without enabling change reports:
CSI ? 998 n
A supporting terminal MUST reply with a visibility report. This query does not
change private mode 2033.
Visibility Report #
Both query responses and unsolicited notifications use the same private Device Status Report:
CSI ? 999 ; Ps n
The visibility state Ps is one of:
| Value | State | Meaning |
|---|---|---|
1 |
Potentially visible | The terminal view may be observable. |
2 |
Not visible | The terminal knows that the terminal view is not ordinarily observable. |
Applications MUST treat unknown values as potentially visible.
Potentially visible is deliberately conservative. It does not guarantee that
any terminal cell is currently onscreen. A terminal MUST report 1 whenever
visibility is unknown or any associated view may be observable. It MUST report
2 only when it has positive knowledge that the terminal view is not visible.
Determining Visibility #
A terminal MUST determine visibility for the view associated with the terminal session, not merely for its top-level operating-system window. Relevant state may include:
- whether the terminal’s tab is selected;
- whether its pane or view is displayed;
- whether any window displaying the session is minimized, hidden, or on an inactive workspace;
- whether the window is fully occluded; and
- whether the compositor has suspended presentation of the surface.
If the same terminal session is displayed in more than one view, the terminal MUST report potentially visible if any view may be observable.
On macOS, an implementation can use NSWindow.occlusionState as one input. An
unset NSWindowOcclusionStateVisible bit indicates that the entire window is
occluded. A set bit means that at least part of the window’s bounding box is
visible and must therefore be treated as potentially visible.
On Wayland, an implementation can use the suspended xdg_toplevel state as
one input. A suspended surface can be treated as not visible; a surface that is
not suspended must be treated as potentially visible unless the terminal has
other internal knowledge that its view is hidden.
These platform mechanisms are examples, not requirements. Implementations SHOULD use all reliable platform and internal state available to them and MUST resolve uncertainty in favor of potentially visible.
Application Behavior #
A not-visible report is a performance hint. An application MAY pause animations,
coalesce visual updates, or skip other expensive presentation work while the
state is 2. It SHOULD continue processing input and updating the internal state
needed to produce its next frame.
When the state returns to 1, the application SHOULD render its latest complete
state. Applications MUST NOT assume that the terminal will remain hidden for any
minimum duration.
This mode is independent of focus reporting. Focus indicates which view receives keyboard input; visibility indicates whether output may be observed.
Example #
An application first checks whether visibility reports are supported:
A: \x1b[?2033$p
T: \x1b[?2033;2$y
The terminal supports the mode and reports that it is currently disabled. The application enables reports, and the terminal immediately reports that the view is potentially visible:
A: \x1b[?2033h
T: \x1b[?999;1n
The terminal view becomes fully hidden, then later becomes visible again:
T: \x1b[?999;2n
T: \x1b[?999;1n
An application that only needs the current state can issue a one-shot query:
A: \x1b[?998n
T: \x1b[?999;1n