elkowar / eww

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

[BUG] Stack selection index not persisting #1192

Closed koalagang closed 2 weeks ago

koalagang commented 2 weeks ago

Checklist before submitting an issue

Description of the bug

Not sure whether or not this is a bug or a feature but it seems that the index of a stack is reset whenever the window is closed, even if the index is set using a variable.

Reproducing the issue

Here is a minimal config. It's designed so that I can click the button to enable do not disturb mode in mako and then transitions into a different colour so that I can see that it is turned on. This works by setting the selection index to be a variable and then updating the variable, causing a different widget in the stack to show. However, when I close the window and later re-open it, the index is reset to 0 despite the variable's (dnd_toggle) value not having changed.

scss:

.button_enabled {
    color: #1e1e2e;
    background-color: #f2cdcd;
    border-radius: 10px;
    padding: 10px;
    padding-left: 15px;
    padding-right: 15px;
    margin: 2px;
}
.button_disabled {
    color: #f2cdcd;
    background-color: #1e1e2e;
    border: 1px solid #cdd6f4;
    border-radius: 10px;
    padding: 10px;
    padding-left: 15px;
    padding-right: 15px;
    margin: 2px;
}

yuck:

(defvar dnd_toggle 0)
(defwidget dnd []
  (stack
     :transition "crossfade"
     :same-size true
     :selected dnd_toggle
     (button
       :class "button_disabled"
       :onclick "${EWW_CMD} update dnd_toggle=1 && makoctl mode -a dnd"
      "󰍷\  Do Not Disturb")
     (button
       :class "button_enabled"
       :onclick "${EWW_CMD} update dnd_toggle=0 && makoctl mode -r dnd"
      "󰍷\  Do Not Disturb")))

(defwindow settings_menu
  :monitor 0
  :exclusive false
  :stacking "overlay"
  :geometry (geometry
             :x 4
             :y 4
             :anchor "top right")
  (eventbox
    :onhoverlost "${EWW_CMD} close settings_menu"
    (box
            (box :orientation "v"
            ; other buttons that function the same way but I've commented out for brevity
            ; (wifi)
             (dnd)
            ; (power))
            (box :orientation "v"
            ; (vpn)
            ; (nightlight)
            ; (caffeine)
            ))))

(defwidget settings []
  (eventbox
    :onhover "${EWW_CMD} open settings_menu"
    :cursor "pointer"
    (box
      :class "widgets"
      :halign "end"
      (box
        "󰇘"))))

Expected behaviour

I would expect the stack's selection index to remain exactly the value of the variable dnd_toggle even when I close and re-open the window.

Additional context

2024-09-05_17-20-59 2024-09-05_17-25-04

w-lfchen commented 2 weeks ago

@ovalkonia you recently worked on the stack widget. are you by any chance able to look into this ^^'? if not, don't worry about it

@koalagang as a workaround (and something that is probably more efficient as well), you should be able to use the following config (not tested, but should you give an idea):

(defvar dnd_toggle false)
(defwidget dnd []
  (button
    :class {dnd_toggle ? "button_enabled" : "button_disabled"}
    :onclick "${EWW_CMD} update dnd_toggle=${!dnd_toggle} && makoctl mode -t dnd"
    "󰍷\  Do Not Disturb"))

i'll look into this if noone else does so, but i'm currently a bit busy so this might take a while

by the way, that menu looks really neat! (i will take inspiration from it if i ever find the energy to rice again) and for a vpn connection, id recommend looking into toggling network manager connections, they have a vpn type, this might work. just wanted to note that on the offchance that it helps ^^

ovalkonia commented 2 weeks ago

As @w-lfchen mentioned, there's no need for the stack widget here. Although, I'm not sure if that's a problem with the stack widget itself. Unfortunately, I was not able to reproduce the issue with the following configuration:

eww.yuck:

(defwidget settings []
    (eventbox
        :onhover "${EWW_CMD} open some_menu"
        (label :text "settings beep boop!")
    )
)

(defwindow bar
    :monitor "0"
    :geometry (geometry
        :x "0"
        :y "0"
        :width "100%"
        :height "35px"
        :anchor "top center"
    )
    :exclusive "true"
    (settings)
)

(defvar stack_index "0")
(defwidget stack_test []
    (stack
        :selected {stack_index}
        (label :class "red" :text "red")
        (label :class "green" :text "green")
    )
)

(defwindow some_menu
    :monitor "0"
    :geometry (geometry
        :x "0"
        :y "0"
        :width "100%"
        :height "35px"
        :anchor "top center"
    )
    :exclusive "false"
    (eventbox
        :onhoverlost "${EWW_CMD} close some_menu"
        :onclick "${EWW_CMD} update stack_index=${(stack_index + 1) % 2}"
        (stack_test)
    )
)

