An advanced automation daemon for X11 desktops and window managers. Designed to limit FPS/CPU usage and run commands on window focus and unfocus events. Provides gaming-oriented features. Written mostly in Bash and partially in C.
- Known issues
- Screenshot
- Features
- Dependencies
- Building and installation
- Post install
- Uninstallation
- Usage
- Configuration
- Tips and tricks
- Apply changes in config file
- Alternative way to mute process audio on unfocus for Pipewire with Wireplumber
- Increase process priority on window appearance
- Overclock NVIDIA GPU on focus
- Change keyboard layout to English on focus
- Increase digital vibrance on focus
- Preload shader cache on window appearance
- Disable night light on focus
- Possible questions
- Freezing online/multiplayer games by setting
unfocus-cpu-limitto0%causes disconnects.- Use less aggressive CPU limit to allow game to send/receive packets.
- Stuttery audio in unfocused game if CPU limit is pretty aggressive.
- That should be expected, because
cpulimitinterrupts process withSIGSTOPandSIGCONTsignals very frequently to limit CPU usage. Useunfocus-muteconfig key, or in case you use Pipewire with Wireplumber, you may want to usewpctlas described here.
- That should be expected, because
- In some games, with
focus-grab-cursorset totrue, cursor still able to escape, but does not work outside of window.- As example, in "Ori and the Will of the Wisps" game (Unity engine) in windowed mode. Whether do not use
focus-grab-cursorconfig key in such cases or ignore an issue, I can not do anything with this, sorry.
- As example, in "Ori and the Will of the Wisps" game (Unity engine) in windowed mode. Whether do not use
- Daemon says that it waits for cursor ungrab "without any reason".
- That happens in case game grabs cursor manually (e.g. in fullscreen mode, not borderless one). Do not use
focus-grab-cursorconfig key in such cases, as it becomes useless.
- That happens in case game grabs cursor manually (e.g. in fullscreen mode, not borderless one). Do not use
- Daemon mutes multiple processes if there is >=2 processes with the same name.
- Edge case, that happens in case processes do not report their PIDs, so daemon should guess. If you use Pipewire with Wireplumber, you may want to use this method. Keep in mind, this method does not mute processes in sandboxes with PID namespaces, unlike default one.
Daemon running handling already opened windows (-H) in verbose mode (-v) and enabled timestamps (-t).
- Applying CPU or FPS limit to process on unfocus and unlimit on focus. FPS limiting requires game running using MangoHud with already existing config file.
- Reducing process priority on unfocus and restore it on focus.
- Minimizing window on unfocus, useful for borderless windows.
- Expanding window to fullscreen on focus. Useful for games which handle a window mode in a weird way.
- Grabbing cursor and redirect input into focused window to prevent cursor from escaping to second monitor in case with borderless windows.
- Executing commands and scripts on focus, unfocus and window closure events to extend daemon functionality. Daemon provides info about window and process through environment variables.
- Logging support.
- Notifications support.
- Flexible identifiers support to avoid false positives, including regular expressions.
- Working with processes running through sandbox with PID namespaces, e.g. Firejail.
- Handling DE/WM restart or switching it on the fly.
- Support for most of X11 DEs/WMs (EWMH-compatible ones) and does not rely on either GPU or its driver.
- Detection and handling both explicitly and implicitly opened windows.
- Muting processes on unfocus and unmuting on focus with Pulseaudio and Pipewire support, including Pipewire Media Session and Wireplumber.
Required: bash util-linux cpulimit coreutils libxres libx11 libxext xorgproto less
Optional: mangohud lib32-mangohud libnotify libpulse
Build: libxres libx11 libxext xorgproto make gcc
Required: bash cpulimit coreutils libxres1 libx11-6 libxext6 less
Optional: mangohud mangohud:i386 libnotify-bin pulseaudio-utils
Build: libxres-dev libx11-dev libxext-dev x11proto-dev make gcc
Required: bash util-linux cpulimit coreutils libXres libX11 libXext xorgproto less
Optional: MangoHud MangoHud-32bit libnotify pulseaudio-utils
Build: libXres-devel libX11-devel libXext-devel xorgproto make gcc
Required: bash util-linux cpulimit coreutils libXres libX11 libXext less
Optional: mangohud mangohud.i686 libnotify pulseaudio-utils
Build: libXres-devel libX11-devel libXext-devel xorg-x11-proto-devel make gcc
Required: bash util-linux cpulimit coreutils libXRes1 libX11-6 libXext6 less
Optional: mangohud mangohud-32bit libnotify4 pulseaudio-utils
Build: libXres-devel libX11-devel libXext-devel xorgproto-devel make gcc
Make sure you have installed base-devel package before continue.
git clone https://aur.archlinux.org/cpulimit.gitcd cpulimitmakepkg -sriccd ..git clone https://github.com/itz-me-zappex/flux.gitcd flux/packaging/archlinuxmakepkg -sricsudo pacman -Rns $(pacman -Qttdq)git clone https://github.com/itz-me-zappex/flux.gitcd flux/packaging/debianbash build-deb.shWARNING: You need to figure out with file name, it differs depending on version and architecture, e.g.:
sudo dpkg -i flux_1.31.0.1-1_amd64.debsudo apt install -fsudo apt autoremovesudo dnf install rpmdevtoolsgit clone https://github.com/itz-me-zappex/flux.gitrpmdev-setuptreecp flux/packaging/fedora/flux.spec rpmbuild/SPECS/spectool -g rpmbuild/SPECS/flux.spec --sourcedirsudo dnf builddep rpmbuild/SPECS/flux.specrpmbuild -bb rpmbuild/SPECS/flux.specWARNING: You need to figure out with file name, it differs depending on version and architecture, e.g.:
sudo dnf install rpmbuild/RPMS/x86_64/flux-1.31.0.1-1.fc42.x86_64.rpmdnf history listsudo dnf history undo <number>Use this method if you use other distro. Make sure you have installed dependencies as described here before continue.
| Option | Description |
|---|---|
clean |
Remove build/ in repository directory with all files created there after make. |
install |
Install daemon to prefix, can be changed using $PREFIX, defaults to /usr/local. |
uninstall |
Remove bin/flux and lib/flux/ from prefix, can be changed using $PREFIX, defaults to /usr/local. |
| Variable | Description |
|---|---|
PREFIX |
Install daemon to <PREFIX>/bin/ and <PREFIX>/lib/flux/, defaults to /usr/local. |
CC |
C compiler, defaults to gcc. |
CFLAGS |
C compiler options, defaults to -O2 -s. |
wget -qO- 'https://api.github.com/repos/itz-me-zappex/flux/releases/latest' | grep '"tarball_url":' | cut -d '"' -f 4 | xargs wget -O flux.tar.gztar -xvf flux.tar.gz --one-top-level=flux --strip-components=1cd 'flux'makesudo make installNeeded for flux group users to bypass scheduling policy change limitations.
sudo install -Dm644 '10-flux.conf' '/etc/security/limits.d/'PREFIX="~/.local" make installDaemon fully functional without installation, if you installed proper dependencies into system.
./build/flux -hNeeded to bypass scheduling policies change limitations.
sudo groupadd -r fluxNeeded to bypass limitations related to changing scheduling policies.
sudo usermod -aG flux "$USER"sudo pacman -Rns fluxsudo apt autopurge fluxsudo dnf remove fluxwget 'https://github.com/itz-me-zappex/flux/archive/refs/tags/v1.23.4.tar.gz'tar -xvf 'v1.23.4.tar.gz'cd 'flux-1.23.4'sudo make uninstallsudo PREFIX='/usr' make uninstallsudo rm '/etc/security/limits.d/10-flux.conf'Depends on distro and package manager you use, I highly suggest to remove dependencies selectively and check which packages are use them to avoid system breakage.
rm -rf '/tmp/flux'Path to config file depends on your own choice.
rm "$HOME/.config/flux.ini"rm "$XDG_CONFIG_HOME/flux.ini"sudo rm '/etc/flux.ini'sudo groupdel fluxUsage: flux [-C <mode>] [-c <file>] [-g <method>] [-l <file>] [-T <format>] [--pe/--pi/--pv/--pw <text>] [options]
Options and values:
-C, --color <mode> Color mode, either 'always', 'auto' or 'never'
default: auto
-c, --config <file> Change path to config file
default: 1) $XDG_CONFIG_HOME/flux.ini
2) $HOME/.config/flux.ini
3) /etc/flux.ini
-g, --get <method> Display window process info and exit, method either 'focus' or 'pick'
-h, --help Display this help and exit
-H, --hot Apply actions to already unfocused windows before handling events
-l, --log <file> Enable logging and set path to log file
-L, --log-overwrite Recreate log file before start, depends on '--log' option
-n, --notifications Display notifications
-q, --quiet Display errors and warnings only
-T, --timestamp-format <format> Set timestamp format, depends on '--timestamps' option
default: [%Y-%m-%dT%H:%M:%S%z]
-t, --timestamps Include timestamps in messages
-u, --usage Alias for '--help'
-v, --verbose Detailed output
-V, --version Display release information and exit
Prefixes configuration:
--pe, --prefix-error <text> Change prefix for error messages
default: [x]
--pi, --prefix-info <text> Change prefix for info messages
default: [i]
--pv, --prefix-verbose <text> Change prefix for verbose messages
default: [~]
--pw, --prefix-warning <text> Change prefix for warning messages
default: [!]
Examples:
flux -Hvt
flux -HtLl ~/.flux.log -T '[%d.%m.%Y %H:%M:%S]'
flux -ql ~/.flux.log
flux -c ~/.config/flux.ini.bak
flux -tT '(\e[1;4;36m%d.%m.%Y\e[0m \e[1;4;31m%H:%M:%S\e[0m)'
Daemon supports colors in prefixes and timestamps, those are configurable and I did everything to prevent user from shooting into his third "leg". There is a bunch of logic implemented to avoid that:
- Daemon will not interpret anything but ANSI escape sequences (e.g.
\e[31mHello, world!\e[0m), so output breakage because of something like\nor\rsimply impossible, those are just shown as text. - Daemon adds additional
\e[0mto end of prefix/timestamp, that prevents output breakage by isolating formatting inside variables. - Even if timestamp/prefix specified by user contains ANSI escape sequences, daemon still removes those keeping only text if output becomes redirected or if
--colorforced tonone.
To configure colors in custom prefix/timestamp, you need to use ANSI escape sequence inside of prefix/timestamp as specified below:
flux -tT '(\e[1;4;36m%d.%m.%Y\e[0m \e[1;4;31m%H:%M:%S\e[0m)'Now you have timestamp with bold and underlined text with cyan date and red time. Order or count of ANSI escape sequences does not matter, so you can turn timestamps into freaking rainbow without causing explosion of the Sun. Same is applicable to prefixes. If you do not like \e for whatever reason, you can use either \033, \u001b or \x1b instead, those are handled registry independently. More about colors and ANSI escape sequences you can find on https://www.shellhacks.com/bash-colors or on another website.
flux -Hvtflux -HtLl ~/.flux.log & exitRunning daemon as root also possible, but that feature almost useless and UNSAFE.
Just add command to autostart using your DE/WM settings or config file.
An INI-like syntax is used for configuration.
Daemon searches for following configuration files by priority:
$XDG_CONFIG_HOME/flux.ini$HOME/.config/flux.ini/etc/flux.ini
As INI is not standartized, I should mention all supported features here.
Supported:
- Spaces and other symbols in section names.
- Single and double quoted strings.
- Сase insensitivity of key names.
- Comments using
;and/or#symbols. - Insensetivity to spaces before and after
=symbol. - Appending values to config keys using
+=. Works only in scripting config keys. - Regular expressions using
~=. Works only in identifier config keys.
Unsupported:
- Line continuation.
- Inline comments.
- Anything else that unmentioned here.
| Key | Description |
|---|---|
command |
Command which is used to execute process, required if name is not specified. |
name |
Name of process, required if command is not specified. Daemon uses process executable name as process name, because /proc/<PID>/comm is stripped to 15 visible symbols. Side effect of this, is that in case /proc/<PID>/cmdline contains arguments separated with spaces instead of zero bytes, then arguments become a part of process name (noticed that only with Ungoogled Chromium subprocesses daemon can't even see). You can safely use executable name of both native and Wine/Proton applications here. |
owner |
Effective UID of process or username (login), optional. |
| Key | Description |
|---|---|
unfocus-cpu-limit |
CPU limit to set on unfocus event, accepts values between 0% (freeze) and 100% (no limit), % symbol is optional. Defaults to 100%. |
fps-unfocus |
FPS to set on unfocus, required by and requires mangohud-config, cannot be equal to 0 as that means no limit. |
fps-focus |
FPS to set on focus or list of comma-separated integers (e.g. 30,60,120, used in MangoHud as FPS limits you can switch between using built-in keybinding), requires fps-unfocus. Defaults to 0 (i.e. no limit). |
unfocus-sched-idle |
Boolean, set SCHED_IDLE scheduling policy for process on unfocus event to greatly reduce its priority. Daemon should run as @flux to be able restore SCHED_RR/SCHED_FIFO/SCHED_OTHER/SCHED_BATCH scheduling policy and only as root to restore SCHED_DEADLINE scheduling policy. If daemon does not have sufficient rights to restore these scheduling policies, it will print warning and will not change anything. Defaults to false. |
unfocus-mute |
Boolean, daemon mutes process on unfocus and unmutes on focus. Uses pactl tool with a bunch of logic to parse list of sink inputs and find match using process name and PID. Defaults to false. You may want to use an alternative way to mute process in case you use Pipewire with Wireplumber. |
| Key | Description |
|---|---|
unfocus-limits-delay |
Delay in seconds before apply CPU/FPS limit and/or setting SCHED_IDLE. Supports values with floating point. Defaults to 0. |
mangohud-source-config |
Path to MangoHud config file which should be used as a base before apply FPS limit in mangohud-config. If not specified, then target behaves as source. Useful if you are not looking to duplicate MangoHud config for multiple games. |
mangohud-config |
Path to MangoHud config which should be changed (target), required if you want change FPS limits and requires fps-unfocus. Make sure you created specified config file before start game/application with it (at least keep it blank), otherwise MangoHud will not be able to load new config on the fly and daemon will throw warnings related to config absence. Do not use the same config for multiple sections to avoid unexpected issues with limits! |
group |
Specify group from which section supposed to inherit rules. Group declaration should begin with @ symbol in both its section name and in value of group key. |
All commands run via Bash with nohup setsid and will not be killed on daemon exit, output is hidden to avoid mess, so consider to redirect output to expected place if you need output of specific command.
| Key | Description |
|---|---|
exec-oneshot |
Command to execute on window appearance event. |
exec-closure |
Command to execute on window closure event. Defaults to lazy-exec-unfocus value if not specified or declared with += (appending). |
exec-exit |
Command to execute when daemon receives SIGINT or SIGTERM signal. Defaults to lazy-exec-unfocus value if not specified or declared with += (appending). |
exec-exit-focus |
Same as exec-exit, but command appears executed only if matching window appears focused at the moment of daemon termination. |
exec-exit-unfocus |
Same as exec-exit, but command appears executed only if matching window appears unfocused at the moment of daemon termination. |
exec-focus |
Command to execute on focus event. |
exec-unfocus |
Command to execute on unfocus event. |
lazy-exec-focus |
Same as exec-focus, but command will not run when processing opened windows if --hot is specified or in case window appeared implicitly. |
lazy-exec-unfocus |
Same as exec-unfocus, but command will not run when processing opened windows if --hot is specified or in case window appeared implicitly. Used as exec-exit and/or exec-closure automatically if one/two of those is/are not specified. |
| Key | Description |
|---|---|
unfocus-minimize |
Boolean, minimize window to panel on unfocus. Useful for borderless windowed apps/games as those are not minimized automatically on Alt+Tab. Defaults to false. |
focus-fullscreen |
Boolean, sends X event to window manager on focus to expand window to fullscreen. Useful if game handles window mode in a weird way, e.g. Forza Horizon 4. Defaults to false. |
focus-grab-cursor |
Boolean, daemon grabs cursor if possible, binds it to window rectangles and because of X11 nature which prevents input to anything but client which owns cursor (flux-grab-cursor module in background in this case) - redirects all input into focused window. This ugly layer prevents cursor from escaping to second monitor in some games at cost of possible input lag. Cursor is ungrabbed on unfocus event. Defaults to false. |
To avoid repeating yourself, reduce config file size and simplify editing, you may want to create and use groups.
Order of group config key matters a lot, if you want to overwrite value from group, specify key below group = @<group>, otherwise - above. If you want to append value to key from group, then use += after group config key.
Group name does not matter, except section name should begin with @ symbol. That is how daemon defines whether that is just a section or group.
Position of group declaration section in config file does not matter at all.
Using multiple groups in one section at the same time is not possible.
Group should not contain identifiers e.g. name, owner and/or command.
You can use group config key inside groups.
To make things more clear, here is an example of how to create and use groups:
[@games]
unfocus-mute = true
lazy-exec-focus += nvidia-settings -a '[gpu:0]/DigitalVibrance=150'
lazy-exec-unfocus += nvidia-settings -a '[gpu:0]/DigitalVibrance=0'
exec-oneshot += renice -n -4 $FOCUSED_PID
exec-oneshot += find ~/.nv -type f -exec cat {} +
[@games-overclock]
group = @games
lazy-exec-focus += nvidia-settings -c :0 -a '[gpu:0]/GPUGraphicsClockOffset[2]=200'
lazy-exec-focus += nvidia-settings -c :0 -a '[gpu:0]/GPUMemoryTransferRateOffset[2]=2000'
lazy-exec-unfocus += nvidia-settings -c :0 -a '[gpu:0]/GPUGraphicsClockOffset[2]=0'
lazy-exec-unfocus += nvidia-settings -c :0 -a '[gpu:0]/GPUMemoryTransferRateOffset[2]=0'
[Geometry Dash]
name = GeometryDash.exe
unfocus-cpu-limit = 2%
unfocus-sched-idle = true
group = @games-overclock
[Ember Knights]
name = EmberKnights_64.exe
unfocus-cpu-limit = 5%
unfocus-sched-idle = true
unfocus-minimize = true
group = @games
[Alan Wake]
name = AlanWake.exe
unfocus-cpu-limit = 0%
group = @games-overclockTo simplify config file editing and reduce its size, you may want to use regular expressions. As example, to avoid extremely long strings, like in case with Minecraft as its process name is just java and command is extremely long or to make section matchable with multiple process names.
; Section matches both 'vkcube' and 'glxgears' processes
[vkcube and glxgears]
name ~= ^(vkcube|glxgears)$
unfocus-cpu-limit = 0%
; Minecraft has extremely long command and process name is just 'java'
[Minecraft]
name = java
command ~= minecraft
unfocus-cpu-limit = 5%Config keys command and owner are optional in this case, so you can use just name.
; Freeze on unfocus and disable/enable compositor on focus and unfocus respectively
[The Witcher 3: Wild Hunt]
name = witcher3.exe
command = Z:\run\media\zappex\WD-BLUE\Games\Steam\steamapps\common\The Witcher 3\bin\x64\witcher3.exe
owner = zappex
unfocus-cpu-limit = 0%
lazy-exec-focus = killall picom
lazy-exec-unfocus = picom
; Set FPS to 5, minimize, reduce process priority and mute on unfocus
; Set FPS to 60, restore process priority, unmute and expand to fullscreen on focus
[Forza Horizon 4]
name = ForzaHorizon4.exe
command = Z:\run\media\zappex\WD-BLUE\Games\Steam\steamapps\common\ForzaHorizon4\ForzaHorizon4.exe
owner = zappex
mangohud-config = ~/.config/MangoHud/wine-ForzaHorizon4.conf
mangohud-source-config = ~/.config/MangoHud/MangoHud.conf
fps-unfocus = 5
fps-focus = 60
unfocus-mute = true
unfocus-sched-idle = true
unfocus-minimize = true
focus-fullscreen = true
; Reduce CPU usage and reduce priority when unfocused to keep game able download music and assets
[Geometry Dash]
name = GeometryDash.exe
command = Z:\run\media\zappex\WD-BLUE\Games\Steam\steamapps\common\Geometry Dash\GeometryDash.exe
owner = zappex
unfocus-cpu-limit = 2%
unfocus-sched-idle = trueYou can use these variables in your commands and scripts that running from exec-* config keys to avoid obtaining window XID and process info twice.
| Variable | Description |
|---|---|
FOCUSED_WINDOW_XID |
Decimal XID of focused window. |
FOCUSED_PID |
Process PID of focused window. |
FOCUSED_PROCESS_NAME |
Process name of focused window. |
FOCUSED_PROCESS_OWNER |
Effective process UID of focused window. |
FOCUSED_PROCESS_OWNER_USERNAME |
Effective process owner username of focused window. |
FOCUSED_PROCESS_COMMAND |
Command used to run process of focused window. |
UNFOCUSED_WINDOW_XID |
Decimal XID of unfocused window. |
UNFOCUSED_PID |
Process PID of unfocused window. |
UNFOCUSED_PROCESS_NAME |
Process name of unfocused window. |
UNFOCUSED_PROCESS_OWNER |
Effective process UID of unfocused window. |
UNFOCUSED_PROCESS_OWNER_USERNAME |
Effective process owner username of unfocused window. |
UNFOCUSED_PROCESS_COMMAND |
Command used to run process of unfocused window. |
As daemon does not parse config on the fly, you need to restart daemon with --hot option after config file editing to make it handle already opened windows immediately after start.
This way should be faster and simplier, than using pactl tool with a bunch of logic as daemon does in case with unfocus-mute config key.
But, wpctl tool does not mute processes which run in sandbox with PID namespaces (e.g. Firejail), and will not work without Wireplumber, so it is not applicable on Pulseaudio setups too.
Add following lines to section responsible for target:
exec-focus += wpctl set-mute -p $FOCUSED_PID 0
exec-unfocus += wpctl set-mute -p $UNFOCUSED_PID 1Niceness -4 is fine for multimedia tasks, including games.
Add following line to section responsible for target:
exec-oneshot += renice -n -4 $FOCUSED_PIDCommand from lazy-exec-unfocus is also executed on daemon termination if window appears focused at this moment.
Add following lines to section responsible for target (use your own values):
For rootful X session:
lazy-exec-focus += nvidia-settings -c :0 -a '[gpu:0]/GPUGraphicsClockOffset[2]=200'
lazy-exec-focus += nvidia-settings -c :0 -a '[gpu:0]/GPUMemoryTransferRateOffset[2]=2000'
lazy-exec-unfocus += nvidia-settings -c :0 -a '[gpu:0]/GPUGraphicsClockOffset[2]=0'
lazy-exec-unfocus += nvidia-settings -c :0 -a '[gpu:0]/GPUMemoryTransferRateOffset[2]=0'In case with rootful session, that is all, you can stop reading.
For rootless X session (sudo):
lazy-exec-focus += sudo nvidia-settings -a GPUGraphicsClockOffsetAllPerformanceLevels=200
lazy-exec-focus += sudo nvidia-settings -a GPUMemoryTransferRateOffsetAllPerformanceLevels=2000
lazy-exec-unfocus += sudo nvidia-settings -a GPUGraphicsClockOffsetAllPerformanceLevels=0
lazy-exec-unfocus += sudo nvidia-settings -a GPUMemoryTransferRateOffsetAllPerformanceLevels=0For rootless X session (opendoas):
lazy-exec-focus += doas /usr/bin/nvidia-settings -a GPUGraphicsClockOffsetAllPerformanceLevels=200
lazy-exec-focus += doas /usr/bin/nvidia-settings -a GPUMemoryTransferRateOffsetAllPerformanceLevels=2000
lazy-exec-unfocus += doas /usr/bin/nvidia-settings -a GPUGraphicsClockOffsetAllPerformanceLevels=0
lazy-exec-unfocus += doas /usr/bin/nvidia-settings -a GPUMemoryTransferRateOffsetAllPerformanceLevels=0Full path to binary in case with opendoas is needed because it expects 100% command match with rules in doas.conf.
For ability to overclock GPU without password prompt on rootless X session, consider to allow these commands in your favourite privilege elevation tool.
For sudo:
## Allow NVIDIA GPU overclock without password prompt
%wheel ALL=(ALL:ALL) NOPASSWD: /usr/bin/nvidia-settings ^-a GPUGraphicsClockOffsetAllPerformanceLevels=[0-9]+$, /usr/bin/nvidia-settings ^-a GPUMemoryTransferRateOffsetAllPerformanceLevels=[0-9]+$
For opendoas (use your own values):
## Allow NVIDIA GPU overclock without password prompt
permit nopass :wheel as root cmd /usr/bin/nvidia-settings args -a GPUGraphicsClockOffsetAllPerformanceLevels=0
permit nopass :wheel as root cmd /usr/bin/nvidia-settings args -a GPUMemoryTransferRateOffsetAllPerformanceLevels=0
permit nopass :wheel as root cmd /usr/bin/nvidia-settings args -a GPUGraphicsClockOffsetAllPerformanceLevels=200
permit nopass :wheel as root cmd /usr/bin/nvidia-settings args -a GPUMemoryTransferRateOffsetAllPerformanceLevels=2000
Please notice that in case with opendoas you should specify exactly the same frequencies as you did in flux.ini to make things work properly, because there is no support for regexp or wildcards (*).
If you encounter "Authorization required, but no authorization protocol specified" error from nvidia-settings in case with opendoas, then consider to run xhost +SI:localuser:root (this command does not require root) by either adding it to autostart, running it before flux daemon or even by adding it to commands in flux.ini like this (extremely ugly but works):
lazy-exec-focus += "xhost +SI:localuser:root ; doas /usr/bin/nvidia-settings -a GPUGraphicsClockOffsetAllPerformanceLevels=200"
lazy-exec-focus += "xhost +SI:localuser:root ; doas /usr/bin/nvidia-settings -a GPUMemoryTransferRateOffsetAllPerformanceLevels=2000"
lazy-exec-unfocus += "xhost +SI:localuser:root ; doas /usr/bin/nvidia-settings -a GPUGraphicsClockOffsetAllPerformanceLevels=0"
lazy-exec-unfocus += "xhost +SI:localuser:root ; doas /usr/bin/nvidia-settings -a GPUMemoryTransferRateOffsetAllPerformanceLevels=0"P.S.: Do not ask why I suggest to use different commands depending on whether session is rootful or rootless. Commands for rootful session refuse to work on rootless session even if they run as root. Thx to @ewbteewbte from NVIDIA forum for spending the whole night and founding this three eight years old solution.
Useful for some games/apps that do not understand cyrillic letters and rely on layout instead of scancodes.
Add following lines to section responsible for target (use your own values):
lazy-exec-focus += setxkbmap us,ru,ua
lazy-exec-unfocus += setxkbmap ru,ua,usUse vibrant-cli from libvibrant project if you use AMD or Intel GPU.
Add following lines to section responsible for target (use your own values):
lazy-exec-focus += nvidia-settings -a '[gpu:0]/DigitalVibrance=150'
lazy-exec-unfocus += nvidia-settings -a '[gpu:0]/DigitalVibrance=0'lazy-exec-focus += vibrant-cli DisplayPort-0 2.3
lazy-exec-unfocus += vibrant-cli DisplayPort-0 1Very important if you want to improve FPS stability and get rid of stutters in games at cost of higher RAM usage.
First time (e.g. after reboot) preloading may take a lot of time, especially if shader cache folder that big as mine, but next executions will happen immediately.
As you can see, first preload command is very slow, but next one is blazingly fast.
That is how bufferization works, you just need to load file to memory by reading it somehow, and then kernel will not read it from disk again, relying on RAM instead.
P.S.: I have set __GL_SHADER_DISK_CACHE_PATH="$HOME/.nv" to environment variables.
Add following line to section responsible for target (path may vary depending on system configuration):
exec-oneshot += find ~/.cache/nvidia -type f -exec cat {} +exec-oneshot += find ~/.cache/mesa_shader_cache_db -type f -exec cat {} +Add following lines to section responsible for target depending on your desktop environment:
Using dconf:
lazy-exec-focus += dconf write '/org/cinnamon/settings-daemon/plugins/color/night-light-enabled' false
lazy-exec-unfocus += dconf write '/org/cinnamon/settings-daemon/plugins/color/night-light-enabled' trueUsing gsettings:
lazy-exec-focus += gsettings set org.cinnamon.settings-daemon.plugins.color night-light-enabled false
lazy-exec-unfocus += gsettings set org.cinnamon.settings-daemon.plugins.color night-light-enabled trueUsing dconf:
lazy-exec-focus += dconf write '/org/gnome/settings-daemon/plugins/color/night-light-enabled' false
lazy-exec-unfocus += dconf write '/org/gnome/settings-daemon/plugins/color/night-light-enabled' trueUsing gsettings:
lazy-exec-focus += gsettings set org.gnome.settings-daemon.plugins.color night-light-enabled false
lazy-exec-unfocus += gsettings set org.gnome.settings-daemon.plugins.color night-light-enabled trueYeah, two similar commands, those work as toggle.
lazy-exec-focus += qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut "Toggle Night Color"
lazy-exec-unfocus += qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut "Toggle Night Color"- Daemon listens changes in
_NET_ACTIVE_WINDOWand_NET_CLIENT_LIST_STACKINGatoms, obtains window XIDs and using those obtains PIDs by "asking" Xorg server through XRes extension for those, reads info about processes from files in/proc/<PID>to compare it with identifiers in config file, and, if matching section appears, then it does specified in config file actions, otherwise - nothing.
- Daemon uses event-based algorithm to obtain info about windows and processes, when you switching between windows daemon consumes a bit CPU time and just chills out when you doing stuff in single window. Performance loss should not be noticeable even on weak systems.
- Nowadays, anti-cheats are pure garbage, developed by freaks without balls, and you may get banned even for a wrong click or sudden mouse movement, I am not even talking about bans because of broken libs provided with games by developers themselves. But, daemon by its nature should not trigger any anti-cheat
garbagesoftware. Anyway, I am not responsible for your actions, so use daemon carefully in case you worry and do not write me if you got banned somewhere.
- Main task is to reduce CPU/GPU usage of games that have been minimized. Almost every engine fails to recognize that game is unfocused and still consumes a lot of CPU and GPU resources, what can make system slow for other tasks like browsing stuff, chatting, transcoding video etc. or even unresponsive at all. With this daemon now I can simply play a game or tinker with virtual machine and then minimize window if needed without carrying about high CPU/GPU usage and suffering from low multitasking performance. Also, daemon does not care about type of software, so you can use it with everything. Inspiried by feature from NVIDIA driver for Windows where user can set FPS limit for minimized software, this tool is not exactly the same, but better than nothing.
- I try to avoid using external tools in favor of bashisms to reduce CPU usage by daemon and speed up code.
- That is impossible, there is no any unified or even per-compositor way to read window related events and obtain PIDs of windows on Wayland. Even if that become possible, it is still will not be possible to e.g. bind cursor to window rectangles, minimize/fullscreenize windows and so on. Think twice before abandoning X11. Wayland breaks everything!
- This is (scripting) language I know pretty good, despite a fact that Bash as all interpretators works slower than compilable languages, it still fits my needs almost perfectly.

