events

package
v0.703.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 7, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package events defines the backend-agnostic UI event subscription model for the Pando Desktop Controller. A platform backend (internal/uiauto/ platform/...) may optionally implement Subscriber, in addition to core.Backend, to push live UI-tree changes instead of being polled; WaitFor prefers that live path and transparently falls back to core.WaitFor's polling loop for any backend that does not implement it, or when a live subscription itself fails. Capabilities.Events must reflect which is actually happening for a given backend/session -- never claim events support a backend cannot genuinely deliver.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func WaitFor

func WaitFor(ctx context.Context, backend core.Backend, sub Subscriber, l *core.Locator, cond core.Condition, timeout time.Duration) (*core.Element, error)

WaitFor waits for cond to hold for l against backend, preferring a live subscription from sub (when non-nil) and transparently falling back to core.WaitFor's polling loop when sub is nil, sub.Subscribe itself fails, or the subscription channel closes before the condition is met (the polling loop then covers the rest of the deadline). Even on the event-driven path, every received event only triggers a fresh, authoritative evaluate() call against backend -- an event is a wake-up signal, never trusted as the source of truth by itself.

Types

type Event

type Event struct {
	Kind Kind
	// ElementRef is a best-effort qualified reference to the affected
	// element, when the backend can map the raw native event onto a live
	// Manager snapshot ref. It is frequently empty: events are a wake-up
	// signal, not a source of truth -- WaitFor always re-evaluates the
	// actual condition against the backend rather than trusting this
	// field, so an empty ElementRef never blocks correctness.
	ElementRef core.ElementRef
	// AppID/WindowID identify the owning application/window when the
	// backend can cheaply provide them.
	AppID    string
	WindowID string
	// Timestamp is when this package observed the event (not necessarily
	// when the backend/OS generated it).
	Timestamp time.Time
	// Details carries whatever raw, backend-specific information is
	// useful for diagnostics (e.g. the native signal member name, the CDP
	// node id). Not part of the stable cross-backend contract.
	Details map[string]any
}

Event is one backend-reported UI change.

type EventBus

type EventBus struct {
	// contains filtered or unexported fields
}

EventBus fans a single upstream event source (typically one long-lived, backend-specific listener -- a D-Bus signal match, a CDP ListenTarget handler, ...) out to any number of independent waiters, each with its own buffered channel so one slow consumer never blocks another or the publisher.

func NewEventBus

func NewEventBus() *EventBus

NewEventBus creates an empty EventBus.

func (*EventBus) Close

func (b *EventBus) Close()

Close unsubscribes and closes every current subscriber channel and causes any future Subscribe call to return an already-closed channel. Safe to call more than once.

func (*EventBus) Len

func (b *EventBus) Len() int

Len reports the current subscriber count.

func (*EventBus) Publish

func (b *EventBus) Publish(ev Event)

Publish fans ev out to every current subscriber. A subscriber whose buffer is full has the event dropped for it rather than blocking the publisher: this is a deliberate best-effort design, not a bug -- see Subscriber's doc comment.

func (*EventBus) Subscribe

func (b *EventBus) Subscribe(buffer int) (<-chan Event, func())

Subscribe registers a new waiter with the given channel buffer size (<=0 uses a small default), returning its receive-only channel and an unsubscribe func. Unsubscribe is idempotent and safe to call from any goroutine, any number of times. Subscribing to a closed bus returns an already-closed channel and a no-op unsubscribe.

type Kind

type Kind string

Kind enumerates the accessibility event categories a Subscriber can report. This is a deliberately small, backend-agnostic vocabulary; a backend maps its native event/signal names onto these.

const (
	// KindCreated signals a new element appeared (e.g. AT-SPI
	// ChildrenChanged:add, CDP DOM.childNodeInserted).
	KindCreated Kind = "created"
	// KindDestroyed signals an element disappeared/was removed.
	KindDestroyed Kind = "destroyed"
	// KindPropertyChanged signals a generic attribute/state change that
	// isn't more specifically a focus or value change.
	KindPropertyChanged Kind = "propertychanged"
	// KindFocusChanged signals keyboard focus moved.
	KindFocusChanged Kind = "focuschanged"
	// KindValueChanged signals an element's value/text content changed.
	KindValueChanged Kind = "valuechanged"
)

type Subscriber

type Subscriber interface {
	Subscribe(ctx context.Context, scope core.Scope) (<-chan Event, func(), error)
}

Subscriber is implemented by a core.Backend that can push live UI events for a scope instead of being polled. It is intentionally a separate, optional interface (like core.Backend's own PhysicalInput/screen split) so a backend that cannot genuinely support it simply does not implement it -- callers detect support via a type assertion (backend.(events.Subscriber)) and fall back to polling, never a runtime panic or a faked capability.

Subscribe returns a channel of events (closed when the subscription ends, e.g. the backend connection drops) and an idempotent unsubscribe func. Implementations must never block the caller of Subscribe itself on waiting for an actual event; event delivery afterwards is best-effort/buffered (a slow consumer may miss events -- WaitFor always re-checks the real condition, so a missed event only costs a slightly later re-check).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL