One layer-shell surface with a managed lifecycle. More...
#include <phosphor-layer/include/PhosphorLayer/Surface.h>
Classes | |
| class | CtorToken |
| Opaque construction token — only SurfaceFactory can create instances of it. More... | |
Public Types | |
| enum class | State { Constructed , Warming , Shown , Hidden , Failed } |
Public Slots | |
Lifecycle | |
Idempotent and safe to call in any state. Invalid transitions warn and no-op. Declared as Q_SLOTS so consumers can wire QML-side signals (e.g. a dismissTimer's | |
| void | show () |
| void | hide () |
| void | warmUp () |
| Create engine + window + content, leave hidden. | |
Signals | |
| void | stateChanged (State newState) |
| NOTIFY signal for the state Q_PROPERTY. | |
| void | failed (const QString &reason) |
| Emitted once when transitioning to State::Failed. | |
| void | screenLost () |
| Emitted when the QScreen the Surface was attached to is removed from the IScreenProvider's list. | |
Public Member Functions | |
| ~Surface () override | |
| Q_ENUM so QMetaEnum can stringify State values in log messages (State::Failed → "Failed") and so Q_PROPERTY / QSignalSpy introspection works. | |
| State | state () const noexcept |
| const SurfaceConfig & | config () const noexcept |
| bool | isLogicallyShown () const noexcept |
| Convenience: is the Surface in the logical "shown" state? | |
Escape hatches | |
Prefer the declarative API. These are for consumers that need to reach into Qt machinery (installing event filters, connecting to window-specific signals, etc.). | |
| QQuickWindow * | window () const noexcept |
| ITransportHandle * | transport () const noexcept |
Protected Member Functions | |
| Surface (CtorToken, SurfaceConfig cfg, SurfaceDeps deps, QObject *parent) | |
| Protected so subclasses can forward a CtorToken through their own constructor. | |
One layer-shell surface with a managed lifecycle.
Owns its QQuickWindow and (by default) its QQmlEngine. Constructed only via SurfaceFactory so injected dependencies can travel with it.
| From | Event | To |
|---|---|---|
| Constructed | warmUp() | Warming |
| Constructed | show() | Warming |
| Warming | (content ready, intent=warm) | Hidden |
| Warming | (content ready, intent=show) | Shown |
| Warming | (content error) | Failed |
| Hidden | show() | Shown |
| Shown | hide() | Hidden |
| any | (transport rejected) | Failed |
Invalid transitions (e.g. show() from Failed) log qCWarning with the debugName and no-op. They never throw.
Topology-driven respawn (screen removal / compositor restart) is the consumer's responsibility, not the library's: subscribe to TopologyCoordinator callbacks or use ScreenSurfaceRegistry::syncToScreens to decide when to destroy and rebuild surfaces. The library deliberately keeps Surface oblivious to the screen lifecycle so consumers retain full control over the save-state-before-destroy sequencing.
hide() is synchronous from the caller's perspective — the window is unmapped immediately. We do not expose a transient "Hiding" state because the compositor's acknowledgement is invisible to application code and the surface is unusable until it's either Shown again or recreated.
|
strong |
| Enumerator | |
|---|---|
| Constructed | Config accepted; no window yet. |
| Warming | Engine / window / content initialising. |
| Shown | Layer surface attached; window visible. |
| Hidden | Attached but window hidden — show() is cheap. |
| Failed | Unrecoverable (content error, transport rejected, …) |
|
override |
Q_ENUM so QMetaEnum can stringify State values in log messages (State::Failed → "Failed") and so Q_PROPERTY / QSignalSpy introspection works.
Not currently registered with QML — consumers that want to bind surface state from QML should register the type themselves via qmlRegisterUncreatableType<Surface>.
|
protected |
|
noexcept |
|
signal |
Emitted once when transitioning to State::Failed.
reason is a human-readable diagnostic (QML compile error, transport rejection, etc.). Surface remains in Failed thereafter.
The library defers this signal via Qt::QueuedConnection so consumer slots that call delete surface do not re-enter library code on a dead this. For non-failure stateChanged emissions the consumer must prefer deleteLater() over delete.
|
slot |
|
noexcept |
Convenience: is the Surface in the logical "shown" state?
Equivalent to state() == State::Shown and exists to give consumers a single canonical answer to "is this overlay currently the
user's view of itself" regardless of the underlying lifecycle.
Under SurfaceConfig::keepMappedOnHide=true, the QQuickWindow stays Qt-visible across logical hide/show cycles — window()->isVisible() is therefore NOT a reliable signal for "currently shown" because it stays true while the surface is logically Hidden under Qt::WindowTransparentForInput. This helper is the right answer for both lifecycles: keep-mapped surfaces consult Surface state (false during the transparent-for-input span); destroy-on-hide surfaces are simply gone from the consumer's tracking when hidden, so the call site never reaches isLogicallyShown() on a destroyed Surface.
|
signal |
Emitted when the QScreen the Surface was attached to is removed from the IScreenProvider's list.
The Surface stays in its current state (Shown/Hidden); consumers decide whether to destroy+rebuild or wait for the screen to come back. m_config.screen is nulled inside the library so the next attach falls back to the provider's primary.
The library defers this signal via Qt::QueuedConnection so consumer slots that call delete surface do not re-enter library code on a dead this. Deleting the Surface from a stateChanged slot for non-Failed transitions remains UB — prefer deleteLater() there.
|
slot |
|
noexcept |
|
signal |
NOTIFY signal for the state Q_PROPERTY.
Carries the new state so slots don't need a round-trip getter call. The previous state is not exposed — track it in your slot if you need it.
|
noexcept |
|
slot |
Create engine + window + content, leave hidden.
Pre-compiles QML so the first show() is latency-free.
|
noexcept |