inputactivity

package
v2.22.1 Latest Latest
Warning

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

Go to latest
Published: Nov 10, 2026 License: GPL-3.0 Imports: 21 Imported by: 0

Documentation

Overview

Package inputactivity detects whether a person is using a device's keyboard, mouse or controllers. The decision logic lives in portable files so it can be tested without hardware; the OS-specific files only gather raw samples.

Index

Constants

View Source
const (
	// NotifyInterval is the shortest gap between two callbacks.
	NotifyInterval = 200 * time.Millisecond

	// PollInterval is how often polled sources sample while idle rotation is
	// only waiting for someone to go away.
	PollInterval = 250 * time.Millisecond
	// ResponsivePollInterval is the sampling gap while a countdown is on
	// screen and one tap has to register.
	ResponsivePollInterval = 20 * time.Millisecond
)
View Source
const ProcDevicesPath = "/proc/bus/input/devices"

ProcDevicesPath is the kernel's list of input devices.

Variables

This section is empty.

Functions

This section is empty.

Types

type ChatterFilter

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

ChatterFilter suppresses a device that is stuck. A person pauses or varies what they do; a gamepad keyboard interface, a pegged axis or a flapping switch repeats the same event nonstop.

func (*ChatterFilter) Allow

func (f *ChatterFilter) Allow(now time.Time, sig uint64) bool

Allow records one activity event at now, identified by sig (a digest of what it reported), and reports whether it should count as activity.

type Class

type Class uint8

Class is a set of kinds of input. The bit values match platforms.InputClass so a platform can convert with a plain cast.

const (
	// Keyboard is key presses on a keyboard.
	Keyboard Class = 1 << iota
	// Mouse is mouse or pointer movement and buttons.
	Mouse
	// Controller is button and stick activity on a game controller.
	Controller
)

func (Class) Has

func (c Class) Has(want Class) bool

Has reports whether every class in want is in c.

type Desktop

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

Desktop watches a desktop session: controllers through event nodes and keyboard plus mouse through the session's idle time on D-Bus.

func NewDesktop

func NewDesktop() *Desktop

NewDesktop returns a source for a non-root desktop session.

func (*Desktop) Coverage

func (d *Desktop) Coverage() Class

Coverage reports keyboard and mouse only when a session idle source works, and controllers only when event nodes can be read.

func (*Desktop) Watch

func (d *Desktop) Watch(ctx context.Context, responsive bool, onActivity func()) error

Watch blocks until ctx is cancelled. It fails at once when neither source works, and returns the error when the controller watch stops on its own: coverage still claims controllers, so carrying on without them would leave a person using one looking idle.

type Evdev

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

Evdev watches /dev/input/event* nodes for keyboards, mice and controllers. It only works where nothing else grabs the devices exclusively.

func NewEvdev

func NewEvdev(classes Class) *Evdev

NewEvdev returns a source limited to the given classes of input.

func NewEvdevAll

func NewEvdevAll() *Evdev

NewEvdevAll returns a source watching keyboards, mice and controllers.

func (*Evdev) Coverage

func (e *Evdev) Coverage() Class

Coverage reports the classes of input that can be read right now.

func (*Evdev) Watch

func (e *Evdev) Watch(ctx context.Context, _ bool, onActivity func()) error

Watch reads input devices until ctx is cancelled.

type IdleTracker

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

IdleTracker turns a stream of "time since last input" readings into activity. Idle time only ever grows by the time between readings unless someone touched an input in between.

func NewIdleTracker

func NewIdleTracker(clock clockwork.Clock) *IdleTracker

NewIdleTracker returns a tracker reading time from clock.

func (*IdleTracker) Observe

func (t *IdleTracker) Observe(idle time.Duration) bool

Observe records an idle reading and reports whether input happened since the previous one. The first reading is a baseline.

type InputDevice

type InputDevice struct {
	Name     string
	Phys     string
	Sysfs    string
	Uniq     string
	Handlers []string
	// contains filtered or unexported fields
}

