Skip to content

Latest commit

 

History

History

README.md

watcher

watcher is a module that observes window, keyboard and mouse activity. Canonically it is intended for use in contextually switching device page to match the current application, but can also be used to log activity using the worklog module.

watcher periodically polls the OS for active window and last activity time. The results of this are passed to a CEL evaluation as the following object:

{
	"time":   <timestamp>,
	"period": <duration>,

	"wid":        <int>,
	"pid":        <int>,
	"name":       <string>,
	"class":      <string>,
	"window":     <string>,
	"last_input": <timestamp>,
	"locked":     <bool>,
	"last": {
		"wid":        <int>,
		"pid":        <int>,
		"name":       <string>,
		"class":      <string>,
		"window":     <string>,
		"last_input": <timestamp>,
		"locked":     <bool>,
	},
}

The resulting evaluation is then send as an RPC message if it has a string field "method". If the evaluation has a field "uid" corresponding to an rpc.UID value the message is forwarded as a "method" notification to the daemon identified by that UID. Otherwise it is passed to the kernel to handle.

Example configuration fragment that pages to the "dev" page when "sublime_text" or "sublime_merge" is the active window (requires a kernel configuration fragment with an additional service — below):

# Watcher module component: get active window and activity.
[module.watcher]
path = "watcher"
log_mode = "log"
log_level = "info"
log_add_source = false

[module.watcher.options]
polling = "1s"

rules.paging = """
{
	"sublime_text":  "dev",
	"sublime_merge": "dev",
}.as(page_for, !(last.name in page_for || name in page_for) || page_for[?name] == page_for[?last.name] ? {} : {
	"method": "page",
	"params": {
		"page":    name in page_for ? page_for[name] : "default",
		"service": {"service":"kernel_default_service"}
	},
})
"""

A rule may also be used to blank the device when the screen is locked.

rules.blanking = """
locked == last.locked ? {} : {
	"method": "sleep",
	"params": {
		"action":  "set",
		"state":   locked ? "locked" : "awake",
		"service": {"service":"kernel_default_service"}
	},
}
"""

These depend on a kernel service to assign a device. This can be set up in the kernel configuration by adding the following lines.

# Define a default kernel service.
[service.kernel_default_service]
serial = ""

Where serial is either default or the target device's serial.

See the example for the worklog to see how a non-kernel call is handled.

Detailers

watcher obtains details from the GUI environment. On Linux, by default this is determined from the XDG_SESSION_TYPE and XDG_CURRENT_DESKTOP environment variables, but is configurable if auto-detection does not work.

The configuration is made in the options.strategy configuration field.

[module.watcher.options]
strategy = "xorg"
polling = "1s"

Currently, available Linux detailers are:

On MacOS, details are obtained from the OS and no configuration is required.

CEL optional types

The CEL environment enables the CEL optional types library, version 1, and a function to obtain the current sleep state of a device and its last button event time, sleep_state(<string>) -> <map<string,dyn>> using the sleep RPC method.

CEL debugging

The watcher module can be invoked with a debug option that is a path to a txtar file containing a prg file and a data file. The prg file is the CEL program to be run and the data file is the data that will be passed to the program. The structure of the data is JSON as emitted by watcher as a log message on CEL program evaluation failure. To manually construct data, the object passed to CEL is in the tick, period, details and last fields.