Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] set power source type on listener for laptops #67

Open
AmirAref opened this issue Jun 6, 2024 · 13 comments
Open

[Feature] set power source type on listener for laptops #67

AmirAref opened this issue Jun 6, 2024 · 13 comments

Comments

@AmirAref
Copy link

AmirAref commented Jun 6, 2024

Hi,
thanks for your nice program, I think it could be so helpful to add a parameter on listener configuration for laptops to define different listeners for AC power or Battery power.
For example, I want to set more time to go to sleep on AC power :

listener {
    on-power = battery # on battery power
    timeout = 600
    on-power = systemctl suspend
}

listener {
    on-power = AC # on AC power
    timeout = 1800
    on-power = systemctl suspend
}
@fufexan
Copy link
Member

fufexan commented Jun 6, 2024

I've actually thought about this before, and I plan to implement it (though I don't have as much time as I'd like to do that).
I've envisioned a different syntax:

listener {
    timeouts = 600, 1800 # BATT, AC
    command = systemctl suspend
}

or

listener {
    timeout-battery = 600
    timeout-ac = 1800
    command = systemctl suspend
}

in which case timeout would still be used as fallback if you want both BAT/AC timeouts to be the same.

@AmirAref
Copy link
Author

AmirAref commented Jun 6, 2024

I think the second syntax is better, also it should to be considered that for example someone may not want to set any listener for sleep or lock commands on AC power but do it on Battery.

So something like this behavior could be efficient :

  • timeout : both sources
  • timeout-ac : only AC power
  • timeout-bat : only Battery power

Which means a listener can have only one of AC or battery timeouts, or both of them.

@fufexan
Copy link
Member

fufexan commented Jun 6, 2024

I have a practical usecase for setting both ac and bat, and that is DPMS.

@stinobook
Copy link

stinobook commented Jun 8, 2024

Hello,

Quick question in the meantime:
With hypridle running, is it possible to 'reload' the config file or add a listener ?
Or does it need to be killed and restarted? this way we could just have 2 hypridle configs, one for battery power and one for mains :)

FYI atm i do it like this:
file /etc/acpi/handler.sh
and just use 2 different configs.


    ac_adapter)
        case "$2" in
            AC*|AD*)
                case "$4" in
                    00000000)
                        logger 'AC unplugged'
			sudo -u stino cp /home/stino/.config/hypr/hypridle-battery.conf /home/stino/.config/hypr/hypridle.conf
			sudo -u stino pkill hypridle
			sudo -u stino hypridle
                        ;;
                    00000001)
                        logger 'AC plugged'
			sudo -u stino cp /home/stino/.config/hypr/hypridle-ac.conf /home/stino/.config/hypr/hypridle.conf
			sudo -u stino pkill hypridle
			sudo -u stino hypridle
                        ;;
                esac
                ;;
            *)
                logger "ACPI action undefined: $2"
                ;;
        esac
        ;;

@AmirAref
Copy link
Author

AmirAref commented Jun 8, 2024

@stinobook
it's not necessary to overwrite the main hypridle.conf file, you can easily create two files, one for battery and one for AC,
and when you want to change your profile, just kill the previous hypeidle process and start a new process with the config file that you want using -c flag which mentioned here as configuration file path.
For example, my ~/.config/hypr/ files:

hypridle.conf
hypridle-ac.conf
hypridle-battery.conf

for switching to AC mode:

pkill hypridle
hypridle -c ~/.config/hypr/hypridle-ac.conf

also, this tricky way to start the process in background would be useful (which means you can close your terminal after that):

nohup hypridle -c hypridle-ac.conf &

@bzglve
Copy link

bzglve commented Jun 14, 2024

I'm not sure if this is a good idea, but it would be convenient to have different timings for one or another percentage of the battery

something like

# base listener that works for battery < 100%
listener {
    timeout-battery = 600
    command = systemctl suspend
}

# listener that works for battery < 60%
listener {
    timeout-battery-60 = 300
    command = systemctl suspend
}

# listener that works for battery < 10%
listener {
    timeout-battery-10 = 120
    command = systemctl suspend
}

@yawor
Copy link
Contributor

