From 5f99bfd367e4dc4bbf8fd3a4e219978936fedd3a Mon Sep 17 00:00:00 2001 From: Cameron Otsuka Date: Thu, 30 Apr 2026 19:23:43 -0700 Subject: [PATCH] add more configs --- dot_aws/private_config | 3 + dot_config/darkman/config.yaml | 2 + dot_config/easyeffects/fw13-easyeffects.json | 320 ++++++++++ dot_config/easyeffects/microphone.json | 102 ++++ dot_config/fontconfig/fonts.conf | 26 + dot_config/foot/foot.ini | 287 +++++++++ dot_config/mako/config | 12 + dot_config/mpv/mpv.conf | 20 + .../pipewire.conf.d/10-allowed-rates.conf | 3 + dot_config/psd/psd.conf | 70 +++ dot_config/spotify-launcher.conf | 2 + dot_config/sunsetr/sunsetr.toml | 29 + dot_config/swappy/config | 3 + dot_config/swayimg/config | 142 +++++ .../override.conf | 2 + .../override.conf | 8 + .../override.conf | 5 + .../override.conf" | 2 + .../override.conf" | 2 + .../override.conf" | 2 + dot_config/systemd/user/hyprlauncher.service | 13 + .../hyprpolkitagent.service.d/override.conf | 5 + .../user/upower-power-profile-policy.service | 14 + .../override.conf | 4 + dot_config/theme/foot.ini | 65 +++ dot_config/theme/hyprland.conf | 7 + dot_config/theme/hyprlock.conf | 5 + dot_config/theme/mako | 3 + dot_config/theme/vscode.json | 547 ++++++++++++++++++ dot_config/theme/waybar.css | 2 + dot_config/uwsm/env | 3 + dot_config/uwsm/env-hyprland | 2 + dot_config/waybar/config.jsonc | 143 +++++ dot_config/waybar/style.css | 60 ++ dot_config/xdg-desktop-portal/portals.conf | 8 + dot_gitconfig | 5 + dot_zshenv | 14 + .../bin/executable_power-menu.sh | 39 ++ .../executable_upower-power-profile-policy.py | 318 ++++++++++ 39 files changed, 2299 insertions(+) create mode 100644 dot_aws/private_config create mode 100644 dot_config/darkman/config.yaml create mode 100644 dot_config/easyeffects/fw13-easyeffects.json create mode 100644 dot_config/easyeffects/microphone.json create mode 100644 dot_config/fontconfig/fonts.conf create mode 100644 dot_config/foot/foot.ini create mode 100644 dot_config/mako/config create mode 100644 dot_config/mpv/mpv.conf create mode 100644 dot_config/pipewire/pipewire.conf.d/10-allowed-rates.conf create mode 100644 dot_config/psd/psd.conf create mode 100644 dot_config/spotify-launcher.conf create mode 100644 dot_config/sunsetr/sunsetr.toml create mode 100644 dot_config/swappy/config create mode 100644 dot_config/swayimg/config create mode 100644 dot_config/systemd/user/app-blueman@autostart.service.d/override.conf create mode 100644 dot_config/systemd/user/app-com.github.wwmm.easyeffects@autostart.service.d/override.conf create mode 100644 dot_config/systemd/user/app-org.keepassxc.KeePassXC@autostart.service.d/override.conf create mode 100644 "dot_config/systemd/user/app-signal\\x2ddesktop@autostart.service.d/override.conf" create mode 100644 "dot_config/systemd/user/app-spotify\\x2dlauncher@autostart.service.d/override.conf" create mode 100644 "dot_config/systemd/user/app-teams\\x2dfor\\x2dlinux@autostart.service.d/override.conf" create mode 100644 dot_config/systemd/user/hyprlauncher.service create mode 100644 dot_config/systemd/user/hyprpolkitagent.service.d/override.conf create mode 100644 dot_config/systemd/user/upower-power-profile-policy.service create mode 100644 dot_config/systemd/user/xdg-desktop-portal.service.d/override.conf create mode 100644 dot_config/theme/foot.ini create mode 100644 dot_config/theme/hyprland.conf create mode 100644 dot_config/theme/hyprlock.conf create mode 100644 dot_config/theme/mako create mode 100644 dot_config/theme/vscode.json create mode 100644 dot_config/theme/waybar.css create mode 100644 dot_config/uwsm/env create mode 100644 dot_config/uwsm/env-hyprland create mode 100644 dot_config/waybar/config.jsonc create mode 100644 dot_config/waybar/style.css create mode 100644 dot_config/xdg-desktop-portal/portals.conf create mode 100644 dot_gitconfig create mode 100644 dot_zshenv create mode 100644 private_dot_local/bin/executable_power-menu.sh create mode 100644 private_dot_local/bin/executable_upower-power-profile-policy.py diff --git a/dot_aws/private_config b/dot_aws/private_config new file mode 100644 index 0000000..d43f98d --- /dev/null +++ b/dot_aws/private_config @@ -0,0 +1,3 @@ +[default] +region = us-west-2 +output = json \ No newline at end of file diff --git a/dot_config/darkman/config.yaml b/dot_config/darkman/config.yaml new file mode 100644 index 0000000..6fddd24 --- /dev/null +++ b/dot_config/darkman/config.yaml @@ -0,0 +1,2 @@ +lat: 47.61 +lng: -122.65 diff --git a/dot_config/easyeffects/fw13-easyeffects.json b/dot_config/easyeffects/fw13-easyeffects.json new file mode 100644 index 0000000..831829a --- /dev/null +++ b/dot_config/easyeffects/fw13-easyeffects.json @@ -0,0 +1,320 @@ +{ + "output": { + "bass_enhancer#0": { + "amount": 4.0, + "blend": 0.0, + "bypass": true, + "floor": 10.0, + "floor-active": true, + "harmonics": 10.0, + "input-gain": 0.0, + "output-gain": 0.0, + "scope": 200.0 + }, + "blocklist": [], + "convolver#0": { + "autogain": true, + "bypass": false, + "input-gain": 0.0, + "ir-width": 100, + "kernel-name": "IR_22ms_27dB_5t_15s_0c", + "output-gain": 6.0 + }, + "filter#0": { + "balance": 0.0, + "bypass": false, + "equal-mode": "IIR", + "frequency": 60.0, + "gain": 0.0, + "input-gain": 0.0, + "mode": "RLC (BT)", + "output-gain": 0.0, + "quality": 16.0, + "slope": "x16", + "type": "High-pass", + "width": 1.0 + }, + "limiter#0": { + "alr": false, + "alr-attack": 5.0, + "alr-knee": 0.0, + "alr-release": 50.0, + "attack": 2.0, + "bypass": false, + "dithering": "None", + "external-sidechain": false, + "gain-boost": true, + "input-gain": 0.0, + "lookahead": 4.0, + "mode": "Herm Thin", + "output-gain": 0.0, + "oversampling": "Half x4(2L)", + "release": 8.0, + "sidechain-preamp": 0.0, + "stereo-link": 100.0, + "threshold": 0.0 + }, + "multiband_compressor#0": { + "band0": { + "attack-threshold": -16.0, + "attack-time": 150.0, + "boost-amount": 6.0, + "boost-threshold": -72.0, + "compression-mode": "Downward", + "compressor-enable": true, + "external-sidechain": false, + "knee": -12.0, + "makeup": 0.0, + "mute": false, + "ratio": 5.0, + "release-threshold": -100.0, + "release-time": 300.0, + "sidechain-custom-highcut-filter": false, + "sidechain-custom-lowcut-filter": false, + "sidechain-highcut-frequency": 500.0, + "sidechain-lookahead": 0.0, + "sidechain-lowcut-frequency": 10.0, + "sidechain-mode": "RMS", + "sidechain-preamp": 0.0, + "sidechain-reactivity": 10.0, + "sidechain-source": "Middle", + "solo": false, + "stereo-split-source": "Left/Right" + }, + "band1": { + "attack-threshold": -24.0, + "attack-time": 150.0, + "boost-amount": 6.0, + "boost-threshold": -72.0, + "compression-mode": "Downward", + "compressor-enable": true, + "enable-band": true, + "external-sidechain": false, + "knee": -9.0, + "makeup": 5.0, + "mute": false, + "ratio": 3.0, + "release-threshold": -100.0, + "release-time": 200.0, + "sidechain-custom-highcut-filter": false, + "sidechain-custom-lowcut-filter": false, + "sidechain-highcut-frequency": 1000.0, + "sidechain-lookahead": 0.0, + "sidechain-lowcut-frequency": 500.0, + "sidechain-mode": "RMS", + "sidechain-preamp": 0.0, + "sidechain-reactivity": 10.0, + "sidechain-source": "Middle", + "solo": false, + "split-frequency": 250.0, + "stereo-split-source": "Left/Right" + }, + "band2": { + "attack-threshold": -24.0, + "attack-time": 100.0, + "boost-amount": 6.0, + "boost-threshold": -72.0, + "compression-mode": "Downward", + "compressor-enable": true, + "enable-band": true, + "external-sidechain": false, + "knee": -9.0, + "makeup": 5.0, + "mute": false, + "ratio": 3.0, + "release-threshold": -100.0, + "release-time": 150.0, + "sidechain-custom-highcut-filter": false, + "sidechain-custom-lowcut-filter": false, + "sidechain-highcut-frequency": 2000.0, + "sidechain-lookahead": 0.0, + "sidechain-lowcut-frequency": 1000.0, + "sidechain-mode": "RMS", + "sidechain-preamp": 0.0, + "sidechain-reactivity": 10.0, + "sidechain-source": "Middle", + "solo": false, + "split-frequency": 1250.0, + "stereo-split-source": "Left/Right" + }, + "band3": { + "attack-threshold": -24.0, + "attack-time": 80.0, + "boost-amount": 6.0, + "boost-threshold": -72.0, + "compression-mode": "Downward", + "compressor-enable": true, + "enable-band": true, + "external-sidechain": false, + "knee": -9.0, + "makeup": 5.0, + "mute": false, + "ratio": 4.0, + "release-threshold": -100.0, + "release-time": 120.0, + "sidechain-custom-highcut-filter": false, + "sidechain-custom-lowcut-filter": false, + "sidechain-highcut-frequency": 4000.0, + "sidechain-lookahead": 0.0, + "sidechain-lowcut-frequency": 2000.0, + "sidechain-mode": "RMS", + "sidechain-preamp": 0.0, + "sidechain-reactivity": 10.0, + "sidechain-source": "Middle", + "solo": false, + "split-frequency": 5000.0, + "stereo-split-source": "Left/Right" + }, + "band4": { + "attack-threshold": -12.0, + "attack-time": 20.0, + "boost-amount": 6.0, + "boost-threshold": -72.0, + "compression-mode": "Downward", + "compressor-enable": true, + "enable-band": false, + "external-sidechain": false, + "knee": -6.0, + "makeup": 0.0, + "mute": false, + "ratio": 1.0, + "release-threshold": -100.0, + "release-time": 100.0, + "sidechain-custom-highcut-filter": false, + "sidechain-custom-lowcut-filter": false, + "sidechain-highcut-frequency": 8000.0, + "sidechain-lookahead": 0.0, + "sidechain-lowcut-frequency": 4000.0, + "sidechain-mode": "RMS", + "sidechain-preamp": 0.0, + "sidechain-reactivity": 10.0, + "sidechain-source": "Middle", + "solo": false, + "split-frequency": 4000.0, + "stereo-split-source": "Left/Right" + }, + "band5": { + "attack-threshold": -12.0, + "attack-time": 20.0, + "boost-amount": 6.0, + "boost-threshold": -72.0, + "compression-mode": "Downward", + "compressor-enable": true, + "enable-band": false, + "external-sidechain": false, + "knee": -6.0, + "makeup": 0.0, + "mute": false, + "ratio": 1.0, + "release-threshold": -100.0, + "release-time": 100.0, + "sidechain-custom-highcut-filter": false, + "sidechain-custom-lowcut-filter": false, + "sidechain-highcut-frequency": 12000.0, + "sidechain-lookahead": 0.0, + "sidechain-lowcut-frequency": 8000.0, + "sidechain-mode": "RMS", + "sidechain-preamp": 0.0, + "sidechain-reactivity": 10.0, + "sidechain-source": "Middle", + "solo": false, + "split-frequency": 8000.0, + "stereo-split-source": "Left/Right" + }, + "band6": { + "attack-threshold": -12.0, + "attack-time": 20.0, + "boost-amount": 6.0, + "boost-threshold": -72.0, + "compression-mode": "Downward", + "compressor-enable": true, + "enable-band": false, + "external-sidechain": false, + "knee": -6.0, + "makeup": 0.0, + "mute": false, + "ratio": 1.0, + "release-threshold": -100.0, + "release-time": 100.0, + "sidechain-custom-highcut-filter": false, + "sidechain-custom-lowcut-filter": false, + "sidechain-highcut-frequency": 16000.0, + "sidechain-lookahead": 0.0, + "sidechain-lowcut-frequency": 12000.0, + "sidechain-mode": "RMS", + "sidechain-preamp": 0.0, + "sidechain-reactivity": 10.0, + "sidechain-source": "Middle", + "solo": false, + "split-frequency": 12000.0, + "stereo-split-source": "Left/Right" + }, + "band7": { + "attack-threshold": -12.0, + "attack-time": 20.0, + "boost-amount": 6.0, + "boost-threshold": -72.0, + "compression-mode": "Downward", + "compressor-enable": true, + "enable-band": false, + "external-sidechain": false, + "knee": -6.0, + "makeup": 0.0, + "mute": false, + "ratio": 1.0, + "release-threshold": -100.0, + "release-time": 100.0, + "sidechain-custom-highcut-filter": false, + "sidechain-custom-lowcut-filter": false, + "sidechain-highcut-frequency": 20000.0, + "sidechain-lookahead": 0.0, + "sidechain-lowcut-frequency": 16000.0, + "sidechain-mode": "RMS", + "sidechain-preamp": 0.0, + "sidechain-reactivity": 10.0, + "sidechain-source": "Middle", + "solo": false, + "split-frequency": 16000.0, + "stereo-split-source": "Left/Right" + }, + "bypass": false, + "compressor-mode": "Modern", + "dry": -100.0, + "envelope-boost": "None", + "input-gain": 0.0, + "output-gain": 0.0, + "stereo-split": false, + "wet": 0.0 + }, + "plugins_order": [ + "filter#0", + "bass_enhancer#0", + "convolver#0", + "multiband_compressor#0", + "stereo_tools#0", + "limiter#0" + ], + "stereo_tools#0": { + "balance-in": 0.0, + "balance-out": 0.0, + "bypass": false, + "delay": 0.0, + "input-gain": 0.0, + "middle-level": 0.0, + "middle-panorama": 0.0, + "mode": "LR > LR (Stereo Default)", + "mutel": false, + "muter": false, + "output-gain": 0.0, + "phasel": false, + "phaser": false, + "sc-level": 1.0, + "side-balance": 0.0, + "side-level": 0.0, + "softclip": false, + "stereo-base": 0.30000000000000004, + "stereo-phase": 0.0 + } + } +} + diff --git a/dot_config/easyeffects/microphone.json b/dot_config/easyeffects/microphone.json new file mode 100644 index 0000000..2a7dbde --- /dev/null +++ b/dot_config/easyeffects/microphone.json @@ -0,0 +1,102 @@ +{ + "input": { + "autogain#0": { + "bypass": false, + "input-gain": 0.0, + "maximum-history": 15, + "output-gain": 0.0, + "reference": "Geometric Mean (MSI)", + "silence-threshold": -70.0, + "target": -23.0 + }, + "blocklist": [], + "gate#0": { + "attack": 40.0, + "bypass": false, + "curve-threshold": -57.0, + "curve-zone": -6.0, + "dry": -14.0, + "hpf-frequency": 100.0, + "hpf-mode": "24 dB/oct", + "hysteresis": false, + "hysteresis-threshold": -12.0, + "hysteresis-zone": -6.0, + "input-gain": 0.0, + "lpf-frequency": 1000.0, + "lpf-mode": "24 dB/oct", + "makeup": 0.0, + "output-gain": 0.0, + "reduction": -72.0, + "release": 800.0, + "sidechain": { + "input": "Internal", + "lookahead": 8.0, + "mode": "RMS", + "preamp": 0.0, + "reactivity": 10.0, + "source": "Middle", + "stereo-split-source": "Left/Right" + }, + "stereo-split": false, + "wet": -16.0 + }, + "limiter#0": { + "alr": true, + "alr-attack": 5.0, + "alr-knee": 0.0, + "alr-release": 50.0, + "attack": 5.0, + "bypass": false, + "dithering": "24bit", + "external-sidechain": false, + "gain-boost": false, + "input-gain": 0.0, + "lookahead": 5.0, + "mode": "Exp Tail", + "output-gain": 0.0, + "oversampling": "Full x2(2L)", + "release": 5.0, + "sidechain-preamp": 0.0, + "stereo-link": 100.0, + "threshold": 0.0 + }, + "plugins_order": [ + "rnnoise#0", + "gate#0", + "autogain#0", + "limiter#0", + "stereo_tools#0" + ], + "rnnoise#0": { + "bypass": false, + "enable-vad": true, + "input-gain": 0.0, + "model-path": "", + "output-gain": 0.0, + "release": 20.0, + "vad-thres": 50.0, + "wet": 0.0 + }, + "stereo_tools#0": { + "balance-in": 0.0, + "balance-out": 0.0, + "bypass": false, + "delay": -3.469446951953614e-18, + "input-gain": 0.0, + "middle-level": 0.0, + "middle-panorama": 0.0, + "mode": "LR > LL (Mono Left Channel)", + "mutel": false, + "muter": false, + "output-gain": 0.0, + "phasel": false, + "phaser": false, + "sc-level": 1.0, + "side-balance": 0.0, + "side-level": 0.0, + "softclip": false, + "stereo-base": 0.0, + "stereo-phase": 0.0 + } + } +} diff --git a/dot_config/fontconfig/fonts.conf b/dot_config/fontconfig/fonts.conf new file mode 100644 index 0000000..0a1f5f3 --- /dev/null +++ b/dot_config/fontconfig/fonts.conf @@ -0,0 +1,26 @@ + + + + + serif + + FreeSerif + Noto Serif + + + + sans-serif + + FreeSans + Noto Sans + + + + monospace + + CaskaydiaMono Nerd Font + FreeMono + Noto Sans Mono + + + diff --git a/dot_config/foot/foot.ini b/dot_config/foot/foot.ini new file mode 100644 index 0000000..2af2677 --- /dev/null +++ b/dot_config/foot/foot.ini @@ -0,0 +1,287 @@ +# -*- conf -*- + +include=~/.config/theme/foot.ini +# shell=$SHELL (if set, otherwise user's default shell from /etc/passwd) +# term=foot (or xterm-256color if built with -Dterminfo=disabled) +# term=xterm-256color +# login-shell=no + +# app-id=foot # globally set wayland app-id. Default values are "foot" and "footclient" for desktop and server mode +# title=foot +# locked-title=no + +font=monospace:size=10 +# font-bold= +# font-italic= +# font-bold-italic= +# font-size-adjustment=0.5 +# line-height= +# letter-spacing=0 +# horizontal-letter-offset=0 +# vertical-letter-offset=0 +# underline-offset= +# underline-thickness= +# strikeout-thickness= +# box-drawings-uses-font-glyphs=no +# dpi-aware=no +# gamma-correct-blending=no + +# initial-color-theme=1 +# initial-window-size-pixels=700x500 # Or, +# initial-window-size-chars= +# initial-window-mode=windowed +# pad=0x0 center-when-maximized-and-fullscreen +# resize-by-cells=yes +# resize-keep-grid=yes +# resize-delay-ms=100 + +# bold-text-in-bright=no +# word-delimiters=,│`|:"'()[]{}<> +# selection-target=primary +# workers= +# utmp-helper=/usr/lib/utempter/utempter # When utmp backend is ‘libutempter’ (Linux) +# utmp-helper=/usr/libexec/ulog-helper # When utmp backend is ‘ulog’ (FreeBSD) + +# uppercase-regex-insert=yes + +[environment] +# name=value + +[security] +# osc52=enabled # disabled|copy-enabled|paste-enabled|enabled + +[bell] +# system=yes +# urgent=no +# notify=no +# visual=no +# command= +# command-focused=no + +[desktop-notifications] +# command=notify-send --wait --app-name ${app-id} --icon ${app-id} --category ${category} --urgency ${urgency} --expire-time ${expire-time} --hint STRING:image-path:${icon} --hint BOOLEAN:suppress-sound:${muted} --hint STRING:sound-name:${sound-name} --replace-id ${replace-id} ${action-argument} --print-id -- ${title} ${body} +# command-action-argument=--action ${action-name}=${action-label} +# close="" +# inhibit-when-focused=yes + + +[scrollback] +# lines=1000 +# multiplier=3.0 +# indicator-position=relative +# indicator-format="" + +[url] +# launch=xdg-open ${url} +# label-letters=sadfjklewcmpgh +# osc8-underline=url-mode +# regex=(((https?://|mailto:|ftp://|file:|ssh:|ssh://|git://|tel:|magnet:|ipfs://|ipns://|gemini://|gopher://|news:)|www\.)([0-9a-zA-Z:/?#@!$&*+,;=.~_%^\-]+|\([]\["0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*\)|\[[\(\)"0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*\]|"[]\[\(\)0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*"|'[]\[\(\)0-9a-zA-Z:/?#@!$&*+,;=.~_%^\-]*')+([0-9a-zA-Z/#@$&*+=~_%^\-]|\([]\["0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*\)|\[[\(\)"0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*\]|"[]\[\(\)0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*"|'[]\[\(\)0-9a-zA-Z:/?#@!$&*+,;=.~_%^\-]*')) + +# You can define your own regex's, by adding a section called +# 'regex:' with a 'regex' and 'launch' key. These can then be tied +# to a key-binding. See foot.ini(5) for details + +# [regex:your-fancy-name] +# regex= +# launch= ${match} +# +# [key-bindings] +# regex-launch=[your-fancy-name] Control+Shift+q +# regex-copy=[your-fancy-name] Control+Alt+Shift+q + +[cursor] +# style=block +# blink=no +# blink-rate=500 +# beam-thickness=1.5 +# underline-thickness= + +[mouse] +# hide-when-typing=no +# alternate-scroll-mode=yes + +[touch] +# long-press-delay=400 + +[colors] +# alpha=1.0 +# alpha-mode=default # Can be `default`, `matching` or `all` +# background=242424 +# foreground=ffffff +# flash=7f7f00 +# flash-alpha=0.5 + +# cursor= + +## Normal/regular colors (color palette 0-7) +# regular0=242424 # black +# regular1=f62b5a # red +# regular2=47b413 # green +# regular3=e3c401 # yellow +# regular4=24acd4 # blue +# regular5=f2affd # magenta +# regular6=13c299 # cyan +# regular7=e6e6e6 # white + +## Bright colors (color palette 8-15) +# bright0=616161 # bright black +# bright1=ff4d51 # bright red +# bright2=35d450 # bright green +# bright3=e9e836 # bright yellow +# bright4=5dc5f8 # bright blue +# bright5=feabf2 # bright magenta +# bright6=24dfc4 # bright cyan +# bright7=ffffff # bright white + +## dimmed colors (see foot.ini(5) man page) +# dim0= +# ... +# dim7= + +## The remaining 256-color palette +# 16 = <256-color palette #16> +# ... +# 255 = <256-color palette #255> + +## Sixel colors +# sixel0 = 000000 +# sixel1 = 3333cc +# sixel2 = cc2121 +# sixel3 = 33cc33 +# sixel4 = cc33cc +# sixel5 = 33cccc +# sixel6 = cccc33 +# sixel7 = 878787 +# sixel8 = 424242 +# sixel9 = 545499 +# sixel10 = 994242 +# sixel11 = 549954 +# sixel12 = 995499 +# sixel13 = 549999 +# sixel14 = 999954 +# sixel15 = cccccc + +## Misc colors +# selection-foreground= +# selection-background= +# jump-labels= # black-on-yellow +# scrollback-indicator= # black-on-bright-blue +# search-box-no-match= # black-on-red +# search-box-match= # black-on-yellow +# urls= + +[colors2] +# Alternative color theme, see man page foot.ini(5) + +[csd] +# preferred=server +# size=26 +# font= +# color= +# hide-when-maximized=no +# double-click-to-maximize=yes +# border-width=0 +# border-color= +# button-width=26 +# button-color= +# button-minimize-color= +# button-maximize-color= +# button-close-color= + +[key-bindings] +# scrollback-up-page=Shift+Page_Up Shift+KP_Page_Up +# scrollback-up-half-page=none +# scrollback-up-line=none +# scrollback-down-page=Shift+Page_Down Shift+KP_Page_Down +# scrollback-down-half-page=none +# scrollback-down-line=none +# scrollback-home=none +# scrollback-end=none +# clipboard-copy=Control+Shift+c XF86Copy +# clipboard-paste=Control+Shift+v XF86Paste +# primary-paste=Shift+Insert +# search-start=Control+Shift+r +# font-increase=Control+plus Control+equal Control+KP_Add +# font-decrease=Control+minus Control+KP_Subtract +# font-reset=Control+0 Control+KP_0 +# spawn-terminal=Control+Shift+n +# minimize=none +# maximize=none +# fullscreen=none +# pipe-visible=[sh -c "xurls | fuzzel | xargs -r firefox"] none +# pipe-scrollback=[sh -c "xurls | fuzzel | xargs -r firefox"] none +# pipe-selected=[xargs -r firefox] none +# pipe-command-output=[wl-copy] none # Copy last command's output to the clipboard +# show-urls-launch=Control+Shift+o +# show-urls-copy=none +# show-urls-persistent=none +# prompt-prev=Control+Shift+z +# prompt-next=Control+Shift+x +# unicode-input=Control+Shift+u +# color-theme-switch-1=none +# color-theme-switch-2=none +# color-theme-toggle=none +# noop=none +# quit=none + +[search-bindings] +# cancel=Control+g Control+c Escape +# commit=Return KP_Enter +# find-prev=Control+r +# find-next=Control+s +# cursor-left=Left Control+b +# cursor-left-word=Control+Left Mod1+b +# cursor-right=Right Control+f +# cursor-right-word=Control+Right Mod1+f +# cursor-home=Home Control+a +# cursor-end=End Control+e +# delete-prev=BackSpace +# delete-prev-word=Mod1+BackSpace Control+BackSpace +# delete-next=Delete +# delete-next-word=Mod1+d Control+Delete +# delete-to-start=Control+u +# delete-to-end=Control+k +# extend-char=Shift+Right +# extend-to-word-boundary=Control+w Control+Shift+Right +# extend-to-next-whitespace=Control+Shift+w +# extend-line-down=Shift+Down +# extend-backward-char=Shift+Left +# extend-backward-to-word-boundary=Control+Shift+Left +# extend-backward-to-next-whitespace=none +# extend-line-up=Shift+Up +# clipboard-paste=Control+v Control+Shift+v Control+y XF86Paste +# primary-paste=Shift+Insert +# unicode-input=none +# scrollback-up-page=Shift+Page_Up Shift+KP_Page_Up +# scrollback-up-half-page=none +# scrollback-up-line=none +# scrollback-down-page=Shift+Page_Down Shift+KP_Page_Down +# scrollback-down-half-page=none +# scrollback-down-line=none +# scrollback-home=none +# scrollback-end=none + +[url-bindings] +# cancel=Control+g Control+c Control+d Escape +# toggle-url-visible=t + +[text-bindings] +# \x03=Mod4+c # Map Super+c -> Ctrl+c + +[mouse-bindings] +# scrollback-up-mouse=BTN_WHEEL_BACK +# scrollback-down-mouse=BTN_WHEEL_FORWARD +# font-increase=Control+BTN_WHEEL_BACK +# font-decrease=Control+BTN_WHEEL_FORWARD +# selection-override-modifiers=Shift +# primary-paste=BTN_MIDDLE +# select-begin=BTN_LEFT +# select-begin-block=Control+BTN_LEFT +# select-extend=BTN_RIGHT +# select-extend-character-wise=Control+BTN_RIGHT +# select-word=BTN_LEFT-2 +# select-word-whitespace=Control+BTN_LEFT-2 +# select-quote = BTN_LEFT-3 +# select-row=BTN_LEFT-4 + +# vim: ft=dosini diff --git a/dot_config/mako/config b/dot_config/mako/config new file mode 100644 index 0000000..b3f4390 --- /dev/null +++ b/dot_config/mako/config @@ -0,0 +1,12 @@ +include=~/.config/theme/mako + +default-timeout=5000 +width=420 +outer-margin=20 +padding=10,15 +border-size=2 +max-icon-size=32 +font=monospace 10 + +[urgency=critical] +default-timeout=0 diff --git a/dot_config/mpv/mpv.conf b/dot_config/mpv/mpv.conf new file mode 100644 index 0000000..b843192 --- /dev/null +++ b/dot_config/mpv/mpv.conf @@ -0,0 +1,20 @@ +hwdec=auto +vo=gpu-next +gpu-api=vulkan +ao=pipewire +profile=high-quality +video-sync=display-resample +interpolation +deinterlace=auto +scale=ewa_lanczos4sharpest +dscale=catmull_rom +dscale-antiring=0.7 +tscale=oversample +dither=error-diffusion +temporal-dither +error-diffusion=floyd-steinberg +deband +target-colorspace-hint=auto +target-colorspace-hint-mode=source +icc-profile-auto +icc-use-luma diff --git a/dot_config/pipewire/pipewire.conf.d/10-allowed-rates.conf b/dot_config/pipewire/pipewire.conf.d/10-allowed-rates.conf new file mode 100644 index 0000000..6f5b67e --- /dev/null +++ b/dot_config/pipewire/pipewire.conf.d/10-allowed-rates.conf @@ -0,0 +1,3 @@ +context.properties = { + default.clock.allowed-rates = [ 44100 48000 96000 192000 ] +} diff --git a/dot_config/psd/psd.conf b/dot_config/psd/psd.conf new file mode 100644 index 0000000..26ed36d --- /dev/null +++ b/dot_config/psd/psd.conf @@ -0,0 +1,70 @@ +# +# $XDG_CONFIG_HOME/psd/psd.conf +# +# For documentation, refer man 1 psd or to the wiki page +# https://wiki.archlinux.org/index.php/Profile-sync-daemon + +## NOTE the following: +## To protect data from corruption, in the event that you do make an edit while +## psd is active, any changes made will be applied the next time you start psd. + +# Uncomment and set to "yes" to use overlayfs instead of a full copy to reduce +# the memory costs and to improve sync/unsync operations. Note that your kernel +# MUST have this module available in order to use this mode. +# +USE_OVERLAYFS="yes" + +# Uncomment and set to "yes" to resync on suspend to reduce potential data loss. +# Note that your system MUST have gdbus from glib2 installed to use this mode. +# +#USE_SUSPSYNC="no" + +# List any browsers in the array below to have managed by psd. Useful if you do +# not wish to have all possible browser profiles managed which is the default if +# this array is left commented. +# +# Possible values: +# chromium +# chromium-dev +# conkeror.mozdev.org +# epiphany +# falkon +# firefox +# firefox-trunk +# google-chrome +# google-chrome-beta +# google-chrome-unstable +# heftig-aurora +# icecat +# inox +# luakit +# midori +# opera +# opera-beta +# opera-developer +# opera-legacy +# otter-browser +# qupzilla +# qutebrowser +# palemoon +# rekonq +# seamonkey +# surf +# vivaldi +# vivaldi-snapshot +# +BROWSERS=(chromium firefox) + +# Uncomment and set to "no" to completely disable the crash recovery feature. +# +# The default is to create crash recovery backups if the system is ungracefully +# powered-down due to a kernel panic, hitting the reset switch, battery going +# dead, etc. Some users keep very diligent backups and don't care to have this +# feature enabled. +#USE_BACKUPS="yes" + +# Uncomment and set to an integer that is the maximum number of crash recovery +# snapshots to keep (the oldest ones are deleted first). +# +# The default is to save the most recent 5 crash recovery snapshots. +#BACKUP_LIMIT=5 diff --git a/dot_config/spotify-launcher.conf b/dot_config/spotify-launcher.conf new file mode 100644 index 0000000..ec4c272 --- /dev/null +++ b/dot_config/spotify-launcher.conf @@ -0,0 +1,2 @@ +[spotify] +extra_arguments = ["--enable-features=UseOzonePlatform", "--ozone-platform=wayland"] diff --git a/dot_config/sunsetr/sunsetr.toml b/dot_config/sunsetr/sunsetr.toml new file mode 100644 index 0000000..9f95942 --- /dev/null +++ b/dot_config/sunsetr/sunsetr.toml @@ -0,0 +1,29 @@ +#[Backend] +backend = "auto" # Backend to use: "auto", "hyprland" or "wayland" +transition_mode = "geo" # Select: "geo", "finish_by", "start_at", "center", "static" + +#[Smoothing] +smoothing = true # Enable smooth transitions during startup and exit +startup_duration = 0.5 # Duration of smooth startup in seconds (0.1-60 | 0 = instant) +shutdown_duration = 0.5 # Duration of smooth shutdown in seconds (0.1-60 | 0 = instant) +adaptive_interval = 1 # Adaptive interval base for smooth transitions (1-1000)ms + +#[Time-based config] +night_temp = 3300 # Color temperature during night (1000-20000) Kelvin +day_temp = 6500 # Color temperature during day (1000-20000) Kelvin +night_gamma = 90 # Gamma percentage for night (10-100%) +day_gamma = 100 # Gamma percentage for day (10-100%) +update_interval = 60 # Update frequency during transitions in seconds (10-300) + +#[Static config] +static_temp = 6500 # Color temperature for static mode (1000-20000) Kelvin +static_gamma = 100 # Gamma percentage for static mode (10-100%) + +#[Manual transitions] +sunset = "19:00:00" # Time for manual sunset calculations (HH:MM:SS) +sunrise = "06:00:00" # Time for manual sunrise calculations (HH:MM:SS) +transition_duration = 45 # Transition duration in minutes (5-120) + +#[Geolocation] +latitude = 47.61 # Geographic latitude (auto-detected on first run) +longitude = -122.65 # Geographic longitude (use 'sunsetr geo' to change) diff --git a/dot_config/swappy/config b/dot_config/swappy/config new file mode 100644 index 0000000..d8570c9 --- /dev/null +++ b/dot_config/swappy/config @@ -0,0 +1,3 @@ +[Default] +save_dir=$HOME/Downloads +save_filename_format=screenshot-%Y%m%d-%H%M%S.png diff --git a/dot_config/swayimg/config b/dot_config/swayimg/config new file mode 100644 index 0000000..dbca4d3 --- /dev/null +++ b/dot_config/swayimg/config @@ -0,0 +1,142 @@ +# vim: filetype=dosini + +[general] +size = image + +[slideshow] +time = 3 + +[gallery] +size = 400 +preload = yes + +[list] +recursive = yes + +[info] +show = no + +[info.viewer] +top_left = +name,+format,+filesize,+imagesize,+exif +top_right = index +bottom_left = scale,frame +bottom_right = status + +[info.slideshow] +top_left = none +top_right = none +bottom_left = none +bottom_right = dir,status + +[info.gallery] +top_left = none +top_right = index +bottom_left = none +bottom_right = name,status + +[keys.viewer] +F1 = help +Home = first_file +End = last_file +Left = prev_file +Right = next_file +Space = next_file +Shift+r = rand_file +Shift+d = prev_dir +d = next_dir +Shift+o = prev_frame +o = next_frame +c = skip_file +s = mode slideshow +n = animation +f = fullscreen +Return = mode gallery +Prior = step_left 10 +Next = step_right 10 +Up = step_up 10 +Down = step_down 10 +Equal = zoom +10 +Plus = zoom +10 +Minus = zoom -10 +w = zoom width +Shift+w = zoom height +z = zoom fit +Shift+z = zoom fill +0 = zoom real +BackSpace = zoom optimal +k = zoom keep +Alt+s = zoom +Alt+p = position +bracketleft = rotate_left +bracketright = rotate_right +m = flip_vertical +Shift+m = flip_horizontal +a = antialiasing +r = reload +i = info +Shift+Delete = exec rm -f '%' && echo "File removed: %"; skip_file +Escape = exit +q = exit +# Mouse related +ScrollLeft = step_right 5 +ScrollRight = step_left 5 +ScrollUp = step_up 5 +ScrollDown = step_down 5 +Ctrl+ScrollUp = zoom +10 mouse +Ctrl+ScrollDown = zoom -10 mouse +Shift+ScrollUp = prev_file +Shift+ScrollDown = next_file +Alt+ScrollUp = prev_frame +Alt+ScrollDown = next_frame +MouseLeft = drag +MouseSide = prev_file +MouseExtra = next_file + +[keys.slideshow] +F1 = help +Home = first_file +End = last_file +Left = prev_file +Right = next_file +Shift+r = rand_file +Shift+d = prev_dir +d = next_dir +Space = pause +i = info +f = fullscreen +Return = mode +Escape = exit +q = exit + +[keys.gallery] +F1 = help +Home = first_file +End = last_file +Left = step_left +Right = step_right +Up = step_up +Down = step_down +Prior = page_up +Next = page_down +c = skip_file +s = mode slideshow +f = fullscreen +Return = mode viewer +a = antialiasing +r = reload +i = info +Equal = thumb +20 +Plus = thumb +20 +Minus = thumb -20 +Shift+Delete = exec rm -f '%' && echo "File removed: %"; skip_file +Escape = exit +q = exit +# Mouse related +ScrollLeft = step_right +ScrollRight = step_left +ScrollUp = step_up +ScrollDown = step_down +Ctrl+ScrollUp = thumb +20 +Ctrl+ScrollDown = thumb -20 +MouseLeft = mode viewer + diff --git a/dot_config/systemd/user/app-blueman@autostart.service.d/override.conf b/dot_config/systemd/user/app-blueman@autostart.service.d/override.conf new file mode 100644 index 0000000..28c4525 --- /dev/null +++ b/dot_config/systemd/user/app-blueman@autostart.service.d/override.conf @@ -0,0 +1,2 @@ +[Unit] +After=waybar.service diff --git a/dot_config/systemd/user/app-com.github.wwmm.easyeffects@autostart.service.d/override.conf b/dot_config/systemd/user/app-com.github.wwmm.easyeffects@autostart.service.d/override.conf new file mode 100644 index 0000000..6f51c42 --- /dev/null +++ b/dot_config/systemd/user/app-com.github.wwmm.easyeffects@autostart.service.d/override.conf @@ -0,0 +1,8 @@ +[Unit] +After=waybar.service xdg-desktop-portal.service +Wants=xdg-desktop-portal.service + +[Service] +Environment=QT_NO_XDG_DESKTOP_PORTAL=1 +ExecStart= +ExecStart=/usr/bin/easyeffects --service-mode --hide-window diff --git a/dot_config/systemd/user/app-org.keepassxc.KeePassXC@autostart.service.d/override.conf b/dot_config/systemd/user/app-org.keepassxc.KeePassXC@autostart.service.d/override.conf new file mode 100644 index 0000000..846b82b --- /dev/null +++ b/dot_config/systemd/user/app-org.keepassxc.KeePassXC@autostart.service.d/override.conf @@ -0,0 +1,5 @@ +[Unit] +After=waybar.service + +[Service] +ExecStartPre=/usr/bin/sleep 5 diff --git "a/dot_config/systemd/user/app-signal\\x2ddesktop@autostart.service.d/override.conf" "b/dot_config/systemd/user/app-signal\\x2ddesktop@autostart.service.d/override.conf" new file mode 100644 index 0000000..28c4525 --- /dev/null +++ "b/dot_config/systemd/user/app-signal\\x2ddesktop@autostart.service.d/override.conf" @@ -0,0 +1,2 @@ +[Unit] +After=waybar.service diff --git "a/dot_config/systemd/user/app-spotify\\x2dlauncher@autostart.service.d/override.conf" "b/dot_config/systemd/user/app-spotify\\x2dlauncher@autostart.service.d/override.conf" new file mode 100644 index 0000000..28c4525 --- /dev/null +++ "b/dot_config/systemd/user/app-spotify\\x2dlauncher@autostart.service.d/override.conf" @@ -0,0 +1,2 @@ +[Unit] +After=waybar.service diff --git "a/dot_config/systemd/user/app-teams\\x2dfor\\x2dlinux@autostart.service.d/override.conf" "b/dot_config/systemd/user/app-teams\\x2dfor\\x2dlinux@autostart.service.d/override.conf" new file mode 100644 index 0000000..28c4525 --- /dev/null +++ "b/dot_config/systemd/user/app-teams\\x2dfor\\x2dlinux@autostart.service.d/override.conf" @@ -0,0 +1,2 @@ +[Unit] +After=waybar.service diff --git a/dot_config/systemd/user/hyprlauncher.service b/dot_config/systemd/user/hyprlauncher.service new file mode 100644 index 0000000..83ee08a --- /dev/null +++ b/dot_config/systemd/user/hyprlauncher.service @@ -0,0 +1,13 @@ +[Unit] +Description=A multipurpose and versatile launcher / picker for Hyprland +Documentation=https://github.com/hyprwm/hyprlauncher +PartOf=graphical-session.target +After=graphical-session.target + +[Service] +Type=simple +ExecStart=/usr/bin/hyprlauncher -d +Restart=on-failure + +[Install] +WantedBy=graphical-session.target diff --git a/dot_config/systemd/user/hyprpolkitagent.service.d/override.conf b/dot_config/systemd/user/hyprpolkitagent.service.d/override.conf new file mode 100644 index 0000000..3f73402 --- /dev/null +++ b/dot_config/systemd/user/hyprpolkitagent.service.d/override.conf @@ -0,0 +1,5 @@ +[Unit] +After=xdg-desktop-portal.service + +[Service] +Environment=QT_NO_XDG_DESKTOP_PORTAL=1 diff --git a/dot_config/systemd/user/upower-power-profile-policy.service b/dot_config/systemd/user/upower-power-profile-policy.service new file mode 100644 index 0000000..ffa58b4 --- /dev/null +++ b/dot_config/systemd/user/upower-power-profile-policy.service @@ -0,0 +1,14 @@ +[Unit] +Description=Event-driven power profile policy from UPower state +Documentation=man:upower(1) man:powerprofilesctl(1) +After=graphical-session.target +PartOf=graphical-session.target + +[Service] +Type=simple +ExecStart=%h/.local/bin/upower-power-profile-policy.py +Restart=on-failure +RestartSec=2s + +[Install] +WantedBy=graphical-session.target diff --git a/dot_config/systemd/user/xdg-desktop-portal.service.d/override.conf b/dot_config/systemd/user/xdg-desktop-portal.service.d/override.conf new file mode 100644 index 0000000..9459fa5 --- /dev/null +++ b/dot_config/systemd/user/xdg-desktop-portal.service.d/override.conf @@ -0,0 +1,4 @@ +[Unit] +After=darkman.service +Wants=xdg-desktop-portal-gtk.service xdg-desktop-portal-hyprland.service + diff --git a/dot_config/theme/foot.ini b/dot_config/theme/foot.ini new file mode 100644 index 0000000..ff97c23 --- /dev/null +++ b/dot_config/theme/foot.ini @@ -0,0 +1,65 @@ +[colors-dark] +background=100f0f +foreground=fffcf0 + +## Normal/regular colors (color palette 0-7) +regular0=100f0f # black +regular1=af3029 # red +regular2=66800b # green +regular3=ad8301 # yellow +regular4=205ea6 # blue +regular5=a02f6f # magenta +regular6=24837b # cyan +regular7=fffcf0 # white + +## Bright colors (color palette 8-15) +bright0=100f0f # bright black +bright1=d14d41 # bright red +bright2=879a39 # bright green +bright3=d0a215 # bright yellow +bright4=4385be # bright blue +bright5=ce5d97 # bright magenta +bright6=3aa99f # bright cyan +bright7=fffcf0 # bright white + +## Dim colors +dim0=100f0f # dim black +dim1=af3029 # dim red +dim2=66800b # dim green +dim3=ad8301 # dim yellow +dim4=205ea6 # dim blue +dim5=a02f6f # dim magenta +dim6=24837b # dim cyan +dim7=fffcf0 # dim white + +## The remaining 256-color palette +# 16 = <256-color palette #16> +# ... +# 255 = <256-color palette #255> + +## Sixel colors +# sixel0 = 000000 +# sixel1 = 3333cc +# sixel2 = cc2121 +# sixel3 = 33cc33 +# sixel4 = cc33cc +# sixel5 = 33cccc +# sixel6 = cccc33 +# sixel7 = 878787 +# sixel8 = 424242 +# sixel9 = 545499 +# sixel10 = 994242 +# sixel11 = 549954 +# sixel12 = 995499 +# sixel13 = 549999 +# sixel14 = 999954 +# sixel15 = cccccc + +## Misc colors +# selection-foreground= +# selection-background= +# jump-labels= # black-on-yellow +# scrollback-indicator= # black-on-bright-blue +# search-box-no-match= # black-on-red +# search-box-match= # black-on-yellow +# urls= diff --git a/dot_config/theme/hyprland.conf b/dot_config/theme/hyprland.conf new file mode 100644 index 0000000..ee911ab --- /dev/null +++ b/dot_config/theme/hyprland.conf @@ -0,0 +1,7 @@ +general { + col.active_border = rgba(4385BEee) +} + +group { + col.border_active = rgba(4385BEee) +} diff --git a/dot_config/theme/hyprlock.conf b/dot_config/theme/hyprlock.conf new file mode 100644 index 0000000..03ac408 --- /dev/null +++ b/dot_config/theme/hyprlock.conf @@ -0,0 +1,5 @@ +$color = rgba(16,15,15,1.0) +$inner_color = rgba(28,27,26,1.0) +$outer_color = rgba(64,62,60,1.0) +$font_color = rgba(206,205,195,1.0) +$check_color = rgba(67, 133, 190, 1.0) diff --git a/dot_config/theme/mako b/dot_config/theme/mako new file mode 100644 index 0000000..85ff619 --- /dev/null +++ b/dot_config/theme/mako @@ -0,0 +1,3 @@ +text-color=#cecdc3 +border-color=#4385be +background-color=#100f0f diff --git a/dot_config/theme/vscode.json b/dot_config/theme/vscode.json new file mode 100644 index 0000000..8856cb2 --- /dev/null +++ b/dot_config/theme/vscode.json @@ -0,0 +1,547 @@ +{ + "name": "Flexoki", + "type": "dark", + "colors": { + "editor.background": "#100F0F", + "editor.foreground": "#CECDC3", + "editor.hoverHighlightBackground": "#343331", + "editor.lineHighlightBackground": "#1C1B1A", + "editor.selectionBackground": "#CECDC333", + "editor.selectionHighlightBackground": "#CECDC333", + "editor.findMatchBackground": "#AD8301", + "editor.findMatchHighlightBackground": "#AD8301cc", + "editor.findRangeHighlightBackground": "#1C1B1A", + "editor.inactiveSelectionBackground": "#282726", + "editor.lineHighlightBorder": "#282726", + "editor.rangeHighlightBackground": "#403E3C", + "notifications.background": "#282726", + "editorInlayHint.typeBackground": "#343331", + "editorInlayHint.typeForeground": "#CECDC3", + "editorWhitespace.foreground": "#403E3C", + "editorIndentGuide.background1": "#343331", + "editorHoverWidget.background": "#282726", + "editorLineNumber.activeForeground": "#CECDC3", + "editorLineNumber.foreground": "#403E3C", + "editorGutter.background": "#100F0F", + "editorGutter.modifiedBackground": "#3AA99F", + "editorGutter.addedBackground": "#879A39", + "editorGutter.deletedBackground": "#D14D41", + "editorBracketMatch.background": "#282726", + "editorBracketMatch.border": "#343331", + "editorError.foreground": "#D14D41", + "editorWarning.foreground": "#DA702C", + "editorInfo.foreground": "#4385BE", + "diffEditor.insertedTextBackground": "#66800B99", + "diffEditor.removedTextBackground": "#AF302999", + "editorGroupHeader.tabsBackground": "#100F0F", + "editorGroup.border": "#343331", + "tab.activeBackground": "#100F0F", + "tab.inactiveBackground": "#1C1B1A", + "tab.inactiveForeground": "#878580", + "tab.activeForeground": "#CECDC3", + "tab.hoverBackground": "#343331", + "tab.unfocusedHoverBackground": "#343331", + "tab.border": "#343331", + "tab.activeModifiedBorder": "#D0A215", + "tab.inactiveModifiedBorder": "#4385BE", + "tab.unfocusedActiveModifiedBorder": "#AD8301", + "tab.unfocusedInactiveModifiedBorder": "#205EA6", + "editorWidget.background": "#1C1B1A", + "editorWidget.border": "#343331", + "editorSuggestWidget.background": "#100F0F", + "editorSuggestWidget.border": "#343331", + "editorSuggestWidget.foreground": "#CECDC3", + "editorSuggestWidget.highlightForeground": "#878580", + "editorSuggestWidget.selectedBackground": "#343331", + "peekView.border": "#343331", + "peekViewEditor.background": "#100F0F", + "peekViewEditor.matchHighlightBackground": "#403E3C", + "peekViewResult.background": "#1C1B1A", + "peekViewResult.fileForeground": "#CECDC3", + "peekViewResult.lineForeground": "#878580", + "peekViewResult.matchHighlightBackground": "#403E3C", + "peekViewResult.selectionBackground": "#282726", + "peekViewResult.selectionForeground": "#575653", + "peekViewTitle.background": "#343331", + "peekViewTitleDescription.foreground": "#878580", + "peekViewTitleLabel.foreground": "#CECDC3", + "merge.currentHeaderBackground": "#879A39", + "merge.currentContentBackground": "#66800B", + "merge.incomingHeaderBackground": "#3AA99F", + "merge.incomingContentBackground": "#24837B", + "merge.border": "#343331", + "merge.commonContentBackground": "#403E3C", + "merge.commonHeaderBackground": "#343331", + "panel.background": "#100F0F", + "panel.border": "#343331", + "panelTitle.activeBorder": "#403E3C", + "panelTitle.activeForeground": "#CECDC3", + "panelTitle.inactiveForeground": "#878580", + "statusBar.background": "#100F0F", + "statusBar.foreground": "#CECDC3", + "statusBar.border": "#343331", + "statusBar.debuggingBackground": "#D14D41", + "statusBar.debuggingForeground": "#CECDC3", + "statusBar.noFolderBackground": "#403E3C", + "statusBar.noFolderForeground": "#575653", + "titleBar.activeBackground": "#100F0F", + "titleBar.activeForeground": "#CECDC3", + "titleBar.inactiveBackground": "#1C1B1A", + "titleBar.inactiveForeground": "#878580", + "titleBar.border": "#343331", + "menu.foreground": "#CECDC3", + "menu.background": "#100F0F", + "menu.selectionForeground": "#CECDC3", + "menu.selectionBackground": "#343331", + "menu.border": "#343331", + "editorInlayHint.foreground": "#878580", + "editorInlayHint.background": "#343331", + "terminal.foreground": "#CECDC3", + "terminal.background": "#100F0F", + "terminalCursor.foreground": "#CECDC3", + "terminalCursor.background": "#100F0F", + "terminal.ansiRed": "#D14D41", + "terminal.ansiGreen": "#879A39", + "terminal.ansiYellow": "#D0A215", + "terminal.ansiBlue": "#4385BE", + "terminal.ansiMagenta": "#3AA99F", + "terminal.ansiCyan": "#3AA99F", + "activityBar.background": "#100F0F", + "activityBar.foreground": "#CECDC3", + "activityBar.inactiveForeground": "#878580", + "activityBar.activeBorder": "#CECDC3", + "activityBar.border": "#343331", + "sideBar.background": "#100F0F", + "sideBar.foreground": "#CECDC3", + "sideBar.border": "#343331", + "sideBarTitle.foreground": "#CECDC3", + "sideBarSectionHeader.background": "#1C1B1A", + "sideBarSectionHeader.foreground": "#CECDC3", + "sideBarSectionHeader.border": "#343331", + "sideBar.activeBackground": "#403E3C", + "sideBar.activeForeground": "#CECDC3", + "sideBar.hoverBackground": "#343331", + "sideBar.hoverForeground": "#878580", + "sideBar.folderIcon.foreground": "#879A39", + "sideBar.fileIcon.foreground": "#4385BE", + "list.warningForeground": "#DA702C", + "list.errorForeground": "#D14D41", + "list.inactiveSelectionBackground": "#343331", + "list.activeSelectionBackground": "#403E3C", + "list.inactiveSelectionForeground": "#CECDC3", + "list.activeSelectionForeground": "#CECDC3", + "list.hoverForeground": "#CECDC3", + "list.hoverBackground": "#343331", + "input.background": "#1C1B1A", + "input.foreground": "#CECDC3", + "input.border": "#343331", + "input.placeholderForeground": "#878580", + "inputOption.activeBorder": "#343331", + "inputOption.activeBackground": "#282726", + "inputOption.activeForeground": "#CECDC3", + "inputValidation.infoBackground": "#3AA99F", + "inputValidation.infoBorder": "#24837B", + "inputValidation.warningBackground": "#DA702C", + "inputValidation.warningBorder": "#BC5215", + "inputValidation.errorBackground": "#D14D41", + "inputValidation.errorBorder": "#AF3029", + "dropdown.background": "#1C1B1A", + "dropdown.foreground": "#CECDC3", + "dropdown.border": "#343331", + "dropdown.listBackground": "#100F0F", + "badge.background": "#3AA99F", + "activityBarBadge.background": "#3AA99F", + "button.background": "#3AA99F", + "button.foreground": "#100F0F", + "badge.foreground": "#100F0F", + "activityBarBadge.foreground": "#100F0F" + }, + "tokenColors": [ + { + "name": "plain", + "scope": ["source", "support.type.property-name.css"], + "settings": { + "foreground": "#CECDC3" + } + }, + { + "name": "classes", + "scope": ["entity.name.type.class"], + "settings": { + "foreground": "#DA702C" + } + }, + { + "name": "interfaces", + "scope": ["entity.name.type.interface", "entity.name.type"], + "settings": { + "foreground": "#D0A215" + } + }, + { + "name": "structs", + "scope": ["entity.name.type.struct"], + "settings": { + "foreground": "#DA702C" + } + }, + { + "name": "enums", + "scope": ["entity.name.type.enum"], + "settings": { + "foreground": "#DA702C" + } + }, + { + "name": "keys", + "scope": ["meta.object-literal.key", "support.type.property-name"], + "settings": { + "foreground": "#DA702C" + } + }, + { + "name": "methods", + "scope": ["entity.name.function.method", "meta.function.method"], + "settings": { + "foreground": "#879A39" + } + }, + { + "name": "functions", + "scope": [ + "entity.name.function", + "support.function", + "meta.function-call.generic" + ], + "settings": { + "foreground": "#DA702C", + "fontStyle": "bold" + } + }, + { + "name": "variables", + "scope": ["variable", "meta.variable", "variable.other.object.property"], + "settings": { + "foreground": "#CECDC3" + } + }, + { + "name": "variablesOther", + "scope": ["variable.other.object", "variable.other.readwrite.alias"], + "settings": { + "foreground": "#879A39" + } + }, + { + "name": "globalVariables", + "scope": ["variable.other.global", "variable.language.this"], + "settings": { + "foreground": "#CE5D97" + } + }, + { + "name": "localVariables", + "scope": ["variable.other.local"], + "settings": { + "foreground": "#282726" + } + }, + { + "name": "parameters", + "scope": ["variable.parameter", "meta.parameter"], + "settings": { + "foreground": "#CECDC3" + } + }, + { + "name": "properties", + "scope": ["variable.other.property", "meta.property"], + "settings": { + "foreground": "#4385BE" + } + }, + { + "name": "strings", + "scope": [ + "string", + "string.other.link", + "markup.inline.raw.string.markdown" + ], + "settings": { + "foreground": "#3AA99F" + } + }, + { + "name": "stringEscapeSequences", + "scope": ["constant.character.escape", "constant.other.placeholder"], + "settings": { + "foreground": "#CECDC3" + } + }, + { + "name": "keywords", + "scope": ["keyword"], + "settings": { + "foreground": "#879A39" + } + }, + { + "name": "keywordsControl", + "scope": [ + "keyword.control.import", + "keyword.control.from", + "keyword.import" + ], + "settings": { + "foreground": "#D14D41" + } + }, + { + "name": "storageModifiers", + "scope": ["storage.modifier", "keyword.modifier", "storage.type"], + "settings": { + "foreground": "#4385BE" + } + }, + { + "name": "comments", + "scope": ["comment", "punctuation.definition.comment"], + "settings": { + "foreground": "#878580" + } + }, + { + "name": "docComments", + "scope": ["comment.documentation", "comment.line.documentation"], + "settings": { + "foreground": "#575653" + } + }, + { + "name": "numbers", + "scope": ["constant.numeric"], + "settings": { + "foreground": "#8B7EC8" + } + }, + { + "name": "booleans", + "scope": ["constant.language.boolean", "constant.language.json"], + "settings": { + "foreground": "#D0A215" + } + }, + { + "name": "operators", + "scope": ["keyword.operator"], + "settings": { + "foreground": "#D14D41" + } + }, + { + "name": "macros", + "scope": ["entity.name.function.preprocessor", "meta.preprocessor"], + "settings": { + "foreground": "#4385BE" + } + }, + { + "name": "preprocessor", + "scope": ["meta.preprocessor"], + "settings": { + "foreground": "#CE5D97" + } + }, + { + "name": "urls", + "scope": ["markup.underline.link"], + "settings": { + "foreground": "#4385BE" + } + }, + { + "name": "tags", + "scope": ["entity.name.tag"], + "settings": { + "foreground": "#4385BE" + } + }, + { + "name": "jsxTags", + "scope": ["support.class.component"], + "settings": { + "foreground": "#CE5D97" + } + }, + { + "name": "attributes", + "scope": ["entity.other.attribute-name", "meta.attribute"], + "settings": { + "foreground": "#D0A215" + } + }, + { + "name": "types", + "scope": ["support.type"], + "settings": { + "foreground": "#D0A215" + } + }, + { + "name": "constants", + "scope": ["variable.other.constant", "variable.readonly"], + "settings": { + "foreground": "#CECDC3" + } + }, + { + "name": "labels", + "scope": ["entity.name.label", "punctuation.definition.label"], + "settings": { + "foreground": "#CE5D97" + } + }, + { + "name": "namespaces", + "scope": [ + "entity.name.namespace", + "storage.modifier.namespace", + "markup.bold.markdown" + ], + "settings": { + "foreground": "#D0A215" + } + }, + { + "name": "modules", + "scope": ["entity.name.module", "storage.modifier.module"], + "settings": { + "foreground": "#D14D41" + } + }, + { + "name": "typeParameters", + "scope": ["variable.type.parameter", "variable.parameter.type"], + "settings": { + "foreground": "#DA702C" + } + }, + { + "name": "exceptions", + "scope": ["keyword.control.exception", "keyword.control.trycatch"], + "settings": { + "foreground": "#CE5D97" + } + }, + { + "name": "decorators", + "scope": [ + "meta.decorator", + "punctuation.decorator", + "entity.name.function.decorator" + ], + "settings": { + "foreground": "#D0A215" + } + }, + { + "name": "calls", + "scope": ["variable.function"], + "settings": { + "foreground": "#CECDC3" + } + }, + { + "name": "punctuation", + "scope": [ + "punctuation", + "punctuation.terminator", + "punctuation.definition.tag", + "punctuation.separator", + "punctuation.definition.string", + "punctuation.section.block" + ], + "settings": { + "foreground": "#878580" + } + }, + { + "name": "yellow", + "scope": [ + "storage.type.numeric.go", + "storage.type.byte.go", + "storage.type.boolean.go", + "storage.type.string.go", + "storage.type.uintptr.go", + "storage.type.error.go", + "storage.type.rune.go", + "constant.language.go", + "support.class.dart", + "keyword.other.documentation", + "storage.modifier.import.java", + "punctuation.definition.list.begin.markdown", + "punctuation.definition.quote.begin.markdown", + "meta.separator.markdown", + "entity.name.section.markdown" + ], + "settings": { + "foreground": "#D0A215" + } + }, + { + "name": "green", + "scope": [], + "settings": { + "foreground": "#879A39" + } + }, + { + "name": "cyan", + "scope": [ + "markup.italic.markdown", + "support.type.python", + "variable.legacy.builtin.python", + "support.constant.property-value.css", + "storage.modifier.attribute.swift" + ], + "settings": { + "foreground": "#3AA99F" + } + }, + { + "name": "blue", + "scope": [], + "settings": { + "foreground": "#4385BE" + } + }, + { + "name": "purple", + "scope": ["keyword.channel.go", "keyword.other.platform.os.swift"], + "settings": { + "foreground": "#8B7EC8" + } + }, + { + "name": "magenta", + "scope": ["punctuation.definition.heading.markdown"], + "settings": { + "foreground": "#CE5D97" + } + }, + { + "name": "red", + "scope": [], + "settings": { + "foreground": "#D14D41" + } + }, + { + "name": "orange", + "scope": [], + "settings": { + "foreground": "#DA702C" + } + } + ] +} \ No newline at end of file diff --git a/dot_config/theme/waybar.css b/dot_config/theme/waybar.css new file mode 100644 index 0000000..fabd14f --- /dev/null +++ b/dot_config/theme/waybar.css @@ -0,0 +1,2 @@ +@define-color foreground #CECDC3; +@define-color background #100F0F; diff --git a/dot_config/uwsm/env b/dot_config/uwsm/env new file mode 100644 index 0000000..a613f8b --- /dev/null +++ b/dot_config/uwsm/env @@ -0,0 +1,3 @@ +export GDK_BACKEND=wayland,x11,* +export QT_QPA_PLATFORM="wayland;xcb" +export ELECTRON_OZONE_PLATFORM_HINT=auto diff --git a/dot_config/uwsm/env-hyprland b/dot_config/uwsm/env-hyprland new file mode 100644 index 0000000..715bc92 --- /dev/null +++ b/dot_config/uwsm/env-hyprland @@ -0,0 +1,2 @@ +export XCURSOR_SIZE=24 +export HYPRCURSOR_SIZE=24 diff --git a/dot_config/waybar/config.jsonc b/dot_config/waybar/config.jsonc new file mode 100644 index 0000000..242849d --- /dev/null +++ b/dot_config/waybar/config.jsonc @@ -0,0 +1,143 @@ +{ + "reload_style_on_change": true, + "layer": "top", + "position": "top", + "spacing": 0, + "height": 26, + "modules-left": ["hyprland/workspaces"], + "modules-center": ["hyprland/window"], + "modules-right": [ + "group/tray-expander", + "idle_inhibitor", + "power-profiles-daemon", + "network", + "wireplumber", + "battery", + "clock", + "custom/power-menu" + ], + "hyprland/workspaces": { + "format": "{icon}", + "format-icons": { + "default": "", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7", + "8": "8", + "9": "9", + "active": "󱓻" + }, + "persistent-workspaces": { + "1": [], + "2": [], + "3": [], + "4": [], + "5": [] + } + }, + "clock": { + "format": "{:L%A %H:%M}", + "format-alt": "{%Y %B :L%d W%V}", + "tooltip-format": "{calendar}", + "calendar": { + "mode" : "year", + "mode-mon-col" : 3, + "weeks-pos" : "right", + "on-scroll" : 1, + "format": { + "months": "{}", + "days": "{}", + "weeks": "W{}", + "weekdays": "{}", + "today": "{}" + } + } + }, + "network": { + "format-icons": ["󰤯", "󰤟", "󰤢", "󰤥", "󰤨"], + "format": "{icon}", + "format-wifi": "{icon}", + "format-ethernet": "󰀂", + "format-disconnected": "󰖪", + "tooltip-format-wifi": "{essid} ({frequency} GHz)\n⇣{bandwidthDownBytes} ⇡{bandwidthUpBytes}", + "tooltip-format-ethernet": "⇣{bandwidthDownBytes} ⇡{bandwidthUpBytes}", + "tooltip-format-disconnected": "Disconnected", + "interval": 3, + "spacing": 1, + "on-click": "iwmenu -l walker" + }, + "battery": { + "format": "{capacity}% {icon}", + "format-discharging": "{icon}", + "format-charging": "{icon}", + "format-plugged": "", + "format-icons": { + "charging": ["󰢜", "󰂆", "󰂇", "󰂈", "󰢝", "󰂉", "󰢞", "󰂊", "󰂋", "󰂅"], + "default": ["󰁺", "󰁻", "󰁼", "󰁽", "󰁾", "󰁿", "󰂀", "󰂁", "󰂂", "󰁹"] + }, + "format-full": "󰂅", + "tooltip-format-discharging": "{power:>1.0f}W↓ {capacity}%", + "tooltip-format-charging": "{power:>1.0f}W↑ {capacity}%", + "interval": 5, + "states": { + "warning": 20, + "critical": 10 + } + }, + "idle_inhibitor": { + "format": "{icon}", + "format-icons": { + "activated": "", + "deactivated": "" + } + }, + "wireplumber": { + "format": "{icon}", + "on-click": "helvum", + "on-click-right": "pamixer -t", + "tooltip-format": "Playing at {volume}%", + "scroll-step": 5, + "format-muted": "󰝟", + "format-icons": { + "default": ["", "", ""] + } + }, + "power-profiles-daemon": { + "format": "{icon}", + "tooltip-format": "Power profile: {profile}\nDriver: {driver}", + "tooltip": true, + "format-icons": { + "default": "", + "performance": "", + "balanced": "", + "power-saver": "" + } + }, + "group/tray-expander": { + "orientation": "inherit", + "drawer": { + "transition-duration": 600, + "children-class": "tray-group-item" + }, + "modules": ["custom/expand-icon", "tray"] + }, + "custom/expand-icon": { + "format": " ", + "tooltip": false + }, + "tray": { + "icon-size": 12, + "spacing": 12 + }, + "custom/power-menu": { + "format": "⏻", + "tooltip": true, + "tooltip-format": "Power menu", + "on-click": "~/.local/bin/power-menu.sh" + } +} + diff --git a/dot_config/waybar/style.css b/dot_config/waybar/style.css new file mode 100644 index 0000000..ed7164a --- /dev/null +++ b/dot_config/waybar/style.css @@ -0,0 +1,60 @@ +@import "/home/cameron/.config/theme/waybar.css"; + +* { + background-color: @background; + color: @foreground; + border: none; + border-radius: 0; + min-height: 0; + font-family: monospace; + font-size: 12px; +} + +.modules-left { + margin-left: 8px; +} + +.modules-right { + margin-right: 8px; +} + +#workspaces button { + all: initial; + padding: 0 6px; + margin: 0 1.5px; + min-width: 9px; +} + +#workspaces button.empty { + opacity: 0.5; +} + +#tray, +#idle_inhibitor, +#power-profiles-daemon, +#cpu, +#battery, +#network, +#clock, +#wireplumber, +#custom-power-menu { + min-width: 12px; + margin: 0 7.5px; +} + +#custom-expand-icon { + margin-right: 7px; +} + +tooltip { + padding: 2px; +} + +#window { + margin-left: 8.75px; +} + +.hidden { + opacity: 0; +} + diff --git a/dot_config/xdg-desktop-portal/portals.conf b/dot_config/xdg-desktop-portal/portals.conf new file mode 100644 index 0000000..3334903 --- /dev/null +++ b/dot_config/xdg-desktop-portal/portals.conf @@ -0,0 +1,8 @@ +[preferred] +default=gtk +org.freedesktop.impl.portal.Settings=darkman;gtk +org.freedesktop.impl.portal.ScreenCast=hyprland;gtk +org.freedesktop.impl.portal.Screenshot=hyprland;gtk +org.freedesktop.impl.portal.GlobalShortcuts=hyprland +org.freedesktop.impl.portal.Inhibit=gtk + diff --git a/dot_gitconfig b/dot_gitconfig new file mode 100644 index 0000000..b226c1e --- /dev/null +++ b/dot_gitconfig @@ -0,0 +1,5 @@ +[user] + name = Cameron Otsuka + email = cameron@otsuka.haus +[url "git@github.com:"] + insteadOf = https://github.com/ diff --git a/dot_zshenv b/dot_zshenv new file mode 100644 index 0000000..c8c8e84 --- /dev/null +++ b/dot_zshenv @@ -0,0 +1,14 @@ +export XDG_CONFIG_HOME=$HOME/.config +export XDG_CACHE_HOME=$HOME/.cache +export XDG_DATA_HOME=$HOME/.local/share +export XDG_STATE_HOME=$HOME/.local/state +export XDG_BIN_HOME=$HOME/.local/bin + +export EDITOR=nvim +export VISUAL=nvim +export SUDO_EDITOR=$VISUAL + +export RUSTC_WRAPPER=sccache + +export PATH="$HOME/.local/bin:$PATH" + diff --git a/private_dot_local/bin/executable_power-menu.sh b/private_dot_local/bin/executable_power-menu.sh new file mode 100644 index 0000000..b3d753b --- /dev/null +++ b/private_dot_local/bin/executable_power-menu.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +set -euo pipefail + +choice=$(zenity --list \ + --title='Power Menu' \ + --text='Choose an action:' \ + --width=360 \ + --height=320 \ + --hide-header \ + --print-column=1 \ + --ok-label='Select' \ + --cancel-label='Cancel' \ + --column='Action' \ + '⏻ Power Off' \ + '⏾ Hibernate' \ + '↻ Reboot' \ + '⇠ Log Out' 2>/dev/null || true) + +case "$choice" in + '⏻ Power Off') + systemctl poweroff + ;; + '⏾ Hibernate') + systemctl hibernate + ;; + '↻ Reboot') + systemctl reboot + ;; + '⇠ Log Out') + uwsm stop + ;; + '') + exit 0 + ;; + *) + notify-send 'Power Menu' "Unknown selection: $choice" + exit 1 + ;; +esac diff --git a/private_dot_local/bin/executable_upower-power-profile-policy.py b/private_dot_local/bin/executable_upower-power-profile-policy.py new file mode 100644 index 0000000..9f9d6c0 --- /dev/null +++ b/private_dot_local/bin/executable_upower-power-profile-policy.py @@ -0,0 +1,318 @@ +#!/usr/bin/env python3 + +import configparser +import logging +import signal +import sys + +import dbus +import dbus.mainloop.glib +from gi.repository import GLib + +DBUS_BUS = "org.freedesktop.DBus" +DBUS_PATH = "/org/freedesktop/DBus" +DBUS_IFACE = "org.freedesktop.DBus" +PROPS_IFACE = "org.freedesktop.DBus.Properties" + +UPOWER_BUS = "org.freedesktop.UPower" +UPOWER_PATH = "/org/freedesktop/UPower" +UPOWER_IFACE = "org.freedesktop.UPower" +DISPLAY_DEVICE_PATH = "/org/freedesktop/UPower/devices/DisplayDevice" +UPOWER_DEVICE_IFACE = "org.freedesktop.UPower.Device" +UPOWER_CONFIG = "/etc/UPower/UPower.conf" + +PPD_BUS = "org.freedesktop.UPower.PowerProfiles" +PPD_PATH = "/org/freedesktop/UPower/PowerProfiles" +PPD_IFACE = "org.freedesktop.UPower.PowerProfiles" + +WARNING_LEVELS = { + 0: "unknown", + 1: "none", + 2: "discharging", + 3: "low", + 4: "critical", + 5: "action", + 6: "normal", + 7: "high", + 8: "full", +} +LOW_BATTERY_LEVELS = {3, 4, 5} +DEFAULT_LOW_BATTERY_PERCENT = 20.0 +APPLY_DEBOUNCE_MS = 250 + + +class PowerProfilePolicy: + def __init__(self) -> None: + self.bus = dbus.SystemBus() + self.loop = GLib.MainLoop() + self._last_summary = None + self._pending_apply_source = None + self._pending_reason = None + self.low_battery_percent = self._load_low_battery_percent() + + def _load_low_battery_percent(self): + parser = configparser.ConfigParser() + + try: + files = parser.read(UPOWER_CONFIG) + except (configparser.Error, OSError) as exc: + logging.warning( + "Could not read %s, using default %.1f%% low battery threshold: %s", + UPOWER_CONFIG, + DEFAULT_LOW_BATTERY_PERCENT, + exc, + ) + return DEFAULT_LOW_BATTERY_PERCENT + + if not files: + logging.info( + "Could not read %s, using default %.1f%% low battery threshold", + UPOWER_CONFIG, + DEFAULT_LOW_BATTERY_PERCENT, + ) + return DEFAULT_LOW_BATTERY_PERCENT + + try: + use_percentage = parser.getboolean("UPower", "UsePercentageForPolicy", fallback=True) + except (configparser.Error, ValueError) as exc: + logging.warning( + "Could not read UsePercentageForPolicy from %s, using default %.1f%%: %s", + UPOWER_CONFIG, + DEFAULT_LOW_BATTERY_PERCENT, + exc, + ) + return DEFAULT_LOW_BATTERY_PERCENT + + if not use_percentage: + logging.info( + "%s has UsePercentageForPolicy=false; falling back to UPower warning levels", + UPOWER_CONFIG, + ) + return None + + try: + low_battery_percent = parser.getfloat( + "UPower", + "PercentageLow", + fallback=DEFAULT_LOW_BATTERY_PERCENT, + ) + except (configparser.Error, ValueError) as exc: + logging.warning( + "Could not read PercentageLow from %s, using default %.1f%%: %s", + UPOWER_CONFIG, + DEFAULT_LOW_BATTERY_PERCENT, + exc, + ) + return DEFAULT_LOW_BATTERY_PERCENT + + if not 0.0 < low_battery_percent <= 100.0: + logging.warning( + "Invalid PercentageLow %.1f in %s, using default %.1f%%", + low_battery_percent, + UPOWER_CONFIG, + DEFAULT_LOW_BATTERY_PERCENT, + ) + return DEFAULT_LOW_BATTERY_PERCENT + + logging.info( + "Using low battery threshold %.1f%% from %s", + low_battery_percent, + UPOWER_CONFIG, + ) + return low_battery_percent + + def _get_property(self, bus_name: str, object_path: str, interface: str, prop: str): + obj = self.bus.get_object(bus_name, object_path) + props = dbus.Interface(obj, PROPS_IFACE) + return props.Get(interface, prop) + + def _set_active_profile(self, profile: str) -> None: + obj = self.bus.get_object(PPD_BUS, PPD_PATH) + props = dbus.Interface(obj, PROPS_IFACE) + props.Set(PPD_IFACE, "ActiveProfile", dbus.String(profile)) + + def _read_state(self): + on_battery = bool(self._get_property(UPOWER_BUS, UPOWER_PATH, UPOWER_IFACE, "OnBattery")) + warning_level = int( + self._get_property( + UPOWER_BUS, + DISPLAY_DEVICE_PATH, + UPOWER_DEVICE_IFACE, + "WarningLevel", + ) + ) + percentage = float( + self._get_property( + UPOWER_BUS, + DISPLAY_DEVICE_PATH, + UPOWER_DEVICE_IFACE, + "Percentage", + ) + ) + current_profile = str( + self._get_property(PPD_BUS, PPD_PATH, PPD_IFACE, "ActiveProfile") + ) + return on_battery, warning_level, percentage, current_profile + + def _is_low_battery(self, warning_level: int, percentage: float) -> bool: + if self.low_battery_percent is not None: + return percentage <= self.low_battery_percent + return warning_level in LOW_BATTERY_LEVELS + + def _target_profile(self, on_battery: bool, low_battery: bool) -> str: + if not on_battery: + return "performance" + if low_battery: + return "power-saver" + return "balanced" + + def _schedule_apply_policy(self, reason: str) -> None: + self._pending_reason = reason + + if self._pending_apply_source is not None: + GLib.source_remove(self._pending_apply_source) + + self._pending_apply_source = GLib.timeout_add( + APPLY_DEBOUNCE_MS, + self._apply_scheduled_policy, + ) + + def _apply_scheduled_policy(self): + reason = self._pending_reason or "signal" + self._pending_reason = None + self._pending_apply_source = None + self.apply_policy(reason) + return False + + def apply_policy(self, reason: str) -> None: + try: + on_battery, warning_level, percentage, current_profile = self._read_state() + except dbus.DBusException as exc: + logging.warning("Could not read UPower/PPD state (%s): %s", reason, exc) + return + + low_battery = self._is_low_battery(warning_level, percentage) + target_profile = self._target_profile(on_battery, low_battery) + warning_name = WARNING_LEVELS.get(warning_level, f"unknown({warning_level})") + threshold_desc = ( + f"{self.low_battery_percent:.1f}%" + if self.low_battery_percent is not None + else "warning-level" + ) + summary = ( + on_battery, + warning_level, + round(percentage, 1), + low_battery, + current_profile, + target_profile, + ) + + if summary != self._last_summary: + logging.info( + "Policy check: reason=%s on_battery=%s percentage=%.1f warning_level=%s low_battery=%s threshold=%s current=%s target=%s", + reason, + on_battery, + percentage, + warning_name, + low_battery, + threshold_desc, + current_profile, + target_profile, + ) + self._last_summary = summary + + if current_profile == target_profile: + return + + try: + self._set_active_profile(target_profile) + except dbus.DBusException as exc: + logging.error("Failed to switch profile to %s: %s", target_profile, exc) + return + + logging.info("Switched power profile: %s -> %s", current_profile, target_profile) + + def _on_upower_changed(self, interface_name, changed_properties, invalidated_properties): + if interface_name != UPOWER_IFACE: + return + if "OnBattery" in changed_properties or "OnBattery" in invalidated_properties: + self._schedule_apply_policy("UPower OnBattery change") + + def _on_display_device_changed(self, interface_name, changed_properties, invalidated_properties): + if interface_name != UPOWER_DEVICE_IFACE: + return + + relevant_properties = {"WarningLevel", "Percentage"} + changed = set(changed_properties.keys()) + invalidated = set(invalidated_properties) + matched = sorted((changed | invalidated) & relevant_properties) + + if matched: + self._schedule_apply_policy( + f"UPower display device change ({', '.join(matched)})" + ) + + def _on_name_owner_changed(self, name, old_owner, new_owner): + if new_owner: + self._schedule_apply_policy(f"D-Bus name appeared: {name}") + + def run(self) -> None: + self.bus.add_signal_receiver( + self._on_upower_changed, + signal_name="PropertiesChanged", + dbus_interface=PROPS_IFACE, + bus_name=UPOWER_BUS, + path=UPOWER_PATH, + ) + self.bus.add_signal_receiver( + self._on_display_device_changed, + signal_name="PropertiesChanged", + dbus_interface=PROPS_IFACE, + bus_name=UPOWER_BUS, + path=DISPLAY_DEVICE_PATH, + ) + self.bus.add_signal_receiver( + self._on_name_owner_changed, + signal_name="NameOwnerChanged", + dbus_interface=DBUS_IFACE, + bus_name=DBUS_BUS, + path=DBUS_PATH, + arg0=UPOWER_BUS, + ) + self.bus.add_signal_receiver( + self._on_name_owner_changed, + signal_name="NameOwnerChanged", + dbus_interface=DBUS_IFACE, + bus_name=DBUS_BUS, + path=DBUS_PATH, + arg0=PPD_BUS, + ) + + self.apply_policy("startup") + self.loop.run() + + def stop(self, *_args) -> None: + if self._pending_apply_source is not None: + GLib.source_remove(self._pending_apply_source) + self._pending_apply_source = None + self._pending_reason = None + + if self.loop.is_running(): + self.loop.quit() + + +if __name__ == "__main__": + logging.basicConfig( + level=logging.INFO, + format="%(asctime)s %(levelname)s %(message)s", + ) + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + policy = PowerProfilePolicy() + signal.signal(signal.SIGINT, policy.stop) + signal.signal(signal.SIGTERM, policy.stop) + try: + policy.run() + except KeyboardInterrupt: + policy.stop() + sys.exit(0) -- 2.54.0