jD91mZM2/xidlehook

Feature Request: Identified timers

rschmukler opened this issue · 9 comments

Hey! Thanks for all of your work on this project! It has been fantastic to use.

I recently released caffeinate which is inspired by a similarly named MacOS tool. The MacOS one has some nice features that allow you to conditionally enable / disable which timers are disabled / enabled. Eg. caffeinate could only prevent the system from sleeping, but not from the screen turning off.

I was wondering if you'd be open to extending the timers API to take identifiers, and the socket API to being able to selectively enable and disable them. To maintain compatibility we could use the existing command bytes to still disable the "primary" timer, but add new commands that take the name of the timer.

Something like:

xidlehook --timer display-off 180 "xset dpms force off" "" --timer sleep 300 "systemctl suspend" ""

Granted, for this to work, users would have to be using specific timer ID's that caffeinate knows about.

Another option would be to put some of the most common timers (screensaver, display-off, sleep) into xidlehook directly, which would then have the ID hardcoded, offering a perhaps more beginner friendly API.

An example w/ both a named timer, and built in timers:

xidlehook --display-off 60 --sleep 300 --timer lock 100 "~/scripts/lock.sh" ""

This would enable me to develop features like:

caffeinate --only=sleep,lock --timer 300

Just wanted to see if you were open to these kinds of changes so that perhaps I could submit a PR.

Thanks again!

I think that makes sense, thanks for the idea! I don't have much time so a PR would be amazing :)

As we're pre-1.0.0, compatibility isn't a huge concern. But, if you want compatibility: The primary field could be replaced by a general "ID" field, where IDs can be reused (at least IDs named "normal"), and the socket API could input the name of the timer somehow (but default to "primary"...)

Perhaps the idea of "name" could also be changed to "tags", where you can comma-separate tags. Hence you could say "primary,lock" to both get the friendly tag "lock" and still have it be the default timer.

Another idea would be to implicitly index each timer based on ordering, like 0, 1, 2, etc. Then caffeinate could somehow list all timers and choose one based on the ID... I don't know. I just thought having a number as ID would be easier and neater for the API.

Thanks for the response! If I get some time I’ll play around with it and see if I can get us a starting point to work from. Do you have any thoughts regarding the baked in common use cases as flags? (Eg. Suspend, display-off, etc). I suppose that’s a superset of the functionality proposed here so I could start with the identifiable timers and then we can see about the rest.

I dislike the idea of baking in common use-cases. It's easy to go from there and start treating them separately and suddenly we're no longer general-purpose. The original xidlehook briefly got --timer2 for a second timer instead of allowing an arbitrary amount of timers (since "who'd need more than 2 timers?"), which is an example of a mistake made based on the assumption of use-cases.

Makes sense! I'll take care of documenting the appropriate timer settings as part of caffeinate's setup then.

I like your idea of using tags (as opposed to auto-incrementing IDs) because it would allow for timers to be parts of multiple groups, which I could see being useful. It also feels less fragile than positional semantics.

Thanks again for the consideration. Hope to have a PR in the next week or so.

So, I've been thinking. What do you think if, instead of making xidlehook smarter, we make it dumber? Hear me out here: The unix philosophy is good, right? People can mix and match tools however they want, and that's great. So what if xidlehook becomes a simple command line tool that can be started or stopped instead of enabled/disabled, or a library that allows one to make their own xidlehook front-ends?

I'm not opposed to that line of thinking at all. In the context of what that implies for this type of feature, what do you envision the approach to look like?

Do multiple identifiable timers become multiple instances of the application running with different sockets? Or is it even dumber than that? Do tools like caffeinate then become concerned with being the daemon? What about things like preventing sleep when in full-screen, etc?

I like the idea, I'd just like some more clarification regarding where you envision the boundaries being.

I have been working on this for the past two days, and just launched a WIP merge request over at GitLab so you can track my progress.

Do multiple identifiable timers become multiple instances of the application running with different sockets?

I did not envision it being quite that dumb :)

Do tools like caffeinate then become concerned with being the daemon?

That is what I had in mind, yes. That way you can control absolutely every step of the process.

What about things like preventing sleep when in full-screen, etc?

These have been extracted out into "modules", aka pluggable instances of a trait that can compose together into one bigger module and used from the main xidlehook instance. There's still only a very limiting modules API (good enough for the default --not-when-*) but it can be expanded a lot in the future.

Gonna hijack this thread for letting all related issues in on my progress as well:

#30, #29

Yeah this is fixed now, I forgot to clean up the issue list after !6