yawor commented Jun 19, 2024

also, this tricky way to start the process in background would be useful (which means you can close your terminal after that):

nohup hypridle -c hypridle-ac.conf &

If you're using hyprland, it's better to do

hyprctl dispatch exec hypridle -c hypridle-ac.conf

to start new hypridle instance. That way it's started in the same fashion as it's started on login using exec-once.

Also if you'd like to reload some executable on config file change, I recommend using watchexec program. For example, I run waybar from hyprland like this:

exec-once = watchexec --stdin-quit -r -w ~/.config/waybar waybar

The watchexec starts waybar and monitors the waybar config directory. If it detects any changes to the files in that directory, it restarts the waybar process.

The --stdin-quit is important, because without it watchexec won't detect when hyprland exits and it stays running. With that parameter it properly terminates the target process and itself when hyprland exits.

@AmirAref
Copy link
Author

AmirAref commented Jun 20, 2024

The watchexec starts waybar and monitors the waybar config directory. If it detects any changes to the files in that directory, it restarts the waybar process.

@yawor
Oh, thank you. I had to take lots of effort to customize my waybar and reload the new config manually, every time.

Also, i didn't know about the hyprctl dispatch exec command, it's very useful.

@Atemu
Copy link

Atemu commented Aug 9, 2024

There's some further things to consider here. Consider the following config and scenario:

listener {
    timeout-battery = 600
    timeout-ac = 1800
    command = systemctl suspend
}
  1. Laptop is plugged in and left to idle 700s.
  2. Laptop is plugged out.

What should happen?

A "dumb" mode switch to "battery state" would not do anything because the 600s timeout would have already happened. Such behaviour must be avoided IMHO since it represents an illegal state; a state after the event should have fired but didn't actually fire.

I think the least surprising behaviour would be to fire the event immediately after plugging out eventhough it's overdue.

Another interpretation could however be to expect it to wait another 600s after plugging out and basically consider the plugging in/out itself to be an event that should reset the timeout.

Which of these two interpretations should be used should perhaps be user-configurable on a per-listener level with a global default.

@Atemu
Copy link

Atemu commented Aug 9, 2024

Regarding battery levels:

Behaving differently based on battery percentage is also a feature I think hypridle should have. I'd like to propose this option and semantics instead:

listener {
    timeout-battery = 600
    timeout-ac = 1800
    battery-percent = 60
    command = systemctl suspend
}

Everything >60% battery would then be considered the same as AC.

This too would be quite limited in some regards and may not necessarily cover all use-cases.

A better solution would perhaps be to have a generic event listening system where the user can declare their own events to listen/poll for in addition to the absence of user input (which hypridle produces itself).

@yawor
Copy link
Contributor

yawor commented Aug 9, 2024

@Atemu doing dynamic timeouts depending on some external state is not really doable in current approach to timeouts in hypridle. It doesn't create its own timers directly. Instead it registers all configured timeouts in the compositor (using idle notification Wayland API) when it starts and just wait for for callbacks.
The first scenario you've mentioned, where the laptop is unplugged after the timeout has already passed already happens with media playback if you don't inhibit the timeout directly in the compositor. If it's inhibited only in hypridle, then the timeout still happens but it's just ignored by hypridle and won't fire even after the video has finished.
The idle notification Wayland API is not very flexible. I'm don't have much experience with it, but looking at it, it would be hard to register and unregister timeouts dynamically.
I'm wondering if it would be possible to take a different approach. Instead of executing actions on compositor's timeouts, only register on timeout with a very short time (for example 1 second) just to get notifications when the compositor enters or exits idle state, and then handle all timers internally. Creation of timers could then be also controlled by other external sources or states.

@demonspork
Copy link

Maybe just have hypridle re-set itself and re-register with the new set of timers whenever the power status changes?

@Atemu
Copy link

Atemu commented Nov 11, 2024

Oh wow I just thought of a cursed setup where you'd have two hypridle systemd services that point at separate configs where the AC/battery differences are taken care of. Both would Conflicts= each other and un/plugging would start the respective hypridle which would automatically stop the other.

That's so stupid it might actually work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants