elkowar / eww

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

[BUG] eww stop updating #363

Closed tramhao closed 2 years ago

tramhao commented 2 years ago

Checklist before submitting an issue

Describe the bug

I'm using eww as bar for leftwm. It works but always stop updating for no obvious reason that I can find. It'll work again if I close-all and open-many again. About 1 hour or 2 it'll happen. I have two screens. Configuration is as below:

workspaces = [
# external screen as main internal
{ x = 0, y = 0, width = 1080, height = 1920, id = 1},
{ x = 1080, y = 0, width = 1920, height = 1200, id = 0},
]

my monitor xrandr script:

intern=eDP-1
extern=DP-2

if xrandr | grep "$extern disconnected"; then
    xrandr --output "$extern" --off --output "$intern" --auto
else
    xrandr --output "$extern" --mode 1920x1200 --primary --pos 0x0 --output "$intern" --auto --rotate right --left-of "$extern"
fi

my eww configuration is as below:

(defwidget bar []
  (centerbox :orientation "h"
    (workspaces)
    ; (leftstuff)
    (music_widget)
    (rightstuff)))

; (defwidget leftstuff []
;   (box :class "sidestuff" :orientation "h" :space-evenly false :halign "start" 
;     (music_widget)
;     ))

; (deflisten window_title
;   "leftwm-state -w 0 -s '{{ window_title }}'")

 (defpoll window_title :interval "2s"
                       :initial ""
   "xdotool getactivewindow getwindowname")

(defwidget rightstuff []
  (box :class "sidestuff" :orientation "h" :space-evenly false :halign "end"
    ; mailupdatecmd
    (mailupdatewidget)
    ; newsupdatecmd
    (newsupdatewidget)
    ; archupdatecmd
    (archupdatewidget)
    ; eww_weatherupdatecmd
    (eww_weather_widget)
    (metric :label "🖥️"
            :value {EWW_CPU.avg}
            :onchange "")
    (metric :label "🧠"
            :value {EWW_RAM.used_mem_perc}
            :onchange "")
    (metric2  :label "🔊"
              :value eww_volume
              :onchange "pamixer --set-volume {} --allow-boost")
    ; (metric :label "💾"
    ;         :value {round((1 - (EWW_DISK["/"].free / EWW_DISK["/"].total)) * 100, 0)}
    ;         :onchange "")
    battery
    time
    (powerbutton)
    empty_space
    empty_space
    ))
    ; ))
;
; (defwidget workspaces []
    ; (box :class "workspaces"
         ; :orientation "h"
         ; :space-evenly true
         ; :halign "start"
         ; :spacing 10
            ; (button :class "ws-button-mine" :onclick "leftwm-command \"SendWorkspaceToTag 0 0\"" `1`)
            ; (button :class "ws-button-busy" :onclick "leftwm-command \"SendWorkspaceToTag 0 1\"" `2`)
            ; (button :class "ws-button-busy" :onclick "leftwm-command \"SendWorkspaceToTag 0 2\"" `3`)
            ; (button :class "ws-button" :onclick "leftwm-command \"SendWorkspaceToTag 0 3\"" `·`)
            ; (button :class "ws-button" :onclick "leftwm-command \"SendWorkspaceToTag 0 4\"" `·`)
            ; (button :class "ws-button" :onclick "leftwm-command \"SendWorkspaceToTag 0 5\"" `·`)
            ; (button :class "ws-button" :onclick "leftwm-command \"SendWorkspaceToTag 0 6\"" `·`)
            ; (button :class "ws-button" :onclick "leftwm-command \"SendWorkspaceToTag 0 7\"" `·`)
            ; (button :class "ws-button" :onclick "leftwm-command \"SendWorkspaceToTag 0 8\"" `·`)))

(defwidget workspaces []
  (box :class "workspaces"
       :orientation "h"
       :space-evenly false
       :halign "start"
       :spacing 10
    empty_space
    (literal :content {wm-tags})
    empty_space
    (box :class "window_title"
      (label :text window_title
           :limit-width 40))
    )
)

(defvar empty_space " ")

(defwidget music_widget []
  (box :class "music"
       :orientation "h"
       :space-evenly false
       :halign "start"
    (button :onclick "scripts/player-mpris.py play-pause"
            :onrightclick "scripts/player-mpris.py next"
            :onmiddleclick "scripts/player-mpris.py previous"
;            :timeout "5s"
      {music != "" ? "💿 ${music}" : ""})
    ))