InputDevice is one entry of /proc/bus/input/devices.

func ParseDevices

func ParseDevices(r io.Reader) []InputDevice

ParseDevices reads the /proc/bus/input/devices format. Unknown lines are ignored so a newer kernel cannot break enumeration.

func ReadDevices

func ReadDevices(fs afero.Fs, name string) ([]InputDevice, error)

ReadDevices parses the device list at name on fs.

func (*InputDevice) Classify

func (d *InputDevice) Classify() Class

Classify returns the single kind of input a device produces. A device with gamepad buttons is a controller even if it also exposes keys or a pointer, and a device with letter keys is a keyboard even if it has a wheel.

func (*InputDevice) EventNode

func (d *InputDevice) EventNode() (string, bool)

EventNode returns the evdev node name such as "event3".

func (*InputDevice) HasAbs

func (d *InputDevice) HasAbs(code int) bool

HasAbs reports whether the device advertises the absolute axis code.

func (*InputDevice) JoystickNode

func (d *InputDevice) JoystickNode() (string, bool)

JoystickNode returns the legacy joystick node name such as "js0".

func (*InputDevice) Own

func (d *InputDevice) Own() bool

Own reports whether the device is one Zaparoo created itself.

func (*InputDevice) Skipped

func (d *InputDevice) Skipped() bool

Skipped reports whether the device must never count as a person. Only Zaparoo's own devices qualify: software that creates input devices for a real controller, such as Steam Input or ds4drv, is a person's input, and treating every uinput device as synthetic would leave that player invisible while coverage still claimed to see them. Devices that report nonstop without anyone behind them are the chatter filter's job.

func (*InputDevice) Synthetic

func (d *InputDevice) Synthetic() bool

Synthetic reports whether the device was created by software through uinput rather than backed by hardware.

func (*InputDevice) UsbParent

func (d *InputDevice) UsbParent() string

UsbParent returns the physical parent shared by every interface of one USB device, or "" when the device has no such notion (Bluetooth, PS/2).

type SAM

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

SAM watches input the way MiSTer_SAM does, for devices where MiSTer Main holds an exclusive grab on every /dev/input/event* node. The legacy nodes keep reporting while grabbed: joystick state through /dev/input/jsN, keyboards through their /dev/hidrawN twin and every mouse through /dev/input/mice.

func NewSAM

func NewSAM() *SAM

NewSAM returns a source for the MiSTer input layout.

func (*SAM) Coverage

func (s *SAM) Coverage() Class

Coverage reports what the legacy nodes can see right now. Keyboards count only when every keyboard that matters has a readable hidraw node.

func (*SAM) Watch

func (s *SAM) Watch(ctx context.Context, responsive bool, onActivity func()) error

Watch blocks until ctx is cancelled.

type Snapshot

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

Snapshot remembers the last value of each button and axis of a polled device so a change can be told from a held position.

func NewSnapshot

func NewSnapshot() *Snapshot

NewSnapshot returns an empty snapshot.

func (*Snapshot) Axis

func (s *Snapshot) Axis(key uint32, value, deadzone int32) bool

Axis records an axis value and reports whether it moved more than deadzone from the last value that counted. Small drift never accumulates into activity because the reference only advances when it is exceeded.

func (*Snapshot) Button

func (s *Snapshot) Button(key uint32, value int32) bool

Button records a button value and reports whether it changed. The first value seen for a key is a baseline, not activity.

type Throttle

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

Throttle forwards at most one call per interval.

func NewThrottle

func NewThrottle(clock clockwork.Clock, interval time.Duration, fn func()) *Throttle

NewThrottle returns a Throttle that calls fn no more often than interval.

func (*Throttle) Trigger

func (t *Throttle) Trigger()

Trigger records activity and calls fn unless it already did within the interval. fn runs outside the throttle's lock.

Jump to

Keyboard shortcuts

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