eww.scss:

window {
    background-color: #282828;
    color: #ebdbb2;
}

.red {
    color: #ff0000;
}

.green {
    color: #00ff00;
}

It's the same thing you have, right? With this configuration everything works as expected. Whether red or green is chosen, it stays the same even after closing the window. No sure why it doesn't work in your case. Could you provide some more context, maybe some bare minimum configuration with which it fails? I could look into that

w-lfchen commented 2 weeks ago

i didn't test the config earlier, it seems to be working for me as well which version of eww are you using?

koalagang commented 2 weeks ago

@w-lfchen

@koalagang as a workaround (and something that is probably more efficient as well), you should be able to use the following config (not tested, but should you give an idea):

(defvar dnd_toggle false)
(defwidget dnd []
  (button
    :class {dnd_toggle ? "button_enabled" : "button_disabled"}
    :onclick "${EWW_CMD} update dnd_toggle=${!dnd_toggle} && makoctl mode -t dnd"
    "󰍷\  Do Not Disturb"))

This works beautifully! So glad I filed this issue. :D I didn't know it was possible to write conditional statements in yuck. Guess I must have overlooked some part of the documentation... I'll just use this method for my config instead of the stack but I'm willing to work through the issue anyway in case anyone else has difficulties with the stack in the future.

Edit: actually, I forgot that I wanted to keep the animation which the stack provides. Also, when using your suggested method, the button seems to change size (because it doesn't have the :same-size option that the stack does).

by the way, that menu looks really neat! (i will take inspiration from it if i ever find the energy to rice again) and for a vpn connection, id recommend looking into toggling network manager connections, they have a vpn type, this might work. just wanted to note that on the offchance that it helps ^^

Thanks for the compliment. That put a smile on my face. 😄 I don't actually use network manager (just bare iwd, networkd and resolved) and will probably see if I can interface with my VPN provider through their cli utility or via wireguard (have not actually installed and set it up yet) but thanks anyway. :)

@ovalkonia

It's the same thing you have, right? With this configuration everything works as expected. Whether red or green is chosen, it stays the same even after closing the window. No sure why it doesn't work in your case. Could you provide some more context, maybe some bare minimum configuration with which it fails? I could look into that

Strange. I just tested your config and on my end it has the same issue as with my config. I click and it switches from red to green. Then I move my cursor away so that it disappears onhoverlost and then hover over it again and it has gone back to red. Apologies if you didn't manage to test out my initially submitted config btw. That was my attempt at writing a minimum config. Here's attempt number 2 that I wrote separately instead of ripping code straight out of my dotfiles.

yuck

(defvar dnd_toggle 0)
(defwidget dnd []
  (stack
     :transition "crossfade"
     :same-size true
     :selected dnd_toggle
     (button
       :class "button_disabled"
       :onclick "${EWW_CMD} update dnd_toggle=1"
      "Do Not Disturb")
     (button
       :class "button_enabled"
       :onclick "${EWW_CMD} update dnd_toggle=0"
      "Do Not Disturb")))

(defwidget settings []
  (eventbox
    :onhover "${EWW_CMD} open settings_menu"
    :cursor "pointer"
      (box
        "Hover over me!")))

(defwindow settings_menu
  :monitor 0
  :exclusive false
  :stacking "overlay"
  :geometry (geometry
             ; size of tiling window gaps
             :x 4
             :y 4
             :anchor "top center")
  (eventbox
    :onhoverlost "${EWW_CMD} close settings_menu"
    (box
      (dnd))))

(defwindow bar
    :monitor 0
    :stacking "fg"
    :exclusive true
    :geometry (geometry
               :anchor "top center"
               :width "100%"
               :height "0%")
    (box
          :halign "center"
            (settings)))

scss

.button_enabled {
    color: white;
    background-color: black;
}
.button_disabled {
    color: black;
    background-color: white;
}

The issue persists with this configuration too.

@w-lfchen

i didn't test the config earlier, it seems to be working for me as well which version of eww are you using?

0.6.0

w-lfchen commented 2 weeks ago

the relevant documentation for the expression bit would be here, glad to help ^^

are you able to try building from master and seeing whether everything works there? i've been using that and release 0.6.0 is a bit old at this point ^^

i'll look into a version bump soonish, don't think elkowar would be opposed there, but there are some things that should be resolved first

koalagang commented 2 weeks ago

are you able to try building from master and seeing whether everything works there?

I'm still using my puny ThinkPad T420 so I don't think that would be able to handle compiling eww. Maybe in a few days, though, as I have bought a new, more powerful laptop.

Btw I made an edit to my comment. I'll still consider using your method but I might still want to use the stack because I really like the transition animation. 😄

Edit: just noticed that you're a fellow nix user. :) Edit 2: maybe as a solution to me wanting the animation, Elkowar or someone else who knows rust could write an option to make buttons have an animation if they change class.

w-lfchen commented 2 weeks ago

your config, your choice obviously ^^ i don't think i'd have a trustworthy way to share a compiled binary with you right now, so i guess we'll have to wait.

the version in nixpkgs is a bit more up to date however, i'm guessing that #1119 fixes your issue, but that commit is not yet included in the version there

i'm guessing you could hack together a button animation using scss somehow, but i don't know enough scss for that

ovalkonia commented 2 weeks ago

Tested this under eww 0.6.0. It indeed does not work as expected. I will try to find the point where it got fixed

w-lfchen commented 2 weeks ago

@ovalkonia try https://github.com/elkowar/eww/commit/367363975e29c8eedfd63d3fbe717d3ac768a25d ^^

ovalkonia commented 2 weeks ago

@ovalkonia try 3673639 ^^

Yep, works under https://github.com/elkowar/eww/commit/367363975e29c8eedfd63d3fbe717d3ac768a25d. Doesn't work before the fix. Didn't expect it to be this one, but I guess why not

koalagang commented 2 weeks ago

Okay, so I guess I just have to wait until the next version bump?

ovalkonia commented 2 weeks ago

Okay, so I guess I just have to wait until the next version bump?

Pretty much. Or you could install the git version)