(defwidget metric [label value onchange]
  (box :orientation "h"
       :class "metric"
       :space-evenly false
    (box :class "label" label)
    (scale :min 0
           :max 101
           :active {onchange != ""}
           :value value
           :onchange onchange)))

(defwidget metric2 [label value onchange]
  (box :orientation "h"
       :class "metric"
       :space-evenly false
    (box :class "label" label)
    (scale :min 0
           :max 151
           :active {onchange != ""}
           :value value
           :onchange onchange)))

(deflisten music :initial ""
  "scripts/player-mpris.py --format '{icon} {:t30:{artist}:} - {:t40:{title}:}'")
  ; "scripts/player-mpris.py --format '{icon} {:t20:{artist}:} - {:t20:{title}:}' || true")

; (deflisten music :initial ""
;   "playerctl --follow metadata --format '{{ artist }} - {{ title }}' || true")

; (deflisten volume :initial ""
;   "tail -F ~/.local/share/eww_volume.tmp")

(defpoll eww_volume :interval "2s"
                    :initial "80"
  "pamixer --get-volume || true")

(defpoll time :interval "60s"
  "date '+%d(%a),%H:%M'")

(defwidget archupdatewidget []
  (box :orientation "horizontal"
       :halign "center"
       :class "archupdate"
    ; archupdate 
    (button :onclick "WINIT_X11_SCALE_FACTOR=1 setsid -w -f alacritty -e scripts/archafter"
      arch)))

(defpoll archupdatecmd :interval "1h"
                       :initial ""
                       :visible false
  "scripts/archup")

(deflisten arch :initial ""
  `tail -F ~/.local/share/checkup.tmp 2>/dev/null`)

(defwidget mailupdatewidget []
  (box :orientation "horizontal"
       :halign "center"
       :class "mailupdate"
    (button :onclick "WINIT_X11_SCALE_FACTOR=1 setsid -w -f alacritty -e scripts/mailafter"
      mail)))

(defpoll mailupdatecmd :interval "2h"
                       :initial ""
                       :visible false
  "scripts/mailup")

(deflisten mail :initial ""
  `tail -F ~/.local/share/mailupdate.tmp 2>/dev/null`)

(defwidget newsupdatewidget []
  (box :orientation "horizontal"
       :halign "center"
       :class "newsupdate"
    (button :onclick "WINIT_X11_SCALE_FACTOR=1 setsid -w -f alacritty -e 'scripts/newsafter'"
      news)))

(defpoll newsupdatecmd :interval "2h"
                    :initial ""
                    :run-while "wget -q --spider example.org"
                    ; :run-while "!(pgrep newsboat)"
                    :timeout "30s"
                    :visible false
  "scripts/newsup")

(deflisten news :initial ""
  `tail -F ~/.local/share/newsupdate.tmp 2>/dev/null`)

(defpoll eww_weatherupdatecmd :interval "2h"
                              :initial ""
                              :visible false
  "scripts/weatherup")

(defwidget eww_weather_widget []
  (box :orientation "horizontal"
       :halign "center"
       :class "weather"
    (button :onclick "scripts/weatherup"
      eww_weather)))

(deflisten eww_weather 
  `tail -F ~/.local/share/weatherup.tmp 2>/dev/null`)

(defpoll battery :interval "60s"
  "scripts/sb-battery")

