Create race free idle/active watch API
The current DBus API has a number of race condition, some of them are rather obscure. All of these were seen in the g-s-d test suite:
- Registering an active watch takes time, effectively hiding any activity between the user becoming idle and the active watch being registered
- Mutter might send active and idle notifications in the wrong order, scenario:
- Session is idle for 10s
- Application has an active watch registered
- A setting is changed
- Application registers 5s idle watch
- Mutter starts processing idle watch registration
- X server has activity (simulated shift click)
- Mutter finishes processing idle watch registration; does g_idle_add to notify about idle time >=5s (meta_idle_monitor_xsync_make_watch)
- Mutter processes X events, notices activity
- Mutter fires activity watch from check_x11_watches, sending dbus message immediately
- Mutter processes idle handler and sends out the 5s idle notification
- Result: Application thinks the user is inactive for more than 5s
Yes, that seems to actually have happened: https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/jobs/23097
Anyway, the first race condition is much more problematic, and both of them could be solved with a proper API. The general idea for that API would be to remove the notion of an "active watch" but rather trigger idle watches on both edges (i.e. when user becomes idle for longer or becomes active again).
As a further improvement one could have one idle watch monitor multiple idle times. This would enable applications to correctly (and atomically) keep track of how long the user has been active. The DBus API could look like:
- AddIdleMonitor(array:uint64) -> uint32, uint64
- MonitorFired(uint32, uint64 edge)
- RemoveMonitor(uint32)
The application would e.g. register the times [120s, 240s]
meaning it wants to know in which inactivity time frame the user is ([0s..120s)
, [120s..240s)
, >= 240s
). The timestamp returned by AddIdleMonitor
and MonitorFired
would be the start of each range (i.e. 0s, 120s or 240s in this case).