elkowar / eww

ElKowars wacky widgets
https://elkowar.github.io/eww
MIT License
9.3k stars 382 forks source link

[FEATURE] `eww force-poll <pollvar>` command #673

Open shouya opened 1 year ago

shouya commented 1 year ago

Description of the requested feature

Currently, the defpoll variable can only be triggered on a fixed interval. It is not possible to tell eww to refresh the value of a poll variable on demand. I think it would be a convenient feature to add if there's a subcommand that does it.

I can think of two scenarios which could be useful.

In the first scenario, I'm imagining a volume widget that somewhat looks like this:

(defpoll curr-volume
    :interval "1m"
    `awk -F"[][]" '/Left:/ { print $2 }' <(amixer sget Master)`)

(defwidget volume []
  (eventbox
   :onscrollup "amixer -q sset Master 3%+; eww force-poll curr-volume"
   :onscrolldown "amixer -q sset Master 3%+; eww force-poll curr-volume"
   (label :text curr-volume)))

(I'm using the made-up :onscroll{up,down} events to illustrate my point. BTW those are also reasonable events to be supported in the future.)

It would be kind of wasteful to poll the volume more frequently because the volume doesn't change very often. It would be nice to be able to update it when we know it's been updated so that the widget appears responsive. Alternatively, I know it's possible to call eww update curr-volume="awk ...", but that would be too long to fit into a simple string. It's also possible to extract all the shell commands into a script, but writing them like this is concise enough.

In the second scenario, I could be writing a sort of collapsed array of indicators which should be revealed on hover:

(defpoll dunst-paused
    :interval "1m"
    `dunstctl is-paused`)

(defvar status-icons-revealed false)
(defwidget status-icons []
  (eventbox
   :onhover     "eww update status-icons-revealed=true; eww force-poll dunst-paused"
   :onhoverlost "eww update status-icons-revealed=false"

   (box
    :space-evenly false
    (label :text "Show statues")

    (revealer
     :reveal status-icons-revealed
     :transition "slideleft"
     (label :text "dunst is ${dunst-paused ? 'paused' : 'active'}")
     )

    ;; we can put more statuses here
    )))

Since the indicators here are by default hidden, I may want to avoid updating dunst-paused periodically. However, when I hover on the "Show status" label, it's clear that my intention is to see the up-to-date statuses, which includes dunst-paused, so it makes sense to only update the variable when I hover on the "Show status" label.

What do you think?

Proposed configuration syntax

No response

Additional context

No response

migmolrod commented 1 year ago

I like your idea.

It already works, sortof, since you can set the defpoll as any other defvar.

So, in your first scenario:

(scale :onchange "eww update curr-volume={}; amixer -D pulse sset Master {}%")

should work.

But, at least in my case, the bar feels "bouncy". I mean, if you scroll-up to increase volume, the volume bar first goes up to the new value, then very briefly goes back to the previous value and eventually it goes up again to the new value. It's quite strange. Since we are setting the value and using it as the slider value (while the slider already sets it internally at the same time), it doesn't work too well.

Your second scenario should work with this:

   :onhover     "eww update status-icons-revealed=true; eww update dunst-paused=$(dunstctl is-paused)"
   :onhoverlost "eww update status-icons-revealed=false; eww update dunst-paused=$(dunstctl is-paused)"

It works but is a bit ugly (since you're repeating the same command in several places) and feels hacky. So it would be really nice if we could manually trigger polls, like you suggest.

Ocyss commented 1 year ago

I also like this feature so I can condense my very long commands

elkowar commented 1 year ago

I've long been unsure if I actually want to support this, but at this point I think it definitely makes sense -- there's too many use cases for "needs to be updated regularly, but sometimes we know when it updates and want the value immediately" that are too common to ignore (i.e. volume indicator, brightness indicator, etc -- should all update immediately when the volume is changed via keybinds, for example. duplicating the logic to get the volume should be unnecessary.

migmolrod commented 1 year ago

@elkowar very nice. I don't know any Rust so I doubt I can help with the actual coding. But here you have a beta tester for this if you ever need one.