(defwidget powerbutton[]
  (box :orientation "horizontal"
       :halign "center"
    (button :onclick "scripts/sysact-leftwm" 
    ; (button :onclick "scripts/powermenu.sh" 
      " 🔘 ")))

(deflisten wm-tags
  "leftwm-state -w 0 -t ~/.config/leftwm/themes/current/template.liquid")

(defwindow bar0
  :monitor 0
  :windowtype "dock"
  :geometry (geometry :x "0%"
                      :y "0%"
                      :width "100%"
                      :height "20px"
                      :anchor "top center")
  :reserve (struts :side "top" :distance "20px")
  (bar))

(defwindow bar1
  :monitor 1
  :windowtype "dock"
  :geometry (geometry :x "0%"
                      :y "0%"
                      :width "100%"
                      :height "20px"
                      :anchor "top center")
  :reserve (struts :side "top" :distance "20px")
  (bar))

Reproducing the issue

As configuration above.

Expected behaviour

It should keep updating.

Additional context

If applicable, provide additional context or screenshots here I turned on --debug so the log is pretty long and I'll not post it but attach it instead. eww_L2hvbWUvdHJhbWhhby8uY29uZmlnL2V3dw==.log

tramhao commented 2 years ago

I use below script to launch eww:

eww daemon --debug & 

while [[ -z "$(eww windows | grep '[*]')" ]]; do
    index=0
    sizes=( $(leftwm-state -q -n -t $SCRIPTPATH/sizes.liquid | sed -r '/^\s*$/d' ) )
    for size in "${sizes[@]}"
    do
        eww open bar$index
        let index=index+1
    done
  # eww open-many left tags right
done
elkowar commented 2 years ago

by "not updating" do you mean that none of the variables get updated anymore (-> the bar doesn't change at all) or do only some of them not work anymore?

tramhao commented 2 years ago

nothing is changing. I mean the clock stopped(that's usually how I notice this problem). Also window title and workspace indicators are not changing when I switch desktop. volume is not refreshing also. CPU memory doesn't work either.

elkowar commented 2 years ago

interesting, I'll take a look at the log later! thanks for the report

VuiMuich commented 2 years ago

I can confirm this. Also in my experience (I have split my bar into three windows) the windows get stuck individually and can be revived by closing and opening them again. For a while I thought the fault might lay with leftwm state as it regularly occurs for me when switching to the Monocle layout, but that would not explain, why the window with Ram/Volume/WiFi/Time is affected as well, but following a different pattern I couldn't figure out yet.

Here is my config:

; Widgets
(defwidget tags []
    (workspaces))

(defwidget sidestuff_left []
    (box :class "sidestuff"
         :orientation "h"
         :space-evenly false
         :halign "start"
         :valign "start"
         :vexpand true
        (power-menu)
        (keyboard-layout)
        (ws-layout)))

(defwidget sidestuff_right []
    (box :class "sidestuff"
         :orientation "h"
         :space-evenly false
         :halign "end"
        (metric :label ""
                :label-class "icon"
                :value '${EWW_RAM.used_mem_perc}'
                :onchange "")
        (metric :label ""
                :label-class "icon"
                :value {wifi-signal != "" ? wifi-signal : "0.0"}
                :onchange "")
        (metric :label '${audio-icon}'
                :label-class {audio-icon == "" || audio-icon == "ﳌ" ? "icon-small" : "icon-smaller"}
                :value volume
                :onchange  "amixer -D pulse sset Master {}%")
        (metric :label {EWW_BATTERY["BAT0"].status == "Discharging" ? "" : "ﮣ"}
                :label-class {EWW_BATTERY["BAT0"].status == "Discharging" ? "icon"  : "icon-smaller"}
                :value  '${EWW_BATTERY["BAT0"].capacity}'
                :tooltip '${EWW_BATTERY["BAT0"].capacity}'
                :onchange "")
        (time)))

(defwidget workspaces []
    (box :class "workspaces"
         :orientation "h"
         :space-evenly true
         :halign "center"
        (literal :content {wm-tags})))

(defwidget power-menu []
    (box :class "power"
         :orientation "h"
         :space-evenly false
         :halign "start"
         :valign "start"
      (button :onclick "eww update pwmen-open=${!pwmen-open}" "襤")))
      ; (revealer :transition "slideright" :reveal pwmen-open (pwmen))))

(defwidget pwmen []
    (box :class "icon-key"
       :orientation "v"
       :space-evenly true
       :valign "start"
      (button :onclick "systemctl suspend" "鈴 Suspend")
      (button :onclick "systemctl hibernate" " Hibernate")
      (button :onclick "dm-tool switch-to-greeter" "שּ Swtich to Greeter")
      (button :onclick "dm-tool lock" " Lock")
      (button :onclick "loginctl kill-user $XDG_SESSION_ID" " Exit")
      (button :onclick "reboot" "敏 Reboot")
      (button :onclick "shutdown now" "襤 Shutdown")))

(defwidget keyboard-layout []
    (box :class "icon-key"
         :orientation "h"
         :space-evenly false
         :halign "start"
        {kbd-layout != "" ? kbd-layout : ""}))

(defwidget ws-layout []
    (box :class "ws-layout"
         :space-evenly false
         :halign "start" 
         :valign "start"
         :width 220
        (box :class "icon-ws-layout" "")
        (box {workspace-layout != "" ? workspace-layout : "n/a"})))

(defwidget metric [label label-class value onchange]
  (box :orientation "h"
       :class "metric"
       :space-evenly false
    (box :class label-class label)
    (scale :min 0
           :max 101
           :active {onchange != ""}
           :value value
           :onchange onchange)))

(defwidget time []
    (box :class "time"
        (button :onclick "eww open --toggle uhr" :class "icon-time" "")
        {hour + ":" + minute}))

(defwidget uhr []
    (box :class "uhr"
        {uhrwerk}))

(defwidget notes []
    (box :class "notes"
        {notes}))

; Variables
(defvar pwmen-open false)
; sliders
(deflisten audio-icon "scripts/getpa")
(defpoll volume :initial "50" :interval "16s" "scripts/getvol")
(defpoll wifi-signal :initial "0" :interval "10s" "scripts/getwifi")
(defpoll ssid :interval "10s" "nmcli -f IN-USE,SSID device wifi | awk '/^\*/{if (NR!=1) {print $2}}'")
; Time
(defpoll number_day :interval "5h" "date '+%d'")
(defpoll month :interval "10h" "date '+%b'")
(defpoll minute :interval "10s" "date '+%M'")
(defpoll hour :interval "1m" "date '+%H'")
(defpoll year_full :interval "15h" "date '+%Y'")
(deflisten uhrwerk "uhrwerk -t $HOME/Git/uhrwerk/src/time-in-words-templates/en_1.toml")
; WM and Keyboard state
(deflisten wm-tags 'leftwm-state -w 0 -t ~/.config/leftwm/themes/current/template.liquid')
(deflisten kbd-layout "scripts/get-kbd-layout")
(deflisten workspace-layout 'leftwm-state -w 0 -s "{{workspace.layout}}"')
; Notes
(deflisten notes "cat -n $HOME/todo.md")

; Windows
(defwindow left
           :monitor 0
           :windowtype "dock"
           :stacking "overlay"
           :geometry (geometry :x "21px"
                               :y "13px"
                               :width "295px"
                               ; :height "34px"
                               :height "44px" ; this is a workaround, as gtk is expanding the height to this anyways
                               :anchor "top left")
           :reserve (struts :side "top" :distance "55px")
    (sidestuff_left))

(defwindow tags
           :monitor 0
           :windowtype "dock"
           :geometry (geometry :x "0px"
                               :y "13px"
                               :width "19%"
                               ; :height "34px"
                               :height "44px" ; this is a workaround, as gtk is expanding the height to this anyways
                               :anchor "top center")
           :reserve (struts :side "top" :distance "55px")
    (tags))

(defwindow right
           :monitor 0
           :windowtype "dock"
           :geometry (geometry :x "-21px"
                               :y "13px"
                               :width "420px"
                               ; :height "34px"
                               :height "44px" ; this is a workaround, as gtk is expanding the height to this anyways
                               :anchor "top right")
           :reserve (struts :side "top" :distance "55px")
    (sidestuff_right))

(defwindow uhr
           :monitor 0
           :stacking "fg"
           :windowtype "dialog"
           :geometry (geometry :x "89px"
                               :y "-89px"
                               :width "600px"
                               :height "55"
                               :anchor "bottom left")

           :wm-ignore true
    (uhr))

(defwindow notes
           :monitor 0
           :stacking "bg"
           :windowtype "dialog"
           :geometry (geometry :x "-89px"
                               :y "89px"
                               :width "600px"
                               :height "600px"
                               :anchor "top right")
           :wm-ignore true
    (notes))

and since eww startup sequence got improved I start simply with:

 # start eww daemon
 eww daemon &

 #open eww windows
 eww open-many left tags right

further additions: As stated, it most of the time happens, when deflisten workspace-layout is about to be updated, especially with the value Monocle. In general I am thinking if I should move to deflisten on leftwm state -q as this prints a JSON formated state string on every update of the WM, so basically it should be possible to treat this like a magic variable an pick the desired value right in the relevant widget, right?

Here is an example of leftwm state (manually formatted newlines for better human readability):

leftwm state -q
{"window_title":"leftwm state -q /home/vuimuich/.config/leftwm/themes/current",
 "workspaces":[
   {
   "h":1440,
   "w":1280,
   "x":0,
   "y":0,
   "layout":"CenterMainBalanced",
   "index":0,
   "tags":[
      {"name":"","index":0,"mine":true,"visible":true,"focused":true,"busy":true},
      {"name":"","index":1,"mine":false,"visible":false,"focused":false,"busy":true},
      {"name":"","index":2,"mine":false,"visible":false,"focused":false,"busy":true},
      {"name":"","index":3,"mine":false,"visible":false,"focused":false,"busy":true},
      {"name":"ﲾ","index":4,"mine":false,"visible":false,"focused":false,"busy":true},
      {"name":"異","index":5,"mine":false,"visible":false,"focused":false,"busy":false},
      {"name":"","index":6,"mine":false,"visible":false,"focused":false,"busy":false},
      {"name":"ﭮ","index":7,"mine":false,"visible":true,"focused":false,"busy":true},
      {"name":"","index":8,"mine":false,"visible":false,"focused":false,"busy":false}
   ]},{
   "h":1440,
   "w":1280,
   "x":1280,
   "y":0,
   "layout":"MainAndDeck",
   "index":1,
   "tags":[
      {"name":"","index":0,"mine":false,"visible":true,"focused":true,"busy":true},
      {"name":"","index":1,"mine":false,"visible":false,"focused":false,"busy":true},
      {"name":"","index":2,"mine":false,"visible":false,"focused":false,"busy":true},
      {"name":"","index":3,"mine":false,"visible":false,"focused":false,"busy":true},
      {"name":"ﲾ","index":4,"mine":false,"visible":false,"focused":false,"busy":true},
      {"name":"異","index":5,"mine":false,"visible":false,"focused":false,"busy":false},
      {"name":"","index":6,"mine":false,"visible":false,"focused":false,"busy":false},
      {"name":"ﭮ","index":7,"mine":true,"visible":true,"focused":false,"busy":true},
      {"name":"","index":8,"mine":false,"visible":false,"focused":false,"busy":false}]
   }]
}
VuiMuich commented 2 years ago

I updated my yuck with these snippets:

(defwidget ws-layout []
    (box :class "ws-layout"
         :space-evenly false
         :halign "start" 
         :valign "start"
         :width 220
        (box :class "icon-ws-layout" "")
        (box {wmstate.workspaces[0].layout ?: "n/a"})))

(deflisten wmstate "leftwm state")

and it seems to be working more solid. Next, I'm gonna replace the literal in the ws-tags widget. I'm just not sure though, if this template is reproducible in yuck simple expressions:

% assign mine_open = ' (button :class "ws-button-mine" :onclick "leftwm-command \"SendWorkspaceToTag ' %}
{% assign visible_open = ' (button :class "ws-button-visible" :onclick "leftwm-command \"SendWorkspaceToTag ' %}
{% assign busy_open = ' (button :class "ws-button-busy" :onclick "leftwm-command \"SendWorkspaceToTag ' %}
{% assign close = '`)' %}
{% assign unoccupied = ' (button :class "ws-button" :onclick "leftwm-command \"SendWorkspaceToTag ' %}