w-lfchen commented 2 weeks ago

the git version would compile from source i think i mean you could try subjecting your laptop to it

if your nix config uses flakes, you can just use the overlay

feel free to ask if you need help with nix since i wrote the flake in its current form ^^

koalagang commented 2 weeks ago

if your nix config uses flakes, you can just use the overlay

That's true. I may give that a go in a few days once I've moved over to my new laptop. But I can be patient and wait for the next version (although by the looks of the releases page, it seems like they don't come that often so maybe I'm not patient enough for that).

w-lfchen commented 2 weeks ago

sure thing!

i'd ask you to close this issue since it seems to be resolved on master, i'll bump it once an update in nixpkgs happens (if i don't forget it ^^') should that update not fix it, feel free to reopen the issue!

ovalkonia commented 2 weeks ago

@koalagang btw, I think you can achieve the same transition using css only. It should work with gtk's css and it'd be more flexible then using the stack widget

koalagang commented 2 weeks ago

@koalagang btw, I think you can achieve the same transition using css only. It should work with gtk's css and it'd be more flexible then using the stack widget

I may give that a go. I don't actually know any css beyond the very basic stuff in my eww.scss, though. Would you be able to write me an example to work with? If not, that's fine, I'll consult the gtk css documentation. Am I looking in the right place?

Edit: nvm. That was extremely easy. Just added transition: color 0.5s ease, background-color 0.5s ease; to .button_enabled and .button_disabled. I still have the issue of the button changing size, though. Edit 2: fixed the issue with the button changing size. The one class had a border and the other didn't so I just changed it so they both have a border so they're exactly the same size now.

ovalkonia commented 2 weeks ago

Would you be able to write me an example to work with?

Too late, but I will post it anyway. Take a look at the configuration I tested before, but this time without the stack widget:

eww.yuck:

(defwidget settings []
    (eventbox
        :onhover "${EWW_CMD} open some_menu"
        (label :text "settings beep boop!")
    )
)

(defwindow bar
    :monitor "0"
    :geometry (geometry
        :x "0"
        :y "0"
        :width "100%"
        :height "35px"
        :anchor "top center"
    )
    :exclusive "true"
    (settings)
)

(defvar stack_toggle "false")
(defwindow some_menu
    :monitor "0"
    :geometry (geometry
        :x "0"
        :y "0"
        :width "100%"
        :height "35px"
        :anchor "top center"
    )
    :exclusive "false"
    (eventbox
        :onhoverlost "${EWW_CMD} close some_menu"
        :onclick "${EWW_CMD} update stack_toggle=${!stack_toggle}"
        (label :class "${stack_toggle ? "red" : "green"} transition-class" :text "some text beep boop!")
    )
)

eww.scss:

window {
    background-color: #282828;
    color: #ebdbb2;
}

.transition-class {
    transition: 0.8s cubic-bezier(0.25, 0.1, 0.25, 1);
}

.red {
    color: #ff0000;
}

.green {
    color: #00ff00;
}

It's kind of a slow transition from red green and vice versa, but of course you can change the duration, curve of change and even delay of it. Take a look here for more info: https://developer.mozilla.org/en-US/docs/Web/CSS/transition