Streams and presence
cua.env.v1 StreamService and PresenceService: media sessions and multiplayer cursors.
cua.env.v1 StreamService and PresenceService: media sessions and multiplayer cursors.
Media sessions (video and audio over the media wire, see libs/cua/proto/MEDIA.md) and presence for shared sessions.
Source: libs/cua/proto/cua/env/v1/stream.proto, libs/cua/proto/cua/env/v1/presence.proto.
cua.env.v1.StreamService
Control plane for video streaming.
Video never travels over gRPC. This service discovers targets, negotiates
codec and limits, and mints a short-lived media ticket. The client then
opens the media plane (rcdp wire v2, see libs/cua/proto/MEDIA.md) on the
/media WebSocket of the same port, or on direct QUIC, authenticating
with the ticket. The ticket is bound to one media session and target and
is safe to put in a URL; it is not the root token.
Audio is a first-class track next to video: a media session may carry zero or one video track plus any number of downlink audio tracks (desktop mix or per-app), and optionally one uplink audio track (client microphone into a guest virtual source). All tracks share one media clock; see MEDIA.md §12.
/cua.env.v1.StreamService/ListTargets, unary: ListTargetsRequest to ListTargetsResponse.
Lists streamable targets: one desktop target per display, plus windows.
/cua.env.v1.StreamService/OpenMedia, unary: OpenMediaRequest to OpenMediaResponse.
Creates a media session for a target and returns how to attach to it.
/cua.env.v1.StreamService/SetPreferences, unary: SetPreferencesRequest to SetPreferencesResponse.
Changes frame rate, size or bitrate of an open media session.
/cua.env.v1.StreamService/RequestKeyframe, unary: RequestKeyframeRequest to RequestKeyframeResponse.
Asks the encoder for a keyframe (IDR) on the next frame.
/cua.env.v1.StreamService/CloseMedia, unary: CloseMediaRequest to CloseMediaResponse.
Closes a media session and revokes its ticket.
cua.env.v1.PresenceService
Multi-user presence: who is looking at the guest and where their cursors
are. Agent cursors are published automatically when an agent principal
drives ComputerService or cua-driver tools.
Cursor updates are unary (UpdateCursor) so browsers on gRPC-Web can send
them; events arrive on the Join server stream.
| RPC | Request | Response | Kind |
|---|---|---|---|
Join | JoinRequest | JoinResponse | server stream |
UpdateCursor | UpdateCursorRequest | UpdateCursorResponse | unary |
Leave | LeaveRequest | LeaveResponse | unary |
/cua.env.v1.PresenceService/Join, server stream: JoinRequest to JoinResponse.
Joins presence and streams events until Leave or disconnect. The first
event is PresenceJoined with the caller's participant id and the
current roster.
/cua.env.v1.PresenceService/UpdateCursor, unary: UpdateCursorRequest to UpdateCursorResponse.
Publishes the caller's cursor.
/cua.env.v1.PresenceService/Leave, unary: LeaveRequest to LeaveResponse.
Leaves presence and ends the caller's Join stream.
cua/env/v1/stream.proto#A streamable target.
| Field | # | Type | Description |
|---|---|---|---|
display_id | 1 | string (oneof target) | A whole display ("desktop" target), by display id or "primary". |
window | 2 | WindowRef (oneof target) | A single window. |
One entry of ListTargetsResponse.
| Field | # | Type | Description |
|---|---|---|---|
display | 1 | Display (oneof target) | A desktop target. |
window | 2 | WindowInfo (oneof target) | A window target. |
available | 3 | bool | False when the target is listed but cannot be streamed right now. |
limitation | 4 | string | Why not, when available is false (for example "screen recording permission not granted"). |
audio | 5 | AudioSource | The audio source that pairs with this target: the desktop mix for a display target, the owning app's audio for a window target (or the desktop mix, with AudioSource.limitation set, where per-app capture is unsupported). Unset when the guest has no audio capture. |
A capturable audio source.
| Field | # | Type | Description |
|---|---|---|---|
source_id | 1 | string | Opaque id, stable while the source exists. "desktop" always names the desktop mix. |
kind | 2 | AudioSourceKind | What the source captures. |
name | 3 | string | Human-readable name, for example "Desktop audio" or "Firefox". |
app | 4 | AppInfo | Owning application, for AUDIO_SOURCE_KIND_APPLICATION. |
windows | 5 | repeated WindowRef | Windows of that application, for pairing with window video targets. |
available | 6 | bool | False when listed but not capturable right now. |
limitation | 7 | string | Why a source is unavailable, or degraded (for example "per-app capture needs Windows 10 2004+; falls back to desktop audio"). |
desktop_fallback | 8 | bool | True if capturing this source actually captures the desktop mix because per-app capture is unsupported. |
Request for StreamService.ListTargets.
| Field | # | Type | Description |
|---|---|---|---|
include_windows | 1 | bool | Include window targets. Desktop targets are always included. |
window_filter | 2 | WindowFilter | Filter for window targets. |
Response for StreamService.ListTargets.
| Field | # | Type | Description |
|---|---|---|---|
targets | 1 | repeated StreamTarget | Desktop targets first (primary display first), then windows front to back. Phantom and system windows are never listed. |
codecs | 2 | repeated MediaCodec | Codecs this driver can produce, in its preference order. |
audio_sources | 3 | repeated AudioSource | Every capturable audio source: the desktop mix first, then per-app sources. Empty when the guest has no audio capture. |
audio_codecs | 4 | repeated AudioCodec | Audio codecs this driver can produce, in its preference order. |
audio_uplink_allowed | 5 | bool | True if this caller may open an audio uplink (feature "audio.uplink" is supported and the caller's principal is allowed). |
audio_uplink_limitation | 6 | string | Why the uplink is not allowed, when it is not. |
Audio encoding parameters shared by downlink and uplink requests. Zero and unset values select the defaults noted per field.
| Field | # | Type | Description |
|---|---|---|---|
codecs | 1 | repeated AudioCodec | Acceptable codecs in preference order. Empty means Opus, then PCM. |
sample_rate_hz | 2 | uint32 | Sample rate in Hz. 0 means 48000. Opus accepts 8000, 12000, 16000, 24000 and 48000. |
channels | 3 | uint32 | Channel count, 1 or 2. 0 means 2 (downlink) or 1 (uplink). |
bitrate_kbps | 4 | uint32 | Opus target bitrate in kbps (6 to 510). 0 means 64 for stereo, 32 for mono. Ignored for PCM. |
fec | 5 | optional bool | Opus in-band forward error correction. Unset means on. |
dtx | 6 | optional bool | Opus discontinuous transmission (send almost nothing during silence). Unset means on. |
frame_ms | 7 | uint32 | Frame duration in milliseconds: 10, 20, 40 or 60. 0 means 20. Shorter frames lower latency at a higher packet rate. |
expected_loss_percent | 8 | uint32 | Expected packet loss in percent (0 to 100), tuning the Opus FEC redundancy. 0 means 10 when fec is on. |
Audio options for OpenMediaRequest.
| Field | # | Type | Description |
|---|---|---|---|
enabled | 1 | bool | Enable downlink audio. When false, no audio tracks are sent and the other fields except uplink are ignored. |
source_ids | 2 | repeated string | Sources to send, one track each, by AudioSource.source_id. Empty means the source that pairs with the video target (StreamTarget.audio). |
encoding | 3 | AudioEncoding | Downlink encoding. |
uplink | 4 | AudioUplinkOptions | Optional microphone uplink. |
Client-to-guest audio (for example the user's microphone), played into a guest virtual audio source so apps inside can "hear" the user.
Off by default and gated separately from video and input: it requires the
"audio.uplink" feature, a session policy other than
SESSION_POLICY_VIEW_ONLY, and the caller's principal to be allowed by
InitRequest.audio_uplink. A denied uplink does not fail OpenMedia; the
response reports why in AudioUplinkGrant.
| Field | # | Type | Description |
|---|---|---|---|
enabled | 1 | bool | Request an uplink track. |
encoding | 2 | AudioEncoding | Encoding the client will send. |
virtual_source_name | 3 | string | Name of the guest virtual source (microphone) to create or reuse. Empty means "cua-uplink". |
set_default_input | 4 | bool | Make the virtual source the guest's default input device while the uplink is active. |
Request for StreamService.OpenMedia.
| Field | # | Type | Description |
|---|---|---|---|
target | 1 | MediaTarget | What to stream. |
codecs | 2 | repeated MediaCodec | Acceptable codecs in client preference order. Empty means any. |
max_fps | 3 | uint32 | Maximum frames per second. 0 means 30. |
max_dimension | 4 | uint32 | Maximum long edge in pixels. 0 means native. |
bitrate_kbps | 5 | uint32 | Target H.264 bitrate in kbps (250 to 100000). 0 means encoder default. |
policy | 6 | SessionPolicy | Input policy for clients attached to this session. |
geometry_control | 7 | GeometryControl | Geometry control. |
ticket_ttl | 8 | google.protobuf.Duration | Ticket lifetime for attaching. Unset means 60 seconds; at most 10 minutes. The ticket only has to be valid when the socket attaches; an attached socket stays open past expiry. |
prefer_quic | 9 | bool | Include OpenMediaResponse.quic when direct QUIC media is available. |
audio | 10 | AudioOptions | Audio tracks. Unset means no audio (the v2.0 behavior). |
disable_video | 11 | bool | Open an audio-only session: no video track is produced. target still selects the paired audio source when audio.source_ids is empty. |
presence_participant_id | 12 | string | The viewer's presence participant, its input's owner (PRESENCE.md §7). |
One negotiated downlink audio track.
| Field | # | Type | Description |
|---|---|---|---|
track_id | 1 | uint32 | Track id carried in every audio packet header (MEDIA.md §12). Unique within the media session; never 0. |
source | 2 | AudioSource | The source it captures. |
Negotiated audio encoding.
| Field | # | Type | Description |
|---|---|---|---|
codec | 1 | AudioCodec | Selected codec. |
sample_rate_hz | 2 | uint32 | Sample rate in Hz. |
channels | 3 | uint32 | Channel count. |
bitrate_kbps | 4 | uint32 | Target bitrate in kbps (0 for PCM). |
fec | 5 | bool | In-band FEC on. |
dtx | 6 | bool | DTX on. |
frame_ms | 7 | uint32 | Frame duration in milliseconds. |
Outcome of an uplink request.
| Field | # | Type | Description |
|---|---|---|---|
granted | 1 | bool | True if the uplink is open. |
denied_reason | 2 | string | Why not, when denied (for example "principal not allowed", "view_only session", "no virtual audio device"). |
track_id | 3 | uint32 | Track id the client must put in uplink packet headers. |
encoding | 4 | NegotiatedAudioEncoding | Encoding the server expects. |
virtual_source_name | 5 | string | Name of the guest virtual source the audio is played into. |
Negotiated audio for a media session.
| Field | # | Type | Description |
|---|---|---|---|
tracks | 1 | repeated AudioTrack | Downlink tracks, in the order requested. |
encoding | 2 | NegotiatedAudioEncoding | Downlink encoding, shared by every downlink track. |
uplink | 3 | AudioUplinkGrant | Uplink outcome, when an uplink was requested. |
Direct QUIC media endpoint. Only reachable when the client can reach the guest's UDP port directly (not through the Fleet gateway or relay).
| Field | # | Type | Description |
|---|---|---|---|
port | 1 | uint32 | UDP port (normally 3212). |
certificate_sha256 | 2 | string | Lowercase hex SHA-256 of the server's self-signed certificate (DER), to pin. |
alpn | 3 | string | ALPN protocol id, "rcdp/2". |
Geometry of a media session's frames.
| Field | # | Type | Description |
|---|---|---|---|
frame_size | 1 | PixelSize | Frame size in pixels. |
scale | 2 | double | Frame pixels per logical point of the target. |
logical_bounds | 3 | Rect | Target bounds in global logical points when the session opened. |
geometry_epoch | 4 | uint64 | Geometry generation; matches geometry_epoch on the media plane. |
Response for StreamService.OpenMedia.
| Field | # | Type | Description |
|---|---|---|---|
media_session_id | 1 | string | Media session id. |
ticket | 2 | string | Bearer ticket for the media socket. |
ticket_expires_at | 3 | google.protobuf.Timestamp | When the ticket stops being accepted for new attaches. |
ws_path | 4 | string | WebSocket path relative to the spacesd base URL, including the ticket, for example "/media?ticket=…". Works through the Fleet gateway and the relay. |
quic | 5 | QuicEndpoint | Direct QUIC endpoint, when requested and available. |
codec | 6 | MediaCodec | Negotiated codec. |
max_fps | 7 | uint32 | Effective frame rate cap. |
max_dimension | 8 | uint32 | Effective long-edge cap. |
bitrate_kbps | 9 | uint32 | Effective bitrate in kbps, 0 when not applicable. |
policy | 10 | SessionPolicy | Effective policy (may be lower than requested). |
geometry_control | 11 | GeometryControl | Effective geometry control. |
geometry | 12 | MediaGeometry | Initial geometry. |
wire_version | 13 | uint32 | Media wire protocol version. 2 for this contract. |
audio | 14 | NegotiatedAudio | Negotiated audio. Unset when audio was not requested or is not available (see the "audio.*" capabilities). |
Request for StreamService.SetPreferences.
| Field | # | Type | Description |
|---|---|---|---|
media_session_id | 1 | string | Which session. |
max_fps | 2 | uint32 | New frame rate cap. 0 keeps the current value. |
max_dimension | 3 | uint32 | New long-edge cap. 0 keeps the current value. |
bitrate_kbps | 4 | uint32 | New bitrate in kbps. 0 keeps the current value. |
audio_enabled | 5 | optional bool | Pause (false) or resume (true) all downlink audio tracks. Unset keeps the current state. Paused tracks send nothing; the session keeps its track ids. |
audio_bitrate_kbps | 6 | uint32 | New Opus bitrate in kbps. 0 keeps the current value. |
audio_fec | 7 | optional bool | Turn Opus FEC on or off. Unset keeps the current value. |
audio_dtx | 8 | optional bool | Turn Opus DTX on or off. Unset keeps the current value. |
audio_frame_ms | 9 | uint32 | New frame duration in milliseconds (10, 20, 40 or 60). 0 keeps the current value. Takes effect with a new audio config epoch. |
audio_expected_loss_percent | 10 | optional uint32 | New expected loss percentage for FEC tuning. Unset keeps the current value. |
audio_uplink_muted | 11 | optional bool | Mute (true) or unmute (false) the uplink's virtual source. Unset keeps the current state. |
Response for StreamService.SetPreferences. When this returns, capture
has been reconfigured; frames from the old configuration may still be in
flight and are distinguished by codec_epoch on the media plane.
| Field | # | Type | Description |
|---|---|---|---|
max_fps | 1 | uint32 | Effective frame rate cap. |
max_dimension | 2 | uint32 | Effective long-edge cap. |
bitrate_kbps | 3 | uint32 | Effective bitrate in kbps. |
audio_enabled | 4 | bool | True if downlink audio is flowing (not paused). |
audio_encoding | 5 | NegotiatedAudioEncoding | Effective downlink audio encoding. Unset when the session has no audio. |
audio_uplink_muted | 6 | bool | True if the uplink's virtual source is muted. |
Request for StreamService.RequestKeyframe.
| Field | # | Type | Description |
|---|---|---|---|
media_session_id | 1 | string | Which session. |
Response for StreamService.RequestKeyframe.
No fields.
Request for StreamService.CloseMedia.
| Field | # | Type | Description |
|---|---|---|---|
media_session_id | 1 | string | Which session. |
Response for StreamService.CloseMedia.
No fields.
Video codec on the media plane.
| Value | # | Description |
|---|---|---|
MEDIA_CODEC_UNSPECIFIED | 0 | Not set. |
MEDIA_CODEC_H264 | 1 | H.264, one Annex B access unit per packet; keyframes carry SPS/PPS. |
MEDIA_CODEC_BGRA | 2 | Raw top-down BGRA, tightly packed. Loopback / debugging only. |
MEDIA_CODEC_PNG | 3 | One PNG per frame. Fallback when no encoder is available. |
What a media session's attached clients may do to the target.
| Value | # | Description |
|---|---|---|
SESSION_POLICY_UNSPECIFIED | 0 | Not set. Treated as SESSION_POLICY_VIEW_ONLY. |
SESSION_POLICY_VIEW_ONLY | 1 | Video only; interactive input is refused. |
SESSION_POLICY_BACKGROUND_ONLY | 2 | Input allowed, but only background delivery (never activates or moves the real pointer). |
SESSION_POLICY_ALLOW_ACTIVATION | 3 | Input allowed and may activate the target. |
Whether a session may resize its target window to fit the viewer.
| Value | # | Description |
|---|---|---|
GEOMETRY_CONTROL_UNSPECIFIED | 0 | Not set. Treated as GEOMETRY_CONTROL_OBSERVE_ONLY. |
GEOMETRY_CONTROL_OBSERVE_ONLY | 1 | Never resize the target. |
GEOMETRY_CONTROL_BIDIRECTIONAL | 2 | Viewer may resize the target. Exclusive per target: a second bidirectional session fails with FAILED_PRECONDITION instead of stealing the lease. Window targets only. |
Audio codec on the media plane.
| Value | # | Description |
|---|---|---|
AUDIO_CODEC_UNSPECIFIED | 0 | Not set. |
AUDIO_CODEC_OPUS | 1 | Opus (RFC 6716), one Opus packet per media packet. The default. |
AUDIO_CODEC_PCM_S16LE | 2 | Raw interleaved signed 16-bit little-endian PCM. Lossless, for debugging and tests; roughly 1.5 Mbit/s for 48 kHz stereo. |
What an audio source captures.
| Value | # | Description |
|---|---|---|
AUDIO_SOURCE_KIND_UNSPECIFIED | 0 | Not reported. |
AUDIO_SOURCE_KIND_DESKTOP | 1 | Everything the guest plays (the default output's mix). |
AUDIO_SOURCE_KIND_APPLICATION | 2 | Audio of one application only. |
cua/env/v1/presence.proto#A participant.
| Field | # | Type | Description |
|---|---|---|---|
participant_id | 1 | string | Server-assigned participant id, unique per Join. |
principal | 2 | Principal | Who it is. color is the server-assigned color, which may differ from the requested one. |
joined_at | 3 | google.protobuf.Timestamp | When it joined. |
Where a cursor is.
| Field | # | Type | Description |
|---|---|---|---|
display_id | 1 | string | Target the cursor is over. Unset means the primary desktop. |
window | 2 | WindowRef | Window the cursor is over, when the participant is viewing a window stream. |
position | 3 | Point | Position normalized to [0, 1] within the window (if set) or the display, so viewers at different scales agree. |
visible | 4 | bool | False hides the cursor (for example the pointer left the viewer). |
shape | 5 | CursorShape | The pointer shape the guest would show at position, computed by the server for participants that joined with JoinRequest.cursor_shapes. Ignored in UpdateCursorRequest. CURSOR_SHAPE_UNSPECIFIED (older daemons, or not probed yet) is drawn as the arrow. |
shape_source | 6 | CursorShapeSource | How shape was determined. |
Request for PresenceService.Join.
| Field | # | Type | Description |
|---|---|---|---|
principal | 1 | Principal | Who is joining. Overrides the x-cua-principal-bin metadata. |
keepalive_interval | 2 | google.protobuf.Duration | Interval between keepalive events. Unset means 30 seconds. |
cursor_shapes | 3 | bool | Asks the server to compute cursor shapes (CursorPosition.shape) and send CursorShapeChanged. Honored only when the capability "presence.cursor_shape" is supported; otherwise shapes stay unspecified. |
roster_interval | 4 | google.protobuf.Duration | Interval between RosterHeartbeat events, which list everyone present so a client can drop a participant whose leave it missed. Unset or zero means no heartbeats. Clamped to at least one second. |
cursor_batches | 5 | bool | Asks for one CursorBatch per server tick, carrying every cursor that moved in it, instead of one CursorMoved per cursor. |
cursor_datagrams | 6 | bool | Asks for a presence datagram channel (PresenceJoined.datagrams): cursors as unreliable, latest-wins QUIC datagrams in both directions, with this stream kept for everything else. Ignored when the server has no QUIC listener; the stream then carries cursors as before. |
First event of a Join stream.
| Field | # | Type | Description |
|---|---|---|---|
participant | 1 | Participant | The caller. |
roster | 2 | repeated ParticipantCursor | Everyone else currently present, with their last known cursors. |
datagrams | 3 | PresenceDatagrams | The presence datagram channel, when requested and available. See libs/cua/proto/PRESENCE.md. |
Where and how to open the presence datagram channel.
| Field | # | Type | Description |
|---|---|---|---|
endpoint | 1 | QuicEndpoint | The QUIC listener (normally UDP 3212); alpn is "cua-presence/1". |
ticket | 2 | string | Single-use credential binding the QUIC connection to this participant. |
tick | 3 | google.protobuf.Duration | Server cursor tick on the channel (normally 33 ms). |
A participant and their cursor.
| Field | # | Type | Description |
|---|---|---|---|
participant | 1 | Participant | The participant. |
cursor | 2 | CursorPosition | Their last cursor, unset if never published. |
A participant left.
| Field | # | Type | Description |
|---|---|---|---|
participant_id | 1 | string | Their participant id. |
reason | 2 | LeaveReason | Why. |
Everyone present, sent every JoinRequest.roster_interval. A participant
missing from it has left.
| Field | # | Type | Description |
|---|---|---|---|
participant_ids | 1 | repeated string | Participant ids present, the recipient included. |
at | 2 | google.protobuf.Timestamp | When the server sent it. |
Every cursor that moved in one server tick.
| Field | # | Type | Description |
|---|---|---|---|
moves | 1 | repeated CursorMoved | The moves, at most one per participant. |
tick | 2 | uint64 | Server tick number. Ticks are the server's cursor interval apart; a gap means ticks without moves. |
at | 3 | google.protobuf.Timestamp | When the server sent it. |
A participant's cursor moved.
| Field | # | Type | Description |
|---|---|---|---|
participant_id | 1 | string | Whose cursor. |
cursor | 2 | CursorPosition | New position. |
at | 3 | google.protobuf.Timestamp | When the server received it. |
A participant's cursor shape changed. Sent to every subscriber that asked for shapes, including the participant itself, so each client can draw its own cursor with the guest's shape.
| Field | # | Type | Description |
|---|---|---|---|
participant_id | 1 | string | Whose cursor. |
shape | 2 | CursorShape | New shape. |
source | 3 | CursorShapeSource | How it was determined. |
at | 4 | google.protobuf.Timestamp | When the server determined it. |
One message of the PresenceService.Join stream.
| Field | # | Type | Description |
|---|---|---|---|
joined | 1 | PresenceJoined (oneof event) | First event. |
participant_joined | 2 | Participant (oneof event) | Someone joined. |
participant_left | 3 | ParticipantLeft (oneof event) | Someone left. |
cursor_moved | 4 | CursorMoved (oneof event) | Someone's cursor moved. Coalesced to at most 30 per second per participant. |
keepalive | 5 | KeepAlive (oneof event) | Idle stream heartbeat. |
cursor_shape_changed | 6 | CursorShapeChanged (oneof event) | Someone's cursor shape changed (only with JoinRequest.cursor_shapes). |
roster_heartbeat | 7 | RosterHeartbeat (oneof event) | Everyone present (only with JoinRequest.roster_interval). |
cursor_batch | 8 | CursorBatch (oneof event) | Cursors that moved in one tick (only with JoinRequest.cursor_batches). |
Request for PresenceService.UpdateCursor.
| Field | # | Type | Description |
|---|---|---|---|
participant_id | 1 | string | The caller's participant id from PresenceJoined.participant. |
cursor | 2 | CursorPosition | New position. |
Response for PresenceService.UpdateCursor.
No fields.
Request for PresenceService.Leave.
| Field | # | Type | Description |
|---|---|---|---|
participant_id | 1 | string | The caller's participant id. |
Response for PresenceService.Leave.
No fields.
A pointer shape, in a small portable vocabulary. Clients draw their own art for each value in the participant's color.
| Value | # | Description |
|---|---|---|
CURSOR_SHAPE_UNSPECIFIED | 0 | Unknown or not probed. Draw the arrow. |
CURSOR_SHAPE_ARROW | 1 | The ordinary arrow. |
CURSOR_SHAPE_TEXT | 2 | Text insertion (I-beam). |
CURSOR_SHAPE_POINTER | 3 | A link or other clickable control (pointing hand). |
CURSOR_SHAPE_RESIZE_NS | 4 | Resize along the vertical axis (top or bottom edge). |
CURSOR_SHAPE_RESIZE_EW | 5 | Resize along the horizontal axis (left or right edge). |
CURSOR_SHAPE_RESIZE_NESW | 6 | Resize along the rising diagonal (top-right or bottom-left corner). |
CURSOR_SHAPE_RESIZE_NWSE | 7 | Resize along the falling diagonal (top-left or bottom-right corner). |
CURSOR_SHAPE_WAIT | 8 | Busy; input is not accepted. |
CURSOR_SHAPE_PROGRESS | 9 | Working in the background; input is still accepted. |
CURSOR_SHAPE_NOT_ALLOWED | 10 | The action is not permitted here. |
CURSOR_SHAPE_CROSSHAIR | 11 | Precise selection. |
CURSOR_SHAPE_GRAB | 12 | Open hand over something draggable. |
CURSOR_SHAPE_GRABBING | 13 | Closed hand while dragging. |
CURSOR_SHAPE_MOVE | 14 | Move in any direction. |
How a cursor shape was determined.
| Value | # | Description |
|---|---|---|
CURSOR_SHAPE_SOURCE_UNSPECIFIED | 0 | Not reported. |
CURSOR_SHAPE_SOURCE_HIT_TEST | 1 | Accessibility hit-test at the participant's position (role of the element under the point, window edges). Never moves the guest pointer. |
CURSOR_SHAPE_SOURCE_SYSTEM | 2 | The guest's real cursor, read while this participant's input is what positioned the pointer. |
CURSOR_SHAPE_SOURCE_PROBE | 3 | The guest's real cursor, read by briefly moving the idle pointer to the participant's position and restoring it (see PresenceSettings). |
Why a participant left.
| Value | # | Description |
|---|---|---|
LEAVE_REASON_UNSPECIFIED | 0 | Not reported. |
LEAVE_REASON_LEFT | 1 | It called Leave. |
LEAVE_REASON_DISCONNECTED | 2 | Its Join stream ended. |
LEAVE_REASON_TIMEOUT | 3 | No activity within the server's timeout (agents without a stream). |
LEAVE_REASON_RUN_ENDED | 4 | The agent run or driver session that owned the cursor ended. |