{{'(box :orientation "h" :class "workspaces" :space-evenly "true" :halign "center"'}}
{% for tag in workspace.tags %}
{% if tag.mine %}
  {{mine_open}}{{workspace.index | append: ' ' | append: tag.index | append: '\"" `'}}{{ tag.name }}{{close}}
{% elsif tag.visible  %}
{{visible_open}}{{workspace.index | append: ' ' | append: tag.index | append: '\"" `'}}{{ tag.name }}{{close}}
{% elsif tag.busy  %}
{{busy_open}}{{workspace.index | append: ' ' | append: tag.index | append: '\"" `'}}{{ tag.name }}{{close}}
{% else tag.visible  %}
{{unoccupied}}{{workspace.index | append: ' ' | append: tag.index | append: '\"" `'}}{{ "·" }}{{close}}
{% endif %}
{% endfor %}
{{")"}}
VuiMuich commented 2 years ago

The attempt from the last post is only a minor improvement, unfortunately. Though I learned, that it seems to be sufficient to enforce the a redraw of the dock type windows e.g. by full-screening some window, when returning from full screen the eww windows update as usual. So my guess now is, that either eww is waiting for the WM to tell it to redraw or eww misses to tell the WM it got updated and wants to redraw. Since variables appear not to be updated I think the first one is more plausible to me.

tramhao commented 2 years ago

I don't have the layout indicator, but my toolbar stop updating still several times a day.

elkowar commented 2 years ago

Is this still an issue? this type of issue, especially with deflisten stuff, kind of makes it sound like some sort of buffering issue with your deflisten. Eww should redraw regardless of what the WM tells it to, and variables (as per eww state) will definitely update once eww gets any reason to update them. If they don't update as part of a deflisten, either your deflisten script is crashing, or it's buffering weirdly and thus not notifying eww of new values

VuiMuich commented 2 years ago

Yeah, this sort of still is an issue. I'll try to gather some updated info on the topic this week.

In short: I still use the deflisten as above, leftwm-state prints a JSON string to STDOUT on every relevend WM update (i.e. focus change, window move etc. basically on each redraw event), this is my curren eww.yuck (non-relevant stuff ommited):

(defwidget sidestuff_left []
    (box :class "sidestuff"
         :orientation "h"
         :space-evenly false
         :halign "center"
         :valign "start"
         :width 327
        (keyboard-layout)
        (ws-layout)))

(defwidget tags []
    (box :class "workspaces"
         :orientation "h"
         :space-evenly true
         :halign "center"
      (box
        (for tag in '${wmstate.workspaces[0].tags}'
          (button
            :class {tag.mine ? "ws-button-mine" :
                    tag.visible ? "ws-button-visible" :
                    tag.busy ? "ws-button-busy" : "ws-button"}
            :onclick "leftwm-command \"SendWorkspaceToTag 0 ${tag.index}\""
            {!tag.mine && !tag.busy && !tag.visible ?  "·" : "${tag.name}"})))))

(defwidget ws-layout []
    (box :class "ws-layout"
         :space-evenly false
         :halign "start" 
         :valign "start"
         :width 220
        (box :class "icon-ws-layout" "")
        (box {wmstate.workspaces[0].layout ?: "n/a"})))

(deflisten wmstate 
           :initial '{"workspaces":[{"layout":"", "tags":[{"name":"", "index":0, "mine":false, "busy":false, "visible":false}]}]}'
           "leftwm state")

(defwindow left
           :monitor 0
           :windowtype "dock"
           :geometry (geometry :x "21px"
                               :y "10px"
                               :width "327px"
                               :height "44px" ; this is a workaround, as gtk is expanding the height to this anyways
                               :anchor "top left")
           :reserve (struts :side "top" :distance "55px")
    (sidestuff_left))

(defwindow tags
           :monitor 0
           :windowtype "dock"
           :geometry (geometry :x "0px"
                               :y "10px"
                               :width "456px"
                               :height "44px" ; this is a workaround, as gtk is expanding the height to this anyways
                               :anchor "top center")
           :reserve (struts :side "top" :distance "55px")
    (tags))

After a while the updates of the tags window lack several seconds and with some actions that I still have to identify which, it happens the onclick command won't be executed. Usually toggling the window off and on again or issuing eww reload fixes this both.

As said, I will try to get more details sometime this week.

elkowar commented 2 years ago

do the eww logs (with --debug) show the expected events every time leftwm-state gives a new value? if not, then that does indicate a buffering related issue or something like that

VuiMuich commented 2 years ago

I have a terminal window with an --debug session of eww open since the previous post. The issue has not occured since. It"s a classic :see_no_evil:

Edit: ok, the onclick thing seems to appear always, when some window has been in fullscreen. So this might actually also be an WM issue. Edit2: as far as I can tell the Output of leftwm state remains instant at all times.

elkowar commented 2 years ago

so everything works?

VuiMuich commented 2 years ago

I am still on the lookout for the lag on the update of the :class of the tags. I hope I find something soon and let you know if this actually persists or if this issue can be closed.

VuiMuich commented 2 years ago

Haven't been able to reproduce it in the last two days. So I guess you can close it. If it will happen eventually, I will return with fresh info.

BTW: regarding the onclick issue, this was actually a LeftWM buq, that has a PR to fix open.