├── .config ├── fabric │ ├── .gitignore │ ├── assets │ │ ├── arch-symbolic.svg │ │ ├── deta-symbolic.svg │ │ ├── fabric-symbolic.svg │ │ ├── pause.svg │ │ ├── play.svg │ │ ├── profile.png │ │ ├── skip-backward.svg │ │ ├── skip-forward.svg │ │ └── stop.svg │ ├── css │ │ ├── _bar.css │ │ ├── _launcher.css │ │ ├── _notifications.css │ │ ├── _screencorners.css │ │ ├── _sideleft.css │ │ ├── _sideright.css │ │ ├── color.css │ │ ├── dark.css │ │ ├── extra.css │ │ ├── light.css │ │ ├── main.css │ │ └── neutral.css │ ├── icons.py │ ├── imports.py │ ├── main.py │ ├── pyrightconfig.json │ ├── readme.md │ ├── requirements.txt │ └── widgets │ │ ├── bar │ │ ├── _batteryindicator.py │ │ ├── _datetime.py │ │ ├── _globe.py │ │ ├── _logo.py │ │ ├── _minimap.py │ │ ├── _profile.py │ │ ├── _tray.py │ │ ├── _workspace.py │ │ ├── center.py │ │ └── main.py │ │ ├── launcher │ │ ├── _windows.py │ │ ├── main.py │ │ └── test.py │ │ ├── osd │ │ └── notifications.py │ │ ├── screencorners │ │ └── main.py │ │ ├── sideleft │ │ ├── _player.py │ │ ├── _sysinfo.py │ │ ├── _volume.py │ │ ├── _weather.py │ │ └── main.py │ │ └── sideright │ │ ├── _quicksettings.py │ │ └── main.py ├── hypr │ ├── hypridle.conf │ ├── hyprland.conf │ ├── hyprland │ │ ├── colors.conf │ │ ├── env.conf │ │ ├── execs.conf │ │ ├── general.conf │ │ ├── keybinds.conf │ │ └── rules.conf │ └── hyprlock.conf ├── kitty │ └── kitty.conf ├── starship.toml └── wofi │ ├── config │ ├── style.css │ └── styles │ ├── color.css │ ├── dark.css │ ├── light.css │ └── neutral.css ├── .gitignore ├── .pal ├── ai.json ├── browse.json ├── plugins │ ├── mode.py │ └── wallpaper.py ├── templates │ ├── python-venv.sh │ └── sveltekit-tailwindcss-space.sh └── weather.json ├── .wallpapers ├── Dark │ ├── 1.jpg │ ├── 14.jpg │ ├── 2.jpg │ ├── 5.jpg │ └── 8.jpg ├── Light │ ├── 10.jpg │ ├── 11.jpg │ ├── 12.jpg │ ├── 13.jpg │ ├── 3.jpg │ ├── 4.jpg │ ├── 6.jpg │ └── 9.jpg ├── readme.md └── wallpaper.png ├── README.md └── screenshots ├── image-1.png ├── image-2.png ├── image-3.png └── image-4.png /.config/fabric/.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | __pycache__ 3 | .ropeproject 4 | .env 5 | -------------------------------------------------------------------------------- /.config/fabric/assets/arch-symbolic.svg: -------------------------------------------------------------------------------- 1 | Arch Linux -------------------------------------------------------------------------------- /.config/fabric/assets/deta-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.config/fabric/assets/fabric-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /.config/fabric/assets/pause.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.config/fabric/assets/play.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.config/fabric/assets/profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.config/fabric/assets/profile.png -------------------------------------------------------------------------------- /.config/fabric/assets/skip-backward.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.config/fabric/assets/skip-forward.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.config/fabric/assets/stop.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.config/fabric/css/_bar.css: -------------------------------------------------------------------------------- 1 | #center { 2 | border: 2px solid alpha(@background, 0.2); 3 | border-radius: 10px; 4 | padding: 6px; 5 | background-color: alpha(@background, 0.6); 6 | color: @font; 7 | } 8 | 9 | #datetime { 10 | font-size: 16px; 11 | } 12 | 13 | #indicator { 14 | border-radius: 100%; 15 | min-width: 6px; 16 | min-height: 6px; 17 | margin: 8px 3px 8px 6px; 18 | } 19 | 20 | #tlcontainer { 21 | margin: 0px 3px 0px 3px; 22 | background-color: alpha(@background-secondary, 0.2); 23 | padding: 4px 9px 4px 9px; 24 | border-radius: 6px; 25 | } 26 | 27 | #globe { 28 | margin: 0px 3px 0px 3px; 29 | background-color: alpha(@background-secondary, 0.2); 30 | padding: 4px 9px 4px 9px; 31 | border-radius: 6px; 32 | } 33 | 34 | #logo { 35 | margin: 0px 3px 0px 3px; 36 | background-color: alpha(@background-secondary, 0.2); 37 | padding: 5px 9px 5px 9px; 38 | border-radius: 6px; 39 | } 40 | 41 | #center-minimap { 42 | background-color: alpha(@background-secondary, 0.2); 43 | min-width: 128px; 44 | border-radius: 6px; 45 | margin-left: 3px; 46 | } 47 | 48 | #center-workspace { 49 | margin-left: 4px; 50 | } 51 | 52 | #pwcontainer { 53 | margin-right: 3px; 54 | background-color: alpha(@background-secondary, 0.2); 55 | padding: 0px 8px 0px 0px; 56 | border-radius: 6px; 57 | } 58 | 59 | #center-profile { 60 | background-image: url("../assets/profile.png"); 61 | background-size: 100%; 62 | border-radius: 8px; 63 | padding: 0px 15px 0px 15px; 64 | margin-right: 4px; 65 | } 66 | 67 | #right-battery { 68 | border: 2px solid alpha(@background, 0.2); 69 | border-radius: 10px; 70 | padding: 6px; 71 | background-color: alpha(@background, 0.6); 72 | color: @font; 73 | margin-left: 4px; 74 | } 75 | 76 | #right-battery-details { 77 | background-color: alpha(@background-secondary, 0.2); 78 | padding: 4px 9px 4px 9px; 79 | border-radius: 6px; 80 | } 81 | 82 | #left-tray { 83 | border: 2px solid alpha(@background, 0.2); 84 | border-radius: 10px; 85 | padding: 6px; 86 | background-color: alpha(@background, 0.6); 87 | color: @onBackground; 88 | margin-right: 4px; 89 | } 90 | 91 | #left-tray-details { 92 | background-color: alpha(@background-secondary, 0.2); 93 | padding: 4px 9px 4px 9px; 94 | border-radius: 6px; 95 | } 96 | 97 | #left-tray-details > button { 98 | margin: 0px 4px 0px 4px; 99 | } 100 | -------------------------------------------------------------------------------- /.config/fabric/css/_launcher.css: -------------------------------------------------------------------------------- 1 | #launcher { 2 | border: 2px solid alpha(@background, 0.2); 3 | border-radius: 8px; 4 | background-color: alpha(@background, 0.8); 5 | color: @font; 6 | padding: 6px; 7 | } 8 | 9 | #launcher-search { 10 | padding: 16px; 11 | font-size: 14px; 12 | } 13 | 14 | #launcher-apps { 15 | font-size: 13px; 16 | padding: 8px 8px 0px 8px; 17 | } 18 | 19 | #launcher-area { 20 | border: 1px solid alpha(@background, 0.2); 21 | background-color: alpha(@background, 0.2); 22 | } 23 | 24 | #launcher-details { 25 | background-color: alpha(@background, 0.4); 26 | border-top: 1px solid alpha(@background, 0.2); 27 | padding: 8px 12px 8px 12px; 28 | border-radius: 0px 0px 8px 8px; 29 | } 30 | 31 | #launcher-details-label { 32 | font-size: 12px; 33 | font-weight: bold; 34 | margin-right: 8px; 35 | } 36 | 37 | #launcher-details-icon { 38 | background-color: @background-tertiary; 39 | border-radius: 4px; 40 | padding: 4px; 41 | color: @font; 42 | } 43 | 44 | #launcher-app { 45 | border-radius: 12px; 46 | } 47 | 48 | #launcher-app:hover { 49 | background-color: alpha(@background-secondary, 0.2); 50 | } 51 | 52 | #launcher-app:focus { 53 | background-color: alpha(@background-secondary, 0.4); 54 | } 55 | 56 | #launcher-app:nth-child(1) { 57 | margin-top: 0px; 58 | } 59 | 60 | #launcher-app-icon { 61 | margin: 8px; 62 | } 63 | 64 | #launcher-app-label { 65 | color: @font-secondary; 66 | margin-right: 8px; 67 | } 68 | -------------------------------------------------------------------------------- /.config/fabric/css/_notifications.css: -------------------------------------------------------------------------------- 1 | #notification { 2 | padding: 8px; 3 | border: 2px solid alpha(@background, 0.2); 4 | border-radius: 8.01px; 5 | background-color: alpha(@background, 0.8); 6 | } 7 | 8 | #notification .summary { 9 | font-size: 20px; 10 | font-weight: bold; 11 | color: @font; 12 | } 13 | 14 | #notification .body { 15 | color: @font-secondary; 16 | font-weight: normal; 17 | } 18 | 19 | #notification-button { 20 | background-color: alpha(@background, 0.6); 21 | border: 2px solid alpha(@background, 0.2); 22 | border-radius: 8px; 23 | padding: 8px; 24 | } 25 | 26 | #notification-close { 27 | background-color: alpha(@background, 0.6); 28 | border: 2px solid alpha(@background, 0.2); 29 | border-radius: 8px; 30 | padding: 2px; 31 | margin-left: 8px; 32 | } 33 | -------------------------------------------------------------------------------- /.config/fabric/css/_screencorners.css: -------------------------------------------------------------------------------- 1 | #corner-top-left { 2 | background-color: #000000; 3 | } 4 | 5 | #corner-top-right { 6 | background-color: #000000; 7 | } 8 | 9 | #corner-bottom-left { 10 | background-color: #000000; 11 | } 12 | 13 | #corner-bottom-right { 14 | background-color: #000000; 15 | } -------------------------------------------------------------------------------- /.config/fabric/css/_sideleft.css: -------------------------------------------------------------------------------- 1 | #side-left { 2 | border: 2px solid alpha(@background, 0.2); 3 | border-radius: 8.01px; 4 | background-color: alpha(@background, 0.8); 5 | } 6 | 7 | #side-left-container { 8 | margin: 10px; 9 | border: 2px; 10 | border-radius: 8px; 11 | } 12 | 13 | #left-player { 14 | background-color: alpha(@background, 0.6); 15 | border: 2px solid alpha(@background, 0.2); 16 | border-radius: 6px; 17 | } 18 | 19 | #left-player-art { 20 | padding: 64px; 21 | background-size: cover; 22 | background-color: alpha(@background-secondary, 0.2); 23 | border-radius: 6px; 24 | margin: 8px; 25 | } 26 | 27 | #left-player-title { 28 | font-weight: 700; 29 | font-size: 18px; 30 | color: @font; 31 | } 32 | 33 | #left-player-artist { 34 | font-weight: 300; 35 | font-size: 16px; 36 | color: @font; 37 | } 38 | 39 | #left-player-info { 40 | margin: 16px; 41 | } 42 | 43 | #left-player-controls { 44 | margin-top: 16px; 45 | padding: 0px 8px 0px 8px; 46 | } 47 | 48 | #left-player-icon { 49 | font-family: tabler-icons; 50 | font-weight: normal; 51 | font-size: 30px; 52 | color: @font; 53 | } 54 | 55 | #floating-player { 56 | border: 2px solid alpha(@background, 0.2); 57 | border-radius: 8px; 58 | background-color: alpha(@background, 0.8); 59 | } 60 | 61 | #floating-art { 62 | padding: 64px; 63 | background-size: cover; 64 | background-color: alpha(@background-secondary, 0.2); 65 | border-radius: 6px; 66 | margin: 8px; 67 | } 68 | 69 | #floating-controls { 70 | margin: 0px 12px 0px; 71 | } 72 | 73 | #left-sysinfo { 74 | background-color: alpha(@background, 0.6); 75 | border: 2px solid alpha(@background, 0.2); 76 | border-radius: 6px; 77 | padding: 8px; 78 | margin-top: 8px; 79 | } 80 | 81 | #left-sysinfo-box:nth-child(1) { 82 | margin-right: 8px; 83 | } 84 | 85 | #left-sysinfo-box:nth-child(2), 86 | #left-sysinfo-box:nth-child(3) { 87 | margin: 0px 8px 0px 8px; 88 | } 89 | 90 | #left-sysinfo-box:nth-child(4) { 91 | margin-left: 8px; 92 | } 93 | 94 | #left-sysinfo-circular { 95 | color: alpha(@background-secondary, 0.2); 96 | border: solid 8px @font; 97 | } 98 | 99 | #left-sysinfo-icon { 100 | font-family: tabler-icons; 101 | font-weight: normal; 102 | font-size: 24px; 103 | color: @font; 104 | } 105 | 106 | #left-weather { 107 | background-color: alpha(@background, 0.6); 108 | border: 2px solid alpha(@background, 0.2); 109 | border-radius: 6px; 110 | margin-top: 8px; 111 | } 112 | 113 | #weather-temperature { 114 | font-weight: bold; 115 | font-size: 60px; 116 | color: @font; 117 | padding: 20px; 118 | } 119 | 120 | #weather-condition { 121 | font-size: 24px; 122 | padding-bottom: 4px; 123 | color: @font; 124 | } 125 | 126 | #weather-location { 127 | font-size: 12px; 128 | color: @font; 129 | margin-right: 4px; 130 | } 131 | 132 | #weather-time { 133 | font-size: 12px; 134 | color: @font; 135 | margin-left: 4px; 136 | } 137 | 138 | #weather-icon { 139 | background-size: cover; 140 | border-radius: 6px; 141 | padding: 48px; 142 | margin: 8px; 143 | } 144 | 145 | #left-volume { 146 | background-color: alpha(@background, 0.6); 147 | border: 2px solid alpha(@background, 0.2); 148 | border-radius: 6px; 149 | margin-top: 8px; 150 | padding: 4px; 151 | } 152 | 153 | #volume-label { 154 | font-size: 16px; 155 | margin-left: 8px; 156 | color: @font; 157 | } 158 | 159 | #volume-slider { 160 | padding: 12px; 161 | background-color: alpha(@background-secondary, 0.2); 162 | border-radius: 32px; 163 | margin: 8px; 164 | } 165 | -------------------------------------------------------------------------------- /.config/fabric/css/_sideright.css: -------------------------------------------------------------------------------- 1 | #side-right { 2 | border: 2px solid alpha(@background, 0.2); 3 | border-radius: 8.01px; 4 | background-color: alpha(@background, 0.8); 5 | } 6 | 7 | #side-right-container { 8 | margin: 10px; 9 | border: 2px; 10 | border-radius: 8px; 11 | } 12 | 13 | #quicksettings-container button { 14 | background-color: alpha(@background, 0.6); 15 | border: 2px solid alpha(@background, 0.2); 16 | border-radius: 8px; 17 | padding: 16px 38px 16px; 18 | margin: 2px; 19 | } 20 | 21 | #quicksettings-container button.active { 22 | background-color: @background-alternate; 23 | color: @font-secondary; 24 | } 25 | 26 | #settings-icon { 27 | font-family: tabler-icons; 28 | font-weight: normal; 29 | font-size: 24px; 30 | color: @font; 31 | } 32 | -------------------------------------------------------------------------------- /.config/fabric/css/color.css: -------------------------------------------------------------------------------- 1 | @import url("dark.css"); 2 | -------------------------------------------------------------------------------- /.config/fabric/css/dark.css: -------------------------------------------------------------------------------- 1 | @import url("neutral.css"); 2 | 3 | @define-color background @neutral-900; 4 | @define-color background-secondary @neutral-600; 5 | @define-color background-tertiary @neutral-700; 6 | @define-color background-alternate @neutral-900; 7 | 8 | @define-color font @neutral-50; 9 | @define-color font-secondary @neutral-400; 10 | -------------------------------------------------------------------------------- /.config/fabric/css/extra.css: -------------------------------------------------------------------------------- 1 | menu { 2 | border: solid 2px; 3 | border-color: alpha(@background, 0.2); 4 | border-radius: 10px; 5 | color: @font; 6 | } 7 | 8 | menu > menuitem { 9 | background-color: @background-secondary; 10 | padding: 6px; 11 | margin-left: 2px; 12 | margin-right: 2px; 13 | } 14 | 15 | menu > menuitem:first-child { 16 | margin-top: 1.5px; 17 | border-radius: 8px 8px 0px 0px; 18 | } 19 | 20 | menu > menuitem:last-child { 21 | margin-bottom: 1.5px; 22 | border-radius: 0px 0px 8px 8px; 23 | } 24 | 25 | menu > menuitem:hover { 26 | background-color: @background-tertiary; 27 | } 28 | 29 | tooltip { 30 | border: 2px solid alpha(@background, 0.2); 31 | border-radius: 10px; 32 | background-color: @background-secondary; 33 | color: @font; 34 | } 35 | -------------------------------------------------------------------------------- /.config/fabric/css/light.css: -------------------------------------------------------------------------------- 1 | @import url("neutral.css"); 2 | 3 | @define-color background @neutral-50; 4 | @define-color background-secondary @neutral-100; 5 | @define-color background-tertiary @neutral-200; 6 | @define-color background-alternate @neutral-300; 7 | 8 | @define-color font @neutral-800; 9 | @define-color font-secondary @neutral-500; 10 | -------------------------------------------------------------------------------- /.config/fabric/css/main.css: -------------------------------------------------------------------------------- 1 | @import url("_bar.css"); 2 | @import url("_launcher.css"); 3 | @import url("color.css"); 4 | @import url("_screencorners.css"); 5 | @import url("_sideleft.css"); 6 | @import url("_sideright.css"); 7 | @import url("extra.css"); 8 | @import url("_notifications.css"); 9 | 10 | * { 11 | all: unset; 12 | font-family: "Segoe UI", "Roboto", "Helvetica Neue", "Arial", "Noto Sans", 13 | sans-serif; 14 | } 15 | -------------------------------------------------------------------------------- /.config/fabric/css/neutral.css: -------------------------------------------------------------------------------- 1 | @define-color neutral-50 #fafafa; 2 | @define-color neutral-100 #f5f5f5; 3 | @define-color neutral-200 #e5e5e5; 4 | @define-color neutral-300 #d4d4d4; 5 | @define-color neutral-400 #a3a3a3; 6 | @define-color neutral-500 #737373; 7 | @define-color neutral-600 #525252; 8 | @define-color neutral-700 #404040; 9 | @define-color neutral-800 #262626; 10 | @define-color neutral-900 #171717; 11 | @define-color neutral-950 #0a0a0a; -------------------------------------------------------------------------------- /.config/fabric/icons.py: -------------------------------------------------------------------------------- 1 | # from tablericons 2 | 3 | 4 | class icons: 5 | cpu: str = "" 6 | ram: str = "" 7 | storage: str = "" 8 | temperature: str = "" 9 | 10 | backward: str = "" 11 | forward: str = "" 12 | stop: str = "" 13 | play: str = "" 14 | pause: str = "" 15 | 16 | wifi_on: str = "" 17 | wifi_off: str = "" 18 | bluetooth_on: str = "" 19 | bluetooth_off: str = "" 20 | dnd_on: str = "" 21 | dnd_off: str = "" 22 | 23 | moon: str = "" 24 | sun: str = "" 25 | -------------------------------------------------------------------------------- /.config/fabric/imports.py: -------------------------------------------------------------------------------- 1 | from fabric import Application 2 | from fabric.core.fabricator import Fabricator 3 | from fabric.hyprland.service import Hyprland 4 | from fabric.notifications import Notification, Notifications 5 | from fabric.system_tray.widgets import SystemTray 6 | from fabric.utils import ( 7 | DesktopApp, 8 | bulk_connect, 9 | exec_shell_command, 10 | exec_shell_command_async, 11 | get_desktop_applications, 12 | get_relative_path, 13 | idle_add, 14 | invoke_repeater, 15 | monitor_file, 16 | remove_handler, 17 | set_stylesheet_from_file, 18 | ) 19 | from fabric.widgets.box import Box 20 | from fabric.widgets.button import Button 21 | from fabric.widgets.centerbox import CenterBox 22 | from fabric.widgets.circularprogressbar import CircularProgressBar 23 | from fabric.widgets.datetime import DateTime 24 | from fabric.widgets.entry import Entry 25 | from fabric.widgets.eventbox import EventBox 26 | from fabric.widgets.image import Image 27 | from fabric.widgets.label import Label 28 | from fabric.widgets.overlay import Overlay 29 | from fabric.widgets.revealer import Revealer 30 | from fabric.widgets.scale import Scale, ScaleMark 31 | from fabric.widgets.scrolledwindow import ScrolledWindow 32 | from fabric.widgets.shapes import Corner 33 | from fabric.widgets.svg import Svg 34 | from fabric.widgets.wayland import WaylandWindow 35 | -------------------------------------------------------------------------------- /.config/fabric/main.py: -------------------------------------------------------------------------------- 1 | import dotenv 2 | 3 | from imports import * 4 | from widgets.osd.notifications import notifcationPopup 5 | from widgets.bar.main import statusBar 6 | from widgets.launcher.main import Launcher 7 | from widgets.screencorners.main import leftCorners, rightCorners 8 | from widgets.sideleft.main import sideLeft 9 | from widgets.sideright.main import sideRight 10 | 11 | dotenv.load_dotenv() 12 | 13 | 14 | def check_css(*args): 15 | return set_stylesheet_from_file("./css/main.css") 16 | 17 | 18 | if __name__ == "__main__": 19 | monitor = monitor_file(get_relative_path("./css/color.css"), "none") 20 | monitor.connect("changed", check_css) 21 | 22 | notifications = notifcationPopup() 23 | 24 | bar = statusBar() 25 | corners = leftCorners(), rightCorners() 26 | launcher = Launcher() 27 | sideLeft = sideLeft() 28 | sideRight = sideRight() 29 | 30 | # Hide initially 31 | 32 | launcher.hide() 33 | sideLeft.hide() 34 | sideRight.hide() 35 | 36 | app = Application() 37 | 38 | app.set_stylesheet_from_file("css/main.css") 39 | app.run() 40 | -------------------------------------------------------------------------------- /.config/fabric/pyrightconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "venvPath": ".", 3 | "venv": ".venv" 4 | } 5 | -------------------------------------------------------------------------------- /.config/fabric/readme.md: -------------------------------------------------------------------------------- 1 | # Notice 2 | 3 | Due to being left stale the code may have lots of bugs and errors which will not be fixed by me. It is also not fully complete. 4 | Feel free to copy, modify or use this config! 5 | 6 | ## Hyprland 7 | 8 | Add these layer rules to your hyprland config. 9 | 10 | ``` 11 | layerrule = blur, bar 12 | layerrule = ignorealpha 0.4, bar 13 | 14 | layerrule = blur, side-left 15 | layerrule = ignorealpha 0.4, side-left 16 | layerrule = animation slide, side-left 17 | 18 | layerrule = blur, side-right 19 | layerrule = ignorealpha 0.4, side-right 20 | layerrule = animation slide, side-right 21 | 22 | 23 | layerrule = blur, launcher 24 | layerrule = ignorealpha 0.4, launcher 25 | #layerrule = animation popin, launcher 26 | 27 | layerrule = blur, floating-player 28 | layerrule = ignorealpha 0.4, floating-player 29 | 30 | layerrule = blur, notifications 31 | layerrule = ignorealpha 0.4, notifications 32 | ``` 33 | 34 | To setup shortcuts, you will need fabric-cli 35 | 36 | ``` 37 | bind = Super, Space, exec, fabric-cli execute default "launcher.toggle()" 38 | bind = Super, B, exec, fabric-cli execute default "sideLeft.toggle()" 39 | bind = Super, N, exec, fabric-cli execute default "sideRight.toggle()" 40 | ``` 41 | 42 | To start the bar, I recommend using a virtual environment for packages, I also suggest putting the fabric config into .config/fabric 43 | 44 | ``` 45 | exec-once = cd ~/.config/fabric && .venv/bin/python main.py 46 | ``` 47 | 48 | ## Customize 49 | 50 | - Add your own profile picture by changing the asset in `assets/profile.png`. 51 | 52 | - Change the logo by adding an SVG in `assets` and then updating `widgets/bar/_logo.py` line 5. I recommend using icons from [simpleicons](https://simpleicons.org/). 53 | 54 | ## Mode 55 | 56 | Change `css/color.css` to use light/dark, no need to restart fabric as the changes are applied automatically. 57 | 58 | ``` 59 | @import url("./colors/.css"); 60 | ``` 61 | 62 | ## Requirements 63 | 64 | - [fabric](https://github.com/Fabric-Development/fabric) 65 | - [fabric-cli](https://github.com/Fabric-Development/fabric-cli) 66 | - psutil 67 | - wofi 68 | - playerctl 69 | 70 | #### Optional 71 | 72 | - watchfiles 73 | 74 | ## Environment 75 | 76 | In an .env file configs for weather widget are needed, uses https://www.weatherapi.com/. Put into root dir 77 | 78 | ``` 79 | FABRIC_WEATHER_KEY=*********** 80 | FABRIC_WEATHER_LOC=london 81 | ``` 82 | 83 | To install python libraries I recommend using a .venv 84 | 85 | ```py 86 | # with uv 87 | uv venv 88 | # then activate .venv 89 | uv pip install -r requirements.txt 90 | ``` 91 | 92 | ```py 93 | # with pip 94 | python3 -m venv .venv 95 | # then activate .venv 96 | pip install -r requirements.txt 97 | ``` 98 | 99 | 100 | ## Run 101 | 102 | ```sh 103 | python3 main.py 104 | ``` 105 | 106 | or 107 | 108 | ```sh 109 | watchfiles "python3 main.py" . 110 | ``` 111 | 112 | ## Features 113 | 114 | - Bar 115 | - Notifications 116 | - Side panels 117 | - Side menus 118 | - App launcher 119 | - Screen corners 120 | 121 | ## Todo 122 | 123 | - [x] Dark mode 124 | - [x] Icons (maybe use icons from icon browser and then like in launcher) 125 | - [ ] Left side 126 | - [x] Media player 127 | - [x] System info 128 | - [x] Weather 129 | - [ ] Volume 130 | - [ ] Right side 131 | - [ ] Quick settings? 132 | - [ ] Wifi 133 | - [ ] Bluetooth 134 | - [ ] Mode (dark/light) 135 | - [ ] Dnd 136 | - [ ] Calender? 137 | - [ ] Brightness 138 | - [ ] Notifications center 139 | - [ ] App launcher 140 | - [ ] Sections (Commands, Applications) 141 | - [ ] Commands 142 | - [ ] Action Area 143 | - [ ] Fuzzy search (thefuzz pypi) 144 | - [ ] Fix hover 145 | - [x] Notifications 146 | - [ ] Volume indicator 147 | - [ ] Brightness indicator 148 | - [ ] Dynamic notch? 149 | - [x] Update to rewrite 150 | - [x] Fix issues 151 | - [ ] Improve css naming conventions 152 | - [ ] Keybinds cheat sheet? 153 | - [ ] Bar 154 | - [ ] Globe functionality 155 | - [ ] Fix opening fabricast 156 | - [ ] Logging with loguru? 157 | 158 | #### Help 159 | 160 | Are you really stuck? While I probably won't check everyday, if you are facing a problem open an issue, I might help you! 161 | -------------------------------------------------------------------------------- /.config/fabric/requirements.txt: -------------------------------------------------------------------------------- 1 | psutil 2 | git+https://github.com/Fabric-Development/fabric 3 | python-dotenv 4 | -------------------------------------------------------------------------------- /.config/fabric/widgets/bar/_batteryindicator.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | import psutil 4 | 5 | from imports import * 6 | 7 | indicator = Button(name="indicator", style="background-color: #808080;") 8 | 9 | 10 | class batteryPanel(Box): 11 | def __init__(self, **kwargs): 12 | super().__init__(**kwargs) 13 | 14 | self.batteryInfo = Fabricator( 15 | poll_from=lambda f: { 16 | "battery": int( 17 | psutil.sensors_battery().percent 18 | if psutil.sensors_battery() is not None 19 | else 0 20 | ), 21 | "secsleft": int( 22 | psutil.sensors_battery().secsleft 23 | if psutil.sensors_battery() is not None 24 | else 0 25 | ), 26 | "charging": bool( 27 | psutil.sensors_battery().power_plugged 28 | if psutil.sensors_battery() is not None 29 | else False 30 | ), 31 | }, 32 | interval=1000, 33 | ) 34 | 35 | self.status = Label(label="0", name="right-battery-details") 36 | self.battery = Box(children=self.status, name="right-battery") 37 | self.indicator = indicator 38 | 39 | self.revealer = Revealer( 40 | transition_type="slide-right", transition_duration=1000 41 | ) 42 | self.revealer.add(self.battery) 43 | 44 | bulk_connect( 45 | self.indicator, 46 | { 47 | "enter-notify-event": lambda *args: self.indicator.set_cursor( 48 | "pointer" 49 | ), 50 | "leave-notify-event": lambda *args: self.indicator.set_cursor( 51 | "default" 52 | ), 53 | "button-press-event": lambda *args: self.revealer.set_reveal_child( 54 | not self.revealer.get_reveal_child() 55 | ), 56 | }, 57 | ) 58 | 59 | def indicator_color(battery: int, charging: bool) -> str: 60 | if not charging: 61 | if 80 <= battery <= 100: 62 | return "#0EC463" 63 | elif 50 <= battery <= 80: 64 | return "#FFA07A" 65 | elif 20 <= battery <= 50: 66 | return "#EEBB03" 67 | elif 1 <= battery <= 20: 68 | return "#E63946" 69 | return "#9370DB" 70 | 71 | self.batteryInfo.connect( 72 | "changed", 73 | lambda _, value: ( 74 | self.status.set_label( 75 | f"{value['battery']}% ~ {('Charging' if value['charging'] is True else str(datetime.timedelta(seconds=value['secsleft'])))}" 76 | ), 77 | self.indicator.set_style( 78 | f"background-color: {indicator_color(value["battery"], value['charging'])}" 79 | ), 80 | ), 81 | ) 82 | 83 | self.children = self.revealer 84 | -------------------------------------------------------------------------------- /.config/fabric/widgets/bar/_datetime.py: -------------------------------------------------------------------------------- 1 | from imports import * 2 | 3 | datetime = DateTime( 4 | formatters=["%-I:%M %p %b %-d", "%-I:%M:%S %p %b %-d", "%a %-d %Y"], 5 | name="datetime", 6 | ) 7 | -------------------------------------------------------------------------------- /.config/fabric/widgets/bar/_globe.py: -------------------------------------------------------------------------------- 1 | from imports import * 2 | 3 | globe = Button(name="globe", label="🌍") 4 | -------------------------------------------------------------------------------- /.config/fabric/widgets/bar/_logo.py: -------------------------------------------------------------------------------- 1 | from imports import * 2 | 3 | logo = Button( 4 | name="logo", 5 | child=Svg( 6 | size=20, 7 | svg_file=get_relative_path("../../assets/fabric-symbolic.svg"), 8 | style="fill: #3D9A6F;", 9 | ), 10 | ) 11 | -------------------------------------------------------------------------------- /.config/fabric/widgets/bar/_minimap.py: -------------------------------------------------------------------------------- 1 | import json 2 | import time 3 | 4 | from imports import * 5 | 6 | connection = Hyprland() 7 | 8 | workspaceData = connection.send_command("j/activeworkspace").reply 9 | activeWorkspace = json.loads(workspaceData.decode("utf-8"))["name"] 10 | 11 | 12 | # Scroll event credits to gummybearalbum in fabric discord 13 | 14 | 15 | def on_scroll(widget, event): 16 | if event.delta_x != 0: 17 | on_scroll.scroll_value += event.delta_x 18 | if on_scroll.scroll_value >= 5 * on_scroll.multiple: 19 | on_scroll.multiple += 1 20 | connection.send_command(f"/dispatch workspace e+1") 21 | if on_scroll.scroll_value <= -5 * on_scroll.multiple: 22 | on_scroll.multiple += 1 23 | connection.send_command(f"/dispatch workspace e-1") 24 | else: 25 | on_scroll.multiple = 1 26 | on_scroll.scroll_value = 0 27 | 28 | 29 | on_scroll.multiple = 1 30 | on_scroll.scroll_value = 0 31 | 32 | 33 | scrollBox = Box(name="center-minimap") 34 | minimap = EventBox(events="smooth-scroll", child=scrollBox) 35 | 36 | minimap.connect("scroll-event", on_scroll) 37 | -------------------------------------------------------------------------------- /.config/fabric/widgets/bar/_profile.py: -------------------------------------------------------------------------------- 1 | from imports import * 2 | 3 | profile = Button(name="center-profile", size=20) 4 | -------------------------------------------------------------------------------- /.config/fabric/widgets/bar/_tray.py: -------------------------------------------------------------------------------- 1 | from imports import * 2 | 3 | from ._profile import profile 4 | 5 | 6 | class trayPanel(Box): 7 | def __init__(self, **kwargs): 8 | super().__init__(**kwargs) 9 | 10 | self.tray = Box( 11 | children=SystemTray(name="left-tray-details", icon_size=20), 12 | name="left-tray", 13 | ) 14 | self.profile = profile 15 | 16 | self.revealer = Revealer(transition_type="slide-left", transition_duration=1000) 17 | self.revealer.add(self.tray) 18 | 19 | bulk_connect( 20 | self.profile, 21 | { 22 | "enter-notify-event": lambda *args: self.profile.set_cursor("pointer"), 23 | "leave-notify-event": lambda *args: self.profile.set_cursor("default"), 24 | "button-press-event": lambda *args: self.revealer.set_reveal_child( 25 | not self.revealer.get_reveal_child() 26 | ), 27 | }, 28 | ) 29 | 30 | self.add(self.revealer) 31 | -------------------------------------------------------------------------------- /.config/fabric/widgets/bar/_workspace.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from imports import * 4 | 5 | connection = Hyprland() 6 | 7 | workspaceData = connection.send_command("j/activeworkspace").reply 8 | activeWorkspace = json.loads(workspaceData.decode("utf-8"))["name"] 9 | workspace = Label(label=f"Workspace {activeWorkspace}", name="center-workspace") 10 | 11 | 12 | def on_workspace(obj, signal): 13 | global activeWorkspace 14 | activeWorkspace = json.loads(signal.data[0]) 15 | workspace.set_label(f"Workspace {activeWorkspace}") 16 | 17 | 18 | connection.connect("event::workspace", on_workspace) 19 | -------------------------------------------------------------------------------- /.config/fabric/widgets/bar/center.py: -------------------------------------------------------------------------------- 1 | from imports import * 2 | 3 | from ._batteryindicator import indicator 4 | from ._datetime import datetime 5 | from ._globe import globe 6 | from ._logo import logo 7 | from ._minimap import minimap 8 | from ._profile import profile 9 | from ._workspace import workspace 10 | 11 | 12 | class center(Box): 13 | def __init__(self, **kwargs) -> None: 14 | super().__init__( 15 | name="center", 16 | children=[ 17 | Box(name="pwcontainer", children=[profile, workspace]), 18 | globe, 19 | Box(name="tlcontainer", children=[datetime, indicator]), 20 | logo, 21 | minimap, 22 | ], 23 | ) 24 | 25 | for connector in [logo]: # globe 26 | bulk_connect( 27 | connector, 28 | { 29 | "enter-notify-event": lambda *args: self.set_cursor("pointer"), 30 | "leave-notify-event": lambda *args: self.set_cursor("default"), 31 | "button-press-event": self.on_button_press, 32 | }, 33 | ) 34 | 35 | def on_button_press( 36 | self, button: Button, event 37 | ): # https://docs.gtk.org/gdk3/enum.EventType.html 38 | if event.button == 1 and event.type == 4: # Single Click 39 | if button.get_name() == "center-logo": 40 | exec_shell_command("wofi --show drun --fork") 41 | # switch it to fabricast 42 | -------------------------------------------------------------------------------- /.config/fabric/widgets/bar/main.py: -------------------------------------------------------------------------------- 1 | from imports import * 2 | 3 | from ._batteryindicator import batteryPanel 4 | from ._tray import trayPanel 5 | from .center import center 6 | 7 | 8 | class statusBar(WaylandWindow): 9 | def __init__(self, **kwargs): 10 | super().__init__( 11 | title="bar", 12 | layer="top", 13 | anchor="bottom", 14 | margin="0px 0px 5px 0px", 15 | exclusivity="auto", 16 | **kwargs 17 | ) 18 | 19 | self.main = CenterBox(name="bar") 20 | self.center = center() 21 | 22 | self.right = batteryPanel() 23 | self.left = trayPanel() 24 | 25 | self.main.add_start(self.left) 26 | self.main.add_center(self.center) 27 | self.main.add_end(self.right) 28 | 29 | self.add(self.main) 30 | -------------------------------------------------------------------------------- /.config/fabric/widgets/launcher/_windows.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.config/fabric/widgets/launcher/_windows.py -------------------------------------------------------------------------------- /.config/fabric/widgets/launcher/main.py: -------------------------------------------------------------------------------- 1 | import operator 2 | from collections.abc import Iterator 3 | from imports import * 4 | 5 | 6 | class Launcher(WaylandWindow): 7 | def __init__(self): 8 | super().__init__( 9 | title="launcher", 10 | name="launcher", 11 | layer="top", 12 | anchor="center", 13 | exclusivity="none", 14 | keyboard_mode="on-demand", 15 | visible=False, 16 | all_visible=False, 17 | ) 18 | self._arranger_handler: int = 0 19 | self._all_apps = get_desktop_applications() 20 | 21 | self.viewport = Box(orientation="v") 22 | 23 | self.search = Entry( 24 | placeholder="Search for apps...", 25 | h_expand=True, 26 | notify_text=lambda entry, *_: self.arrange_viewport(entry.get_text()), 27 | on_button_press_event=print, 28 | name="launcher-search", 29 | ) 30 | self.apps = ScrolledWindow( 31 | min_content_size=(600, 320), # 2nd number is height 32 | max_content_size=(280 * 2, 320), 33 | child=self.viewport, 34 | name="launcher-apps", 35 | ) 36 | self.action_area = Box(name="launcher-area") 37 | # add center boxes for action stufs check _file.py for stuf like calculator etc 38 | # add sections like raycast? so apps, suggestions etc 39 | # also add the smart thingy for calculations etc 40 | # self.smart_feature_thing # a box that appears between apps and search (like raycast) 41 | self.details_label = Label(label="Fabricast", name="launcher-details-label") 42 | self.details_image = ( 43 | Image( 44 | icon_name="edit-undo-symbolic", 45 | name="launcher-details-icon", 46 | ) 47 | .build() 48 | .set_pixel_size(8) 49 | .unwrap() 50 | ) # Icon size fix 51 | self.details = CenterBox( 52 | name="launcher-details", 53 | start_children=[ 54 | Svg( 55 | size=16, 56 | svg_file=get_relative_path("../../assets/fabric-symbolic.svg"), 57 | style="fill: #3D9A6F;", 58 | ) 59 | ], 60 | end_children=[ 61 | Button(child=Box(children=[self.details_label, self.details_image])) 62 | ], 63 | ) 64 | 65 | self.add( 66 | Box( 67 | orientation="v", 68 | children=[self.search, self.action_area, self.apps, self.details], 69 | ) 70 | ) 71 | self.show_all() 72 | 73 | self.search.connect("key-release-event", self.on_key) 74 | 75 | def on_key(self, entry, event_key): 76 | if event_key.get_keycode()[1] == 9: # Esc to exit 77 | self.toggle() 78 | 79 | def arrange_viewport(self, query: str = ""): 80 | remove_handler(self._arranger_handler) if self._arranger_handler else None 81 | 82 | self.viewport.children = [] 83 | # self.viewport.add( Label(label="Applications", v_expand=True, v_align="start")) # title thingy, fix and stlye corrctly and other stuff if i want to keep this 84 | 85 | filtered_apps_iter = iter( 86 | [ 87 | app 88 | for app in self._all_apps 89 | if query.casefold() 90 | in ( 91 | (app.display_name or "") 92 | + (" " + app.name + " ") 93 | + (app.generic_name or "") 94 | ).casefold() 95 | ] 96 | ) 97 | """ 98 | print( 99 | len( 100 | [ 101 | app 102 | for app in self._all_apps 103 | if query.casefold() 104 | in ( 105 | (app.display_name or "") 106 | + (" " + app.name + " ") 107 | + (app.generic_name or "") 108 | ).casefold() 109 | ] 110 | ) 111 | ) 112 | """ 113 | should_resize = operator.length_hint(filtered_apps_iter) == len(self._all_apps) 114 | 115 | self._arranger_handler = idle_add( 116 | lambda *args: self.add_next_application(*args) 117 | or (self.resize_viewport() if should_resize else False), 118 | filtered_apps_iter, 119 | pin=True, 120 | ) 121 | 122 | return False 123 | 124 | def add_next_application(self, apps_iter: Iterator[DesktopApp]): 125 | if not (app := next(apps_iter, None)): 126 | return False 127 | 128 | self.viewport.add(self.bake_application_slot(app)) 129 | return True 130 | 131 | def resize_viewport(self): 132 | self.apps.set_min_content_width( 133 | self.viewport.get_allocation().width # type: ignore 134 | ) 135 | return False 136 | 137 | def bake_application_slot(self, app: DesktopApp, **kwargs) -> Button: 138 | return Button( 139 | name="launcher-app", 140 | child=Box( 141 | orientation="h", 142 | children=[ 143 | Image( 144 | pixbuf=app.get_icon_pixbuf(size=24), 145 | h_align="start", 146 | name="launcher-app-icon", 147 | ), 148 | Label( 149 | label=app.display_name or "Unknown", 150 | v_align="center", 151 | h_align="center", 152 | ), 153 | Box(h_expand=True), 154 | Label( 155 | label="Application", 156 | tooltip_text=app.description, 157 | name="launcher-app-label", 158 | ), 159 | ], 160 | ), 161 | on_focus_in_event=lambda *_: ( 162 | self.details_label.set_label("Open Application") 163 | ), 164 | # on_enter_notify_event=lambda *_: ( 165 | # self.details_label.set_label("Open Application"), 166 | # self.set_cursor("pointer"), 167 | # ), # fix so that and css hover work 168 | on_clicked=lambda *_: ( 169 | self.launch_app(app), # use while dev # app.launch() 170 | self.hide(), 171 | ), 172 | **kwargs, 173 | ) 174 | 175 | # Temp keep 176 | def launch_app(self, app: DesktopApp): 177 | command = ( 178 | " ".join([arg for arg in app.command_line.split() if "%" not in arg]) 179 | if app.command_line 180 | else None 181 | ) 182 | ( 183 | exec_shell_command_async( 184 | f"hyprctl dispatch exec -- {command}", 185 | lambda *_: print(f"Launched {app.name}"), 186 | ) 187 | if command 188 | else None 189 | ) 190 | 191 | def toggle(self): 192 | self._all_apps = get_desktop_applications() 193 | self.search.set_text("") 194 | self.search.grab_focus() 195 | self.set_visible(not self.is_visible()) 196 | -------------------------------------------------------------------------------- /.config/fabric/widgets/launcher/test.py: -------------------------------------------------------------------------------- 1 | import operator 2 | from collections.abc import Iterator 3 | 4 | from fabric import Application 5 | from fabric.utils import ( 6 | DesktopApp, 7 | get_desktop_applications, 8 | get_relative_path, 9 | idle_add, 10 | remove_handler, 11 | ) 12 | from fabric.widgets.box import Box 13 | from fabric.widgets.button import Button 14 | from fabric.widgets.entry import Entry 15 | from fabric.widgets.image import Image 16 | from fabric.widgets.label import Label 17 | from fabric.widgets.scrolledwindow import ScrolledWindow 18 | from fabric.widgets.wayland import WaylandWindow 19 | 20 | 21 | class Launcher(WaylandWindow): 22 | def __init__(self, **kwargs): 23 | super().__init__( 24 | title="launcher", 25 | layer="top", 26 | anchor="center", 27 | keyboard_mode="on-demand", 28 | # visible=False, 29 | **kwargs, 30 | ) 31 | self._desktop_apps = get_desktop_applications() 32 | 33 | self.viewport = Box(orientation="v") 34 | 35 | self.search = Entry( 36 | placeholder="Search for apps...", 37 | h_expand=True, 38 | name="search", 39 | notify_text=lambda entry, *_: self.arrange_viewport(entry.get_text()), 40 | on_button_press_event=print, 41 | ) 42 | 43 | # self.smart_feature_thing # a box that appears between apps and search (like raycast) 44 | 45 | self.apps = ScrolledWindow( 46 | child=self.viewport, 47 | ) 48 | 49 | self.add(self.search) 50 | self.add(self.apps) 51 | 52 | def arrange_viewport(self, query: str = ""): 53 | remove_handler(self._arranger_handler) if self._arranger_handler else None 54 | 55 | self.viewport.children = [] 56 | 57 | filtered_apps_iter = iter( 58 | [ 59 | app 60 | for app in self._all_apps 61 | if query.casefold() 62 | in ( 63 | (app.display_name or "") 64 | + (" " + app.name + " ") 65 | + (app.generic_name or "") 66 | ).casefold() 67 | ] 68 | ) 69 | should_resize = operator.length_hint(filtered_apps_iter) == len(self._all_apps) 70 | 71 | self._arranger_handler = idle_add( 72 | lambda *args: self.add_next_application(*args) 73 | or (self.resize_viewport() if should_resize else False), 74 | filtered_apps_iter, 75 | pin=True, 76 | ) 77 | 78 | return False 79 | 80 | def add_next_application(self, apps_iter: Iterator[DesktopApp]): 81 | if not (app := next(apps_iter, None)): 82 | return False 83 | 84 | self.viewport.add(self.bake_application_slot(app)) 85 | return True 86 | 87 | def resize_viewport(self): 88 | self.scrolled_window.set_min_content_width( 89 | self.viewport.get_allocation().width # type: ignore 90 | ) 91 | return False 92 | 93 | def bake_application_slot(self, app: DesktopApp, **kwargs) -> Button: 94 | return Button( 95 | child=Box( 96 | orientation="h", 97 | children=[ 98 | Image(pixbuf=app.get_icon_pixbuf(), h_align="start"), 99 | Label( 100 | label=app.display_name or "Unknown", 101 | v_align="center", 102 | h_align="center", 103 | ), 104 | ], 105 | ), 106 | tooltip_text=app.description, 107 | on_clicked=lambda *_: (app.launch(), self.application.quit()), 108 | **kwargs, 109 | ) 110 | 111 | 112 | if __name__ == "__main__": 113 | launcher = Launcher() 114 | app = Application("launcher", launcher) 115 | app.set_stylesheet_from_file(get_relative_path("_launcher.css")) 116 | app.run() 117 | -------------------------------------------------------------------------------- /.config/fabric/widgets/osd/notifications.py: -------------------------------------------------------------------------------- 1 | from typing import cast 2 | from gi.repository import GdkPixbuf 3 | 4 | from imports import * 5 | 6 | NOTIFICATION_WIDTH = 360 7 | NOTIFICATION_IMAGE_SIZE = 64 8 | NOTIFICATION_TIMEOUT = 10 * 1000 # 10 seconds 9 | 10 | 11 | class notificationWidget(Box): 12 | def __init__(self, notification: Notification, **kwargs): 13 | super().__init__( 14 | size=(NOTIFICATION_WIDTH, -1), 15 | name="notification", 16 | spacing=8, 17 | orientation="v", 18 | **kwargs, 19 | ) 20 | 21 | self._notification = notification 22 | 23 | body_container = Box(spacing=4, orientation="h") 24 | 25 | if image_pixbuf := self._notification.image_pixbuf: 26 | body_container.add( 27 | Image( 28 | pixbuf=image_pixbuf.scale_simple( 29 | NOTIFICATION_IMAGE_SIZE, 30 | NOTIFICATION_IMAGE_SIZE, 31 | GdkPixbuf.InterpType.BILINEAR, 32 | ) 33 | ) 34 | ) 35 | 36 | body_container.add( 37 | Box( 38 | # spacing=4, 39 | orientation="v", 40 | children=[ 41 | Box( 42 | orientation="h", 43 | children=[ 44 | Label( 45 | label=self._notification.summary, 46 | ellipsization="middle", 47 | ) 48 | .build() 49 | .add_style_class("summary") 50 | .unwrap(), 51 | ], 52 | h_expand=True, 53 | v_expand=True, 54 | ).build( 55 | lambda box, _: box.pack_end( 56 | Button( 57 | name="notification-close", 58 | image=Image( 59 | icon_name="window-close", 60 | icon_size=16, 61 | ), 62 | v_align="center", 63 | h_align="end", 64 | on_clicked=lambda *_: self._notification.close(), 65 | on_enter_notify_event=lambda *_: ( 66 | self.set_cursor("pointer"), 67 | ), 68 | ), 69 | False, 70 | False, 71 | 0, 72 | ) 73 | ), 74 | Label( 75 | label=self._notification.body, 76 | line_wrap="word-char", 77 | v_align="start", 78 | h_align="start", 79 | ellipsization="end", 80 | ) 81 | .build() 82 | .add_style_class("body") 83 | .unwrap(), 84 | ], 85 | h_expand=True, 86 | v_expand=True, 87 | ) 88 | ) 89 | 90 | self.add(body_container) 91 | 92 | if actions := self._notification.actions: 93 | self.add( 94 | Box( 95 | spacing=4, 96 | orientation="h", 97 | children=[ 98 | Button( 99 | name="notification-button", 100 | h_expand=True, 101 | v_expand=True, 102 | label=action.label, 103 | on_clicked=lambda *_, action=action: action.invoke(), 104 | on_enter_notify_event=lambda *_: ( 105 | self.set_cursor("pointer"), 106 | ), 107 | ) 108 | for action in actions 109 | ], 110 | ) 111 | ) 112 | 113 | self._notification.connect( 114 | "closed", 115 | lambda *_: ( 116 | parent.remove(self) if (parent := self.get_parent()) else None, # type: ignore 117 | self.destroy(), 118 | ), 119 | ) 120 | 121 | invoke_repeater( 122 | NOTIFICATION_TIMEOUT, 123 | lambda: self._notification.close("expired"), 124 | initial_call=False, 125 | ) 126 | 127 | 128 | class notifcationPopup(WaylandWindow): 129 | def __init__(self): 130 | super().__init__( 131 | title="notifications", 132 | margin="4px 4px 4px 4px", 133 | anchor="top right", 134 | child=Box( 135 | size=2, 136 | spacing=4, 137 | orientation="v", 138 | ).build( 139 | lambda viewport, _: Notifications( 140 | on_notification_added=lambda notifs_service, nid: viewport.add( 141 | notificationWidget( 142 | cast( 143 | Notification, 144 | notifs_service.get_notification_from_id(nid), 145 | ) 146 | ) 147 | ) 148 | ) 149 | ), 150 | visible=True, 151 | all_visible=True, 152 | ) 153 | -------------------------------------------------------------------------------- /.config/fabric/widgets/screencorners/main.py: -------------------------------------------------------------------------------- 1 | from imports import * 2 | 3 | 4 | class leftCorners(WaylandWindow): 5 | def __init__( 6 | self, 7 | ): 8 | super().__init__( 9 | title="corners-left", 10 | layer="overlay", 11 | exclusivity="none", 12 | anchor="left top bottom", 13 | margin="0px 0px -51px 0px", 14 | ) 15 | 16 | self.right = CenterBox( 17 | orientation="v", 18 | start_children=[ 19 | Corner( 20 | orientation="top-left", 21 | size=10, 22 | name="corner-top-left", 23 | ) 24 | ], 25 | end_children=[ 26 | Corner( 27 | orientation="bottom-left", 28 | size=10, 29 | name="corner-bottom-left", 30 | ) 31 | ], 32 | ) 33 | 34 | self.add(Box(orientation="h", children=[self.right])) 35 | 36 | self.show() 37 | 38 | 39 | class rightCorners(WaylandWindow): 40 | def __init__( 41 | self, 42 | ): 43 | super().__init__( 44 | title="corners-right", 45 | layer="overlay", 46 | exclusive=False, 47 | anchor="right top bottom", 48 | margin="0px 0px -51px 0px", 49 | ) 50 | 51 | self.right = CenterBox( 52 | orientation="v", 53 | start_children=[ 54 | Corner( 55 | orientation="top-right", 56 | size=10, 57 | name="corner-top-right", 58 | ) 59 | ], 60 | end_children=[ 61 | Corner( 62 | orientation="bottom-right", 63 | size=10, 64 | name="corner-bottom-right", 65 | ) 66 | ], 67 | ) 68 | 69 | self.add(Box(orientation="h", children=[self.right])) 70 | 71 | self.show() 72 | -------------------------------------------------------------------------------- /.config/fabric/widgets/sideleft/_player.py: -------------------------------------------------------------------------------- 1 | import json 2 | import time 3 | 4 | from icons import icons 5 | from imports import * 6 | 7 | 8 | class floating(WaylandWindow): 9 | def __init__(self): 10 | super().__init__( 11 | title="floating-player", 12 | layer="overlay", 13 | visible=False, 14 | name="floating-player", 15 | anchor="bottom left", 16 | v_expand=False, 17 | h_expand=False, 18 | margin="0px 0px -47px 4px", 19 | exclusivity="none", 20 | ) 21 | 22 | self.art = Button( 23 | name="floating-art", 24 | ) 25 | 26 | self.backward = Button( 27 | child=Label( 28 | markup=icons.backward, name="left-player-icon", style="font-size: 20px;" 29 | ) 30 | ) 31 | self.forward = Button( 32 | child=Label( 33 | markup=icons.forward, name="left-player-icon", style="font-size: 20px;" 34 | ) 35 | ) 36 | self.status = Label( 37 | markup=icons.stop, name="left-player-icon", style="font-size: 28px;" 38 | ) 39 | self.play = Button(child=self.status) 40 | 41 | self.children = Overlay( 42 | child=self.art, 43 | overlays=CenterBox( 44 | v_align="center", 45 | name="floating-controls", 46 | start_children=self.backward, 47 | center_children=self.play, 48 | end_children=self.forward, 49 | ), 50 | ) 51 | 52 | self.playerInfo = Fabricator( 53 | poll_from='playerctl --follow metadata --format \'{"status": "{{status}}", "artUrl": "{{mpris:artUrl}}", "title": "{{ markup_escape(title) }}", "artist": "{{ markup_escape(artist) }}"}\'', 54 | stream=True, 55 | interval=1000, 56 | ) 57 | 58 | def extract_metadata(_, value): 59 | if value: 60 | data = json.loads(value) 61 | 62 | self.art.set_style(f"background-image: url('{data['artUrl']}');") 63 | self.status.set_markup( 64 | ( 65 | icons.stop 66 | if data["status"] == "Stopped" 67 | else ( 68 | icons.pause if data["status"] == "Playing" else icons.play 69 | ) 70 | ) 71 | ) 72 | 73 | else: 74 | self.status.set_markup(icons.stop) 75 | 76 | self.playerInfo.connect("changed", extract_metadata) 77 | 78 | for connector in [self.backward, self.play, self.forward, self.art]: 79 | bulk_connect( 80 | connector, 81 | { 82 | "enter-notify-event": lambda *args: self.set_cursor("pointer"), 83 | "leave-notify-event": lambda *args: self.set_cursor("default"), 84 | "button-press-event": self.on_button_press, 85 | }, 86 | ) 87 | 88 | def on_button_press(self, button: Button, event): 89 | if event.button == 1 and event.type == 4: 90 | if button == self.backward: 91 | exec_shell_command("playerctl previous") 92 | elif button == self.play: 93 | exec_shell_command("playerctl play-pause") 94 | elif button == self.forward: 95 | exec_shell_command("playerctl next") 96 | elif event.button == 1 and event.type == 5: 97 | if button == self.art: 98 | self.hide() 99 | 100 | def toggle(self): 101 | self.set_visible(not self.is_visible()) 102 | 103 | 104 | class player(Box): 105 | def __init__(self) -> None: 106 | super().__init__( 107 | name="left-player", 108 | h_expand=True, 109 | orientation="h", 110 | ) 111 | 112 | self.art = Button(name="left-player-art") 113 | self.title = Label( 114 | label="Nothing playing", 115 | name="left-player-title", 116 | justification="center", 117 | ellipsization="end", 118 | character_max_width=24, 119 | ) 120 | self.artist = Label( 121 | name="left-player-artist", 122 | justification="center", 123 | ellipsization="end", 124 | character_max_width=20, 125 | ) 126 | 127 | self.backward = Button( 128 | child=Label(markup=icons.backward, name="left-player-icon") 129 | ) 130 | self.forward = Button( 131 | child=Label(markup=icons.forward, name="left-player-icon") 132 | ) 133 | self.status = Label( 134 | markup=icons.stop, name="left-player-icon", style="font-size: 36px;" 135 | ) 136 | self.play = Button(child=self.status) 137 | 138 | self.controls = CenterBox( 139 | name="left-player-controls", 140 | start_children=[self.backward], 141 | center_children=[self.play], 142 | end_children=[self.forward], 143 | orientation="h", 144 | h_expand=True, 145 | ) 146 | self.info = Box( 147 | name="left-player-info", 148 | children=[self.title, self.artist, self.controls], 149 | orientation="v", 150 | v_align="center", 151 | h_expand=True, 152 | ) 153 | 154 | self.details = Box(children=[self.info], h_expand=True, v_expand=True) 155 | 156 | self.playerInfo = Fabricator( 157 | poll_from='playerctl --follow metadata --format \'{"status": "{{status}}", "artUrl": "{{mpris:artUrl}}", "title": "{{ markup_escape(title) }}", "artist": "{{ markup_escape(artist) }}"}\'', 158 | stream=True, 159 | interval=1000, 160 | ) 161 | 162 | def extract_metadata(_, value): 163 | if value: 164 | data = json.loads(value) 165 | 166 | self.art.set_style(f"background-image: url('{data['artUrl']}');") 167 | self.title.set_label(data["title"]) 168 | self.artist.set_label(data["artist"]) 169 | self.status.set_markup( 170 | ( 171 | icons.stop 172 | if data["status"] == "Stopped" 173 | else ( 174 | icons.pause if data["status"] == "Playing" else icons.play 175 | ) 176 | ) 177 | ) 178 | 179 | else: 180 | self.title.set_label("Nothing playing") 181 | self.artist.set_label("") 182 | self.status.set_markup(icons.stop) 183 | 184 | self.playerInfo.connect("changed", extract_metadata) 185 | 186 | for connector in [self.backward, self.play, self.forward, self.art]: 187 | bulk_connect( 188 | connector, 189 | { 190 | "enter-notify-event": lambda *args: self.set_cursor("pointer"), 191 | "leave-notify-event": lambda *args: self.set_cursor("default"), 192 | "button-press-event": self.on_button_press, 193 | }, 194 | ) 195 | 196 | self.add(self.art) 197 | self.add(self.details) 198 | 199 | def on_button_press(self, button: Button, event): 200 | if event.button == 1 and event.type == 4: 201 | if button == self.backward: 202 | exec_shell_command("playerctl previous") 203 | elif button == self.play: 204 | exec_shell_command("playerctl play-pause") 205 | elif button == self.forward: 206 | exec_shell_command("playerctl next") 207 | elif event.button == 1 and event.type == 5: 208 | if button == self.art: 209 | floating().toggle() # fix not toggling # always shows, might even multiple? 210 | -------------------------------------------------------------------------------- /.config/fabric/widgets/sideleft/_sysinfo.py: -------------------------------------------------------------------------------- 1 | import psutil 2 | 3 | from icons import icons 4 | from imports import * 5 | 6 | 7 | class sysinfo(Box): 8 | def __init__(self) -> None: 9 | super().__init__(name="left-sysinfo", h_expand=True, orientation="h") 10 | 11 | self.systemInfo = Fabricator( 12 | poll_from=lambda f: { 13 | "cpu": psutil.cpu_percent(), 14 | "ram": psutil.virtual_memory().percent, 15 | "storage": psutil.disk_usage("/").percent, 16 | "temp": psutil.sensors_temperatures()["nvme"][0].current, 17 | # temp here 18 | }, 19 | interval=1000, 20 | ) 21 | 22 | self.systemInfo.connect( 23 | "changed", 24 | lambda _, value: (self.update(value)), 25 | ) 26 | 27 | self.cpu_circular = CircularProgressBar( 28 | size=(64, 64), name="left-sysinfo-circular", max_value=100 29 | ) 30 | self.cpu = Box( 31 | name="left-sysinfo-box", 32 | children=[ 33 | Overlay( 34 | child=self.cpu_circular, 35 | overlays=[ 36 | Label( 37 | markup=icons.cpu, 38 | name="left-sysinfo-icon", 39 | style="margin-left: 2px;", 40 | ), 41 | ], 42 | ) 43 | ], 44 | ) 45 | 46 | self.ram_circular = CircularProgressBar( 47 | size=(64, 64), name="left-sysinfo-circular", max_value=100 48 | ) 49 | self.ram = Box( 50 | name="left-sysinfo-box", 51 | children=[ 52 | Overlay( 53 | child=self.ram_circular, 54 | overlays=[ 55 | Label( 56 | markup=icons.ram, 57 | name="left-sysinfo-icon", 58 | style="margin-left: 1px;", 59 | ), 60 | ], 61 | ) 62 | ], 63 | ) 64 | 65 | self.storage_circular = CircularProgressBar( 66 | size=(64, 64), name="left-sysinfo-circular", max_value=100 67 | ) 68 | self.storage = Box( 69 | name="left-sysinfo-box", 70 | children=[ 71 | Overlay( 72 | child=self.storage_circular, 73 | overlays=[ 74 | Label( 75 | markup=icons.storage, 76 | name="left-sysinfo-icon", 77 | ), 78 | ], 79 | ) 80 | ], 81 | ) 82 | 83 | self.temp_circular = CircularProgressBar( 84 | size=(64, 64), name="left-sysinfo-circular", max_value=100 85 | ) 86 | self.temp = Box( 87 | name="left-sysinfo-box", 88 | children=[ 89 | Overlay( 90 | child=self.temp_circular, 91 | overlays=[ 92 | Label( 93 | markup=icons.temperature, 94 | name="left-sysinfo-icon", 95 | ) 96 | ], 97 | ) 98 | ], 99 | ) 100 | 101 | self.children = CenterBox( 102 | h_expand=True, 103 | orientation="h", 104 | center_children=[self.cpu, self.ram, self.storage, self.temp], 105 | ) 106 | 107 | # cpu, ram, storage, temp, 5th thing? 108 | 109 | def update(self, value): 110 | self.cpu_circular.value = value["cpu"] 111 | self.ram_circular.value = value["ram"] 112 | self.storage_circular.value = value["storage"] 113 | self.temp_circular.value = value["temp"] 114 | -------------------------------------------------------------------------------- /.config/fabric/widgets/sideleft/_volume.py: -------------------------------------------------------------------------------- 1 | from fabric.utils import truncate 2 | from imports import * 3 | 4 | 5 | class volume(Box): 6 | def __init__(self) -> None: 7 | super().__init__(name="left-volume", h_expand=True, orientation="h") 8 | 9 | self.label = Label( 10 | label="Sound", h_align="start", v_align="start", name="volume-label" 11 | ) 12 | self.slider = Scale(orientation="v", name="volume-slider", v_expand=True) 13 | 14 | self.children = CenterBox( 15 | orientation="v", 16 | h_expand=True, 17 | start_children=self.label, 18 | center_children=self.slider, 19 | ) 20 | -------------------------------------------------------------------------------- /.config/fabric/widgets/sideleft/_weather.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | 4 | from imports import * 5 | 6 | 7 | class weather(Box): 8 | def __init__(self) -> None: 9 | super().__init__(name="left-weather", h_expand=True, orientation="h") 10 | 11 | self.weather_info = Fabricator( 12 | poll_from=f"curl -X GET 'http://api.weatherapi.com/v1/current.json?key={os.getenv('FABRIC_WEATHER_KEY')}&q={os.getenv('FABRIC_WEATHER_LOC')}&aqi=yes'", 13 | interval=1000 * 60 * 40, 14 | ) 15 | 16 | self.temperature = Label(label="0", name="weather-temperature") 17 | self.condition_text = Label( 18 | label="None", name="weather-condition", h_align="start", v_align="start" 19 | ) 20 | self.time = Label(label="Current · 00:00", name="weather-time") 21 | self.location = Label(label="None", name="weather-location") 22 | self.icon = Box( 23 | name="weather-icon", 24 | ) 25 | 26 | self.details = Box( 27 | orientation="v", 28 | v_expand=True, 29 | v_align="center", 30 | children=[self.condition_text, Box(children=[self.location, self.time])], 31 | ) 32 | 33 | def extract_metadata(_, value): 34 | data = json.loads(value) 35 | 36 | self.temperature.set_label(f"{round(int(data['current']['temp_c']))}°") 37 | self.condition_text.set_label(f"{data['current']['condition']['text']}") 38 | self.location.set_label(f"{data['location']['country']}") 39 | timestr = data["location"]["localtime"] 40 | self.time.set_label(f"Current · {timestr.split(' ', 1)[1]}") 41 | self.icon.set_style( 42 | f"background-image: url('http:{data['current']['condition']['icon']}');" 43 | ) 44 | 45 | self.weather_info.connect("changed", extract_metadata) 46 | 47 | self.children = CenterBox( 48 | h_expand=True, 49 | center_children=[self.temperature, self.details, self.icon], 50 | ) 51 | -------------------------------------------------------------------------------- /.config/fabric/widgets/sideleft/main.py: -------------------------------------------------------------------------------- 1 | from imports import * 2 | 3 | from ._player import player 4 | from ._sysinfo import sysinfo 5 | from ._volume import volume 6 | from ._weather import weather 7 | 8 | 9 | class sideLeft(WaylandWindow): 10 | def __init__( 11 | self, 12 | ): 13 | super().__init__( 14 | title="side-left", 15 | layer="top", 16 | anchor="top bottom left", 17 | margin="4px 4px 4px 4px", 18 | exclusivity="none", 19 | visible=False, 20 | name="side-left", 21 | v_expand=True, 22 | h_expand=False, 23 | ) 24 | 25 | self.main = CenterBox(name="side-left-container", size=450, orientation="v") 26 | 27 | self.player = player() 28 | self.sysinfo = sysinfo() 29 | self.weather = weather() 30 | self.volume = volume() 31 | 32 | self.main.add_start(self.player) 33 | self.main.add_start(self.sysinfo) 34 | self.main.add_start(self.weather) 35 | self.main.add_start(self.volume) 36 | 37 | self.add(self.main) 38 | 39 | def toggle(self): 40 | self.set_visible(not self.is_visible()) 41 | -------------------------------------------------------------------------------- /.config/fabric/widgets/sideright/_quicksettings.py: -------------------------------------------------------------------------------- 1 | from icons import icons 2 | from imports import * 3 | 4 | 5 | class quicksettings(Box): 6 | def __init__(self) -> None: 7 | super().__init__(name="right-quicksettings", h_expand=True, orientation="h") 8 | 9 | self.wifi_icon = Label(name="settings-icon", markup=icons.wifi_on) 10 | self.bluetooth_icon = Label(name="settings-icon", markup=icons.bluetooth_on) 11 | self.mode_icon = Label(name="settings-icon", markup=icons.moon) 12 | self.dnd_icon = Label(name="settings-icon", markup=icons.dnd_on) 13 | 14 | self.wifi = Button(name="wifi-button", child=self.wifi_icon) 15 | self.bluetooth = Button(name="bluetooth-button", child=self.bluetooth_icon) 16 | self.mode = Button(name="mode-button", child=self.mode_icon) 17 | self.dnd = Button(name="dnd-button", child=self.dnd_icon) 18 | 19 | self.children = CenterBox( 20 | name="quicksettings-container", 21 | h_expand=True, 22 | orientation="h", 23 | center_children=[self.wifi, self.bluetooth, self.mode, self.dnd], 24 | ) 25 | 26 | for connector in [self.wifi, self.bluetooth, self.mode, self.dnd]: 27 | bulk_connect( 28 | connector, 29 | { 30 | "enter-notify-event": lambda *args: self.set_cursor("pointer"), 31 | "leave-notify-event": lambda *args: self.set_cursor("default"), 32 | "button-press-event": self.on_button_press, 33 | }, 34 | ) 35 | self.set_states() 36 | 37 | def on_button_press(self, button: Button, event): 38 | if event.button == 1 and event.type == 4: 39 | if button == self.wifi: 40 | 41 | self.set_states() 42 | 43 | def set_states(self): 44 | if "Powered: yes" in exec_shell_command("bluetoothctl show"): # pyright: ignore 45 | self.bluetooth_icon.set_markup(icons.bluetooth_on) 46 | self.bluetooth.add_style_class("active") 47 | else: 48 | self.bluetooth_icon.set_markup(icons.bluetooth_off) 49 | self.bluetooth.remove_style_class("active") 50 | 51 | if "enabled" in exec_shell_command("nmcli radio wifi"): # pyright:ignore 52 | self.wifi_icon.set_markup(icons.wifi_on) 53 | self.wifi.add_style_class("active") 54 | else: 55 | self.wifi_icon.set_markup(icons.wifi_off) 56 | self.wifi.remove_style_class("active") 57 | 58 | if "dark" in exec_shell_command( 59 | "gsettings get org.gnome.desktop.interface color-scheme" 60 | ): # pyright: ignore 61 | self.mode_icon.set_markup(icons.moon) 62 | self.mode.add_style_class("active") 63 | else: 64 | self.mode_icon.set_markup(icons.sun) 65 | self.mode.add_style_class("active") 66 | -------------------------------------------------------------------------------- /.config/fabric/widgets/sideright/main.py: -------------------------------------------------------------------------------- 1 | from imports import * 2 | 3 | from ._quicksettings import quicksettings 4 | 5 | 6 | class sideRight(WaylandWindow): 7 | def __init__( 8 | self, 9 | ): 10 | super().__init__( 11 | title="side-right", 12 | layer="top", 13 | anchor="top bottom right", 14 | margin="4px 4px 4px 4px", 15 | exclusivity="none", 16 | visible=False, 17 | name="side-right", 18 | v_expand=True, 19 | h_expand=False, 20 | ) 21 | 22 | self.main = CenterBox(name="side-right-container", size=450, orientation="v") 23 | 24 | self.quicksettings = quicksettings() 25 | 26 | self.main.add_start(self.quicksettings) 27 | 28 | self.add(self.main) 29 | 30 | def toggle(self): 31 | self.set_visible(not self.is_visible()) 32 | -------------------------------------------------------------------------------- /.config/hypr/hypridle.conf: -------------------------------------------------------------------------------- 1 | $lock_cmd = pidof hyprlock || hyprlock 2 | $suspend_cmd = pidof steam || systemctl suspend || loginctl suspend 3 | 4 | general { 5 | lock_cmd = $lock_cmd 6 | before_sleep_cmd = $lock_cmd 7 | } 8 | 9 | listener { 10 | timeout = 180 # 3mins 11 | on-timeout = $lock_cmd 12 | } 13 | 14 | listener { 15 | timeout = 240 # 4mins 16 | on-timeout = hyprctl dispatch dpms off 17 | on-resume = hyprctl dispatch dpms on # 9mins 18 | } 19 | 20 | listener { 21 | timeout = 540 # 9mins 22 | on-timeout = $suspend_cmd 23 | } 24 | -------------------------------------------------------------------------------- /.config/hypr/hyprland.conf: -------------------------------------------------------------------------------- 1 | source=~/.config/hypr/hyprland/env.conf 2 | source=~/.config/hypr/hyprland/execs.conf 3 | source=~/.config/hypr/hyprland/general.conf 4 | source=~/.config/hypr/hyprland/rules.conf 5 | source=~/.config/hypr/hyprland/colors.conf 6 | # source=~/.cache/wal/colors.conf # use pywal colors if avalible 7 | source=~/.config/hypr/hyprland/keybinds.conf 8 | -------------------------------------------------------------------------------- /.config/hypr/hyprland/colors.conf: -------------------------------------------------------------------------------- 1 | general { 2 | col.active_border = 0xFF52525b 45deg 3 | col.inactive_border = 0xFF27272a 4 | } 5 | -------------------------------------------------------------------------------- /.config/hypr/hyprland/env.conf: -------------------------------------------------------------------------------- 1 | # Qt Variables 2 | 3 | env = QT_QPA_PLATFORM, wayland 4 | env = QT_AUTO_SCREEN_SCALE_FACTOR, 1 5 | env = QT_IM_MODULE, ibus 6 | 7 | # Tearing 8 | 9 | # env = WLR_DRM_NO_ATOMIC, 1 10 | 11 | # Other 12 | 13 | env = XMODIFIERS, @im=ibus 14 | env = GTK_IM_MODULE, ibus 15 | env = GDK_SCALE, 1 16 | 17 | # Cursor Fallback 18 | 19 | env = XCURSOR_THEME, Bibata-Modern-Classic 20 | env = XCURSOR_SIZE, 24 21 | -------------------------------------------------------------------------------- /.config/hypr/hyprland/execs.conf: -------------------------------------------------------------------------------- 1 | # Fabric 2 | 3 | exec-once = cd ~/.config/fabric && .venv/bin/python main.py 4 | 5 | # Clipboard history 6 | 7 | exec-once = wl-paste --type text --watch cliphist store 8 | exec-once = wl-paste --type image --watch cliphist store 9 | 10 | # Wallpaper 11 | 12 | exec-once = swww kill; swww-daemon --format xrgb 13 | 14 | # Authentication Agent 15 | 16 | exec-once = gnome-keyring-daemon --start --components=secrets 17 | exec-once = /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 || /usr/libexec/polkit-gnome-authentication-agent-1 18 | 19 | # Dbus 20 | 21 | exec-once = dbus-update-activation-environment --all 22 | exec-once = sleep 1 && dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP 23 | 24 | 25 | # Idle 26 | 27 | exec-once = hypridle 28 | 29 | # Utils 30 | 31 | exec-once = dbus-update-activation-environment --all 32 | 33 | # Clipboard history 34 | 35 | exec-once = wl-paste --type text --watch cliphist store 36 | exec-once = wl-paste --type image --watch cliphist store 37 | 38 | # Cursor 39 | 40 | exec-once = hyprctl setcursor Bibata-Modern-Classic 24 41 | exec-once = gsettings set org.gnome.desktop.interface cursor-theme 'Bibata-Modern-Classic' 42 | -------------------------------------------------------------------------------- /.config/hypr/hyprland/general.conf: -------------------------------------------------------------------------------- 1 | monitor=eDP-1,preferred,auto,1.566667 2 | monitor=DP-2,preferred,auto,auto 3 | 4 | input { 5 | kb_layout = de 6 | 7 | sensitivity = 0 8 | follow_mouse = 1 9 | 10 | touchpad { 11 | disable_while_typing = false 12 | 13 | natural_scroll = true 14 | scroll_factor = 0.5 15 | 16 | clickfinger_behavior = true 17 | tap-to-click = true 18 | tap-and-drag = false 19 | } 20 | } 21 | 22 | gestures { 23 | workspace_swipe = true 24 | workspace_swipe_fingers = 4 25 | workspace_swipe_create_new = true 26 | } 27 | 28 | general { 29 | gaps_in = 4 30 | gaps_out = 4 31 | 32 | border_size = 1 33 | # no_border_on_floating = true 34 | 35 | layout = dwindle 36 | 37 | # resize_on_border = true 38 | 39 | allow_tearing = true 40 | } 41 | 42 | decoration { 43 | rounding = 8 44 | 45 | drop_shadow = false 46 | # shadow_range = 4 47 | # shadow_render_power = 3 48 | # col.shadow = rgba(0000001A) 49 | 50 | dim_inactive = false 51 | # dim_strength = 0.1 52 | # dim_special = 0 53 | 54 | blur { 55 | enabled = true 56 | size = 14 57 | passes = 4 58 | new_optimizations = true 59 | xray = true 60 | noise = 0.01 61 | contrast = 1 62 | brightness = 1 63 | popups = true 64 | # popups_ignorealpha = 0.6 65 | } 66 | 67 | } 68 | 69 | animations { 70 | enabled = true 71 | 72 | # Curves 73 | 74 | bezier = easeInCubic, 0.4, 0, 1, 1 75 | bezier = easeOutCubic, 0, 0, 0.2, 1 76 | bezier = easeInOutCubic, 0.4, 0, 0.2, 1 77 | 78 | # Animations 79 | 80 | animation = windows, 1, 5, easeInOutCubic, popin 60% 81 | animation = windowsIn, 1, 5, easeInOutCubic, popin 20% 82 | animation = windowsOut, 1, 3, easeOutCubic, popin 60% 83 | animation = windowsMove, 1, 3, default, slide 84 | 85 | animation = layers, 1, 5, easeInOutCubic, fade 86 | animation = layersIn, 1, 3, default, fade 87 | animation = layersOut, 1, 1.6, easeOutCubic 88 | animation = fadeLayersIn, 1, 2, easeInCubic 89 | animation = fadeLayersOut, 1, 4.5, easeOutCubic 90 | 91 | animation = border, 1, 5, easeInOutCubic 92 | 93 | animation = workspaces, 1, 3, default, slidefade 15% 94 | 95 | # Snappy 96 | 97 | # https://github.com/end-4/dots-hyprland/blob/main/.config/hypr/hyprland/general.conf#L102-L136 98 | 99 | # bezier = myBezier, 0.05, 0.9, 0.1, 1.05 100 | 101 | # animation = windows, 1, 7, myBezier 102 | # animation = windowsOut, 1, 7, default, popin 80% 103 | # animation = border, 1, 10, default 104 | # animation = borderangle, 1, 8, default 105 | # animation = fade, 1, 7, default 106 | # animation = workspaces, 1, 6, default 107 | } 108 | 109 | dwindle { 110 | pseudotile = true 111 | preserve_split = true 112 | } 113 | 114 | misc { 115 | vfr = 1 116 | vrr = 1 117 | 118 | disable_hyprland_logo = true 119 | # disable_splash_rendering = true 120 | force_default_wallpaper = 0 121 | 122 | 123 | mouse_move_enables_dpms = true 124 | key_press_enables_dpms = true 125 | 126 | swallow_regex = (foot|kitty) 127 | 128 | focus_on_activate = true 129 | new_window_takes_over_fullscreen = 2 130 | 131 | allow_session_lock_restore = true 132 | 133 | initial_workspace_tracking = false 134 | } 135 | 136 | cursor { 137 | # inactive_timeout = 0 138 | # no_hardware_cursors = 1 139 | # enable_hyprcursor = true 140 | } 141 | -------------------------------------------------------------------------------- /.config/hypr/hyprland/keybinds.conf: -------------------------------------------------------------------------------- 1 | # Screen 2 | 3 | bindle =,XF86MonBrightnessUp, exec, brightnessctl set +5% 4 | bindle =,XF86MonBrightnessDown, exec, brightnessctl set 5%- 5 | 6 | # Audio 7 | 8 | bindl = ,XF86AudioMute, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 0% 9 | bindle = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+ 10 | bindle = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- 11 | bindl= ,XF86AudioPlay, exec, playerctl play-pause 12 | 13 | # Essential 14 | 15 | bind = Super, T, exec, kitty fish 16 | bind = Alt, Space, exec, pkill wofi || wofi --show drun 17 | 18 | # Fabric 19 | 20 | bind = Super, Space, exec, fabric-cli execute default "launcher.toggle()" # /home/sofa/.config/fabric/.venv/bin/python -m fabric execute default "launcher.toggle()" 21 | bind = Super, B, exec, fabric-cli execute default "sideLeft.toggle()" # /home/sofa/.config/fabric/.venv/bin/python -m fabric execute default "sideLeft.toggle()" 22 | bind = Super, N, exec, fabric-cli execute default "sideRight.toggle()" # /home/sofa/.config/fabric/.venv/bin/python -m fabric execute default "sideRight.toggle()" 23 | 24 | # Apps 25 | 26 | bind = Super, E, exec, nautilus --new-window 27 | bind = Super, I, exec, XDG_CURRENT_DESKTOP="gnome" gnome-control-center 28 | 29 | # Screenshots 30 | 31 | bind = Super+Shift,T,exec,grim -g "$(slurp $SLURP_ARGS)" "tmp.png" && tesseract -l eng "tmp.png" - | wl-copy && rm "tmp.png" # OCR - Clipboard 32 | 33 | bind= Super Shift, 1, exec, grim - | swappy -f - # Fullscreen - Edit 34 | bind = Super Shift, 2, exec, grim -g "$(slurp)" - | swappy -f - # Area - Edit 35 | bind = Super Shift, 3, exec, mkdir -p ~/Screenshots && grimblast copysave area ~/Screenshots/Screenshot_"$(date '+%Y-%m-%d_%H.%M.%S')".png # Area - Save - Clipboard 36 | 37 | 38 | bind= ,Print, exec, grim - | swappy -f - # Fullscreen - Edit 39 | bindl= Shift, Print, exec, grim - | wl-copy # Fullscreen - Clipboard 40 | bindl= Ctrl, Print, exec, mkdir -p ~/Screenshots && grimblast copysave screen ~/Screenshots/Screenshot_"$(date '+%Y-%m-%d_%H.%M.%S')".png # Fullscreen - Save - Clipboard 41 | 42 | # Utils 43 | 44 | bind = Super Shift, Space, exec, pkill wofi || cliphist list | wofi --dmenu | cliphist decode | wl-copy # Clipboard history 45 | bind = Super Shift, C, exec, hyprpicker -a # Pick color (Hex) - clipboard 46 | 47 | # Session 48 | 49 | bind = Super, L, exec, loginctl lock-session 50 | bind = Super Shift, L, exec, loginctl lock-session 51 | bindl = Super Shift, L, exec, sleep 0.1 && systemctl suspend || loginctl suspend 52 | 53 | # Window managment 54 | 55 | bind = Super, Q, killactive 56 | bind = Super, P, pseudo 57 | bind = Super, J, togglesplit 58 | bind = Super, V, togglefloating 59 | bind = Super, F, fullscreen 60 | 61 | bind = Super, left, movefocus, l 62 | bind = Super, right, movefocus, r 63 | bind = Super, up, movefocus, u 64 | bind = Super, down, movefocus, d 65 | 66 | binde = Super, Minus, splitratio, -0.1 67 | binde = Super, Plus, splitratio, 0.1 68 | 69 | bind = Super, 1, workspace, 1 70 | bind = Super, 2, workspace, 2 71 | bind = Super, 3, workspace, 3 72 | bind = Super, 4, workspace, 4 73 | bind = Super, 5, workspace, 5 74 | bind = Super, 6, workspace, 6 75 | bind = Super, 7, workspace, 7 76 | bind = Super, 8, workspace, 8 77 | bind = Super, 9, workspace, 9 78 | bind = Super, 0, workspace, 10 79 | 80 | bind = Super Control, 1, movetoworkspace, 1 81 | bind = Super Control, 2, movetoworkspace, 2 82 | bind = Super Control, 3, movetoworkspace, 3 83 | bind = Super Control, 4, movetoworkspace, 4 84 | bind = Super Control, 5, movetoworkspace, 5 85 | bind = Super Control, 6, movetoworkspace, 6 86 | bind = Super Control, 7, movetoworkspace, 7 87 | bind = Super Control, 8, movetoworkspace, 8 88 | bind = Super Control, 9, movetoworkspace, 9 89 | bind = Super Control, 0, movetoworkspace, 10 90 | 91 | bind = Super, mouse_down, workspace, e+1 92 | bind = Super, mouse_up, workspace, e-1 93 | 94 | bindm = Super, mouse:272, movewindow 95 | bindm = Super, mouse:273, resizewindow 96 | 97 | # Debug 98 | 99 | bind = Super, D, exec, hyprctl activeworkspace -j | wl-copy 100 | bind = Super Control Shift, L, exit 101 | -------------------------------------------------------------------------------- /.config/hypr/hyprland/rules.conf: -------------------------------------------------------------------------------- 1 | # Picture in Picture 2 | 3 | windowrulev2 = move 100%-26% 100%-22%, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ 4 | windowrulev2 = size 360 200, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ 5 | windowrulev2 = pin, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ 6 | windowrulev2 = float, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ 7 | #windowrulev2 = monitor 1, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ 8 | windowrulev2 = suppressevent activate, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ 9 | windowrulev2 = suppressevent maximize, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ 10 | windowrulev2 = suppressevent fullscreen, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ 11 | 12 | # Dialogs 13 | 14 | windowrule=float,title:^(Open File)(.*)$ 15 | windowrule=float,title:^(Select a File)(.*)$ 16 | windowrule=float,title:^(Choose wallpaper)(.*)$ 17 | windowrule=float,title:^(Open Folder)(.*)$ 18 | windowrule=float,title:^(Save As)(.*)$ 19 | windowrule=float,title:^(Library)(.*)$ 20 | windowrule=float,title:^(File Upload)(.*)$ 21 | 22 | windowrule=float,title:^(blob:https://)(.*)(.discord.com/)(.*)$ 23 | windowrule=float,title:^(blob:https://discord.com/)(.*)$ 24 | 25 | # Apps 26 | 27 | windowrule = float, ^(steam)$ 28 | windowrule = float, ^(itch)$ 29 | windowrulev2 = float, title:^(Bluetooth)$ 30 | windowrulev2 = tile, class:(dev.warp.Warp) 31 | windowrulev2 = float, title:^(Calculator)$ 32 | windowrulev2 = float, title:^(Volume Control)$ 33 | 34 | # Games 35 | 36 | windowrule=immediate,.*\.exe 37 | #windowrulev2=fullscreen,class:(steam_app) 38 | #windowrulev2=immediate,class:(steam_app) 39 | #windowrulev2=fullscreen, title:^(Steam Big Picture Mode)$ 40 | 41 | # Layers 42 | 43 | layerrule = noanim, hyprpicker 44 | 45 | layerrule = blur, wofi 46 | layerrule = xray, wofi 47 | layerrule = ignorezero 0.4, wofi 48 | #layerrule = animation popin, wofi 49 | 50 | # Fabric 51 | 52 | layerrule = blur, bar 53 | layerrule = ignorealpha 0.4, bar 54 | 55 | layerrule = blur, side-left 56 | layerrule = ignorealpha 0.4, side-left 57 | layerrule = animation slide, side-left 58 | 59 | layerrule = blur, side-right 60 | layerrule = ignorealpha 0.4, side-right 61 | layerrule = animation slide, side-right 62 | 63 | 64 | layerrule = blur, launcher 65 | layerrule = ignorealpha 0.4, launcher 66 | #layerrule = animation popin, launcher 67 | 68 | layerrule = blur, floating-player 69 | layerrule = ignorealpha 0.4, floating-player 70 | 71 | layerrule = blur, notifications 72 | layerrule = ignorealpha 0.4, notifications 73 | -------------------------------------------------------------------------------- /.config/hypr/hyprlock.conf: -------------------------------------------------------------------------------- 1 | $border = rgba(26, 28, 30, 0.1) 2 | $background = rgba(26, 28, 30, 0.6) 3 | $onBackground = rgba(226, 226, 229, 1) 4 | $surface = rgba(26, 28, 30, 0.2) 5 | $inverseOnSurface = rgba(47, 48, 50, 1) 6 | 7 | general { 8 | hide_cursor = true 9 | } 10 | 11 | background { 12 | monitor = 13 | color = rgba(26, 28, 30) 14 | blur_size = 4 15 | blur_passes = 3 16 | noise = 0.0117 17 | contrast = 1.3000 18 | brightness = 0.8000 19 | vibrancy = 0.2100 20 | vibrancy_darkness = 0.0 21 | } 22 | 23 | # Monitor 1 24 | 25 | input-field { 26 | monitor = eDP-1 27 | size = 350, 65 28 | halign = center 29 | valign = center 30 | position = 0, -600 31 | placeholder_text = Enter Password 32 | fade_on_empty = false 33 | outer_color = $border 34 | inner_color = $background 35 | font_color = $onBackground 36 | dots_center = true 37 | # fade_on_empty = true 38 | } 39 | 40 | 41 | label { 42 | monitor = eDP-1 43 | text = cmd[update:1000] echo "$(date '+%A, %B %e')" 44 | color = $onBackground 45 | font_size = 35 46 | position = 0, 400 47 | halign = center 48 | valign = center 49 | } 50 | 51 | label { 52 | monitor = eDP-1 53 | text = $TIME 54 | color = $onBackground 55 | font_size = 85 56 | position = 0, 320 57 | halign = center 58 | valign = center 59 | } 60 | 61 | label { 62 | monitor = eDP-1 63 | text = Hello $USER 64 | color = $onBackground 65 | font_size = 30 66 | position = 0, -530 67 | halign = center 68 | valign = center 69 | } 70 | 71 | # Monitor 2 72 | 73 | label { 74 | monitor = DP-2 75 | text = cmd[update:1000] echo "$(date '+%A, %B %e')" 76 | color = $onBackground 77 | font_size = 35 78 | position = 0, 50 79 | halign = center 80 | valign = center 81 | } 82 | 83 | label { 84 | monitor = DP-2 85 | text = $TIME 86 | color = $onBackground 87 | font_size = 85 88 | position = 0, 0 89 | halign = center 90 | valign = center 91 | } 92 | 93 | label { 94 | monitor = DP-2 95 | text = Login on your other screen 96 | color = $onBackground 97 | font_size = 15 98 | position = 0, -500 99 | halign = center 100 | valign = center 101 | } 102 | -------------------------------------------------------------------------------- /.config/kitty/kitty.conf: -------------------------------------------------------------------------------- 1 | include ~/.cache/wal/colors-kitty.conf 2 | font_family JetBrains Mono Nerd Font 3 | 4 | font_size 12 5 | confirm_os_window_close 0 6 | 7 | map ctrl+c copy_to_clipboard 8 | map ctrl+v paste_from_clipboard 9 | map ctrl+shift+c send_text all \x03 10 | 11 | adjust_line_height 0 12 | cursor #00ccff 13 | 14 | # A port of forest night by sainnhe 15 | # https://github.com/sainnhe/forest-night 16 | 17 | ## name: Everforest Dark B 18 | ## author: nope 19 | ## license: idk 20 | ## blurb: everforesttttttt 21 | 22 | #window 23 | window_padding_width 20 24 | background_opacity 0.5 25 | -------------------------------------------------------------------------------- /.config/starship.toml: -------------------------------------------------------------------------------- 1 | # Don't print a new line at the start of the prompt 2 | add_newline = false 3 | # Pipes ╰─ ╭─ 4 | # Powerline symbols                                    5 | # Wedges 🭧🭒 🭣🭧🭓 6 | # Random noise 🬖🬥🬔🬗 7 | 8 | right_format = """\ 9 | $cmd_duration 10 | """ 11 | 12 | format = """ 13 | $username$hostname$directory 14 | $character 15 | """ 16 | 17 | # Replace the "❯" symbol in the prompt with "➜" 18 | [character] # The name of the module we are configuring is "character" 19 | success_symbol = "[🭧🭒](bold fg:blue)[ ➜ ](bold bg:blue fg:#000000)[](bold fg:blue)" 20 | 21 | error_symbol = "[🭧🭒](bold fg:red)[ ✗ ](bold bg:red fg:#000000)[](bold fg:red)" 22 | # Disable the package module, hiding it from the prompt completely 23 | [package] 24 | disabled = true 25 | 26 | [git_branch] 27 | symbol = "🌱 " 28 | truncation_length = 4 29 | truncation_symbol = "" 30 | 31 | [git_commit] 32 | commit_hash_length = 4 33 | tag_symbol = "🔖 " 34 | 35 | [git_state] 36 | format = '[\($state( $progress_current of $progress_total)\)]($style) ' 37 | cherry_pick = "[🍒 PICKING](bold red)" 38 | 39 | [git_status] 40 | conflicted = " 🏳 " 41 | ahead = " 🏎💨 " 42 | behind = " 😰 " 43 | diverged = " 😵 " 44 | untracked = " 🤷 ‍" 45 | stashed = " 📦 " 46 | modified = " 📝 " 47 | staged = '[++\($count\)](blue)' 48 | renamed = " ✍️ " 49 | deleted = " 🗑 " 50 | 51 | [hostname] 52 | ssh_only = false 53 | format = "[ ](bold bg:yellow fg:blue)[$hostname](bg:yellow bold fg:#000000)[ ](bold fg:yellow bg:green)" 54 | trim_at = ".companyname.com" 55 | disabled = false 56 | 57 | [line_break] 58 | disabled = false 59 | 60 | [memory_usage] 61 | disabled = true 62 | threshold = -1 63 | symbol = " " 64 | style = "bold dimmed blue" 65 | 66 | [time] 67 | disabled = true 68 | format = '🕙[\[ $time \]]($style) ' 69 | time_format = "%T" 70 | 71 | [username] 72 | style_user = "bold bg:blue fg:#000000" 73 | style_root = "red bold" 74 | format = "[🭃](bold fg:blue)[$user]($style)" 75 | disabled = false 76 | show_always = true 77 | 78 | [directory] 79 | home_symbol = " " 80 | read_only = "  " 81 | style = "bold bg:green fg:#000000" 82 | truncation_length = 2 83 | truncation_symbol = "./" 84 | format = '[$path]($style)[🭞](fg:green )' 85 | 86 | 87 | [directory.substitutions] 88 | "Documents" = " " 89 | "/" = "  " 90 | "Downloads" = " " 91 | "Music" = " " 92 | "Pictures" = " " 93 | 94 | [cmd_duration] 95 | min_time = 0 96 | format = '[🬈🬖🬥🬅 ](bold bg:cyan fg:#000000)[time:$duration](bold bg:cyan fg:#000000)[ 🬖🬥🬔🬗](bold bg:cyan fg:#000000)' -------------------------------------------------------------------------------- /.config/wofi/config: -------------------------------------------------------------------------------- 1 | allow_images=true 2 | prompt=Search... 3 | image_size=24 4 | line_warp=word_charline_warp=word_char 5 | # gtk_dark=true 6 | # width=450 7 | -------------------------------------------------------------------------------- /.config/wofi/style.css: -------------------------------------------------------------------------------- 1 | @import url('/home/sofa/.config/wofi/styles/color.css'); 2 | 3 | * { 4 | all: unset; 5 | color: @all; 6 | } 7 | 8 | window { 9 | border-radius: 0.5rem; 10 | background-color: alpha(@window, 0.9); 11 | border: 1px solid @window-border; 12 | } 13 | 14 | #input { 15 | margin: 0.5rem; 16 | background-color: transparent; 17 | padding: 0.5rem; 18 | } 19 | 20 | #input image { 21 | margin-right: 0.5rem; 22 | color: @input-image; 23 | } 24 | 25 | #scroll { 26 | border-top: 1px solid @scroll-border; 27 | } 28 | 29 | #inner-box { 30 | padding: 0.5rem; 31 | } 32 | 33 | #entry { 34 | padding: 0.5rem; 35 | border-radius: 0.5rem; 36 | } 37 | 38 | #entry image { 39 | margin-right: 0.75rem; 40 | } 41 | 42 | #entry:selected { 43 | background-color: alpha(@entry-select-background, 0.8); 44 | padding: 0.5rem; 45 | } 46 | -------------------------------------------------------------------------------- /.config/wofi/styles/color.css: -------------------------------------------------------------------------------- 1 | @import url('./light.css'); 2 | -------------------------------------------------------------------------------- /.config/wofi/styles/dark.css: -------------------------------------------------------------------------------- 1 | @import url('./neutral.css'); 2 | 3 | @define-color all @neutral-50; 4 | 5 | @define-color window @neutral-900; 6 | @define-color window-border @neutral-700; 7 | 8 | @define-color input-image @neutral-500; 9 | 10 | @define-color scroll-border @neutral-700; 11 | 12 | @define-color entry-select-background @neutral-800; -------------------------------------------------------------------------------- /.config/wofi/styles/light.css: -------------------------------------------------------------------------------- 1 | @import url('./neutral.css'); 2 | 3 | @define-color all @neutral-800; 4 | 5 | @define-color window @neutral-50; 6 | @define-color window-border @neutral-200; 7 | 8 | @define-color input-image @neutral-400; 9 | 10 | @define-color scroll-border @neutral-200; 11 | 12 | @define-color entry-select-background @neutral-300; -------------------------------------------------------------------------------- /.config/wofi/styles/neutral.css: -------------------------------------------------------------------------------- 1 | @define-color neutral-50 #fafafa; 2 | @define-color neutral-100 #f5f5f5; 3 | @define-color neutral-200 #e5e5e5; 4 | @define-color neutral-300 #d4d4d4; 5 | @define-color neutral-400 #a3a3a3; 6 | @define-color neutral-500 #737373; 7 | @define-color neutral-600 #525252; 8 | @define-color neutral-700 #404040; 9 | @define-color neutral-800 #262626; 10 | @define-color neutral-900 #171717; 11 | @define-color neutral-950 #0a0a0a; 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ -------------------------------------------------------------------------------- /.pal/ai.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "adrienbrault/gorilla-openfunctions-v2:Q4_K_M", 3 | "host": "http://localhost:11434", 4 | "trust_mode": true 5 | } 6 | -------------------------------------------------------------------------------- /.pal/browse.json: -------------------------------------------------------------------------------- 1 | { 2 | "engines": [ 3 | { 4 | "name": "duckduckgo", 5 | "url": "https://duckduckgo.com/?q=%s" 6 | }, 7 | { 8 | "name": "perplexity", 9 | "url": "https://www.perplexity.ai/?q=%s" 10 | }, 11 | { 12 | "name": "aur", 13 | "url": "https://archlinux.org/packages/?q=%s" 14 | }, 15 | { 16 | "name": "urban", 17 | "url": "http://www.urbandictionary.com/define.php?term=%s" 18 | }, 19 | { 20 | "name": "pypi", 21 | "url": "https://pypi.org/search/?q=%s" 22 | }, 23 | { 24 | "name": "youtube", 25 | "url": "https://www.youtube.com/results?search_query=%s" 26 | } 27 | ], 28 | "default": { 29 | "name": "duckduckgo", 30 | "url": "https://duckduckgo.com/?q=%s" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.pal/plugins/mode.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import re 4 | 5 | 6 | class Plugin: 7 | def __init__(self, commands: argparse._SubParsersAction) -> None: 8 | self.command = commands.add_parser( 9 | "mode", 10 | help="Light/Dark mode switcher", 11 | description="Light/Dark mode switcher", 12 | ) 13 | self.function = { 14 | "name": "mode", 15 | "description": "Switch between light/dark theme", 16 | "parameters": { 17 | "type": "object", 18 | "properties": { 19 | "theme": { 20 | "type": "string", 21 | "description": "The theme that the current mode is set to", 22 | "enum": ["light", "dark"], 23 | } 24 | }, 25 | "required": ["theme"], 26 | }, 27 | } 28 | 29 | def run(self, args: argparse.Namespace, parser: argparse.ArgumentParser) -> None: 30 | if args.light or args.theme == "light": 31 | os.system("gsettings set org.gnome.desktop.interface gtk-theme 'adw-gtk3'") 32 | os.system( 33 | "gsettings set org.gnome.desktop.interface color-scheme 'prefer-light'" 34 | ) 35 | os.system( 36 | "echo \"@import url('./light.css');\" > $HOME/.config/wofi/styles/color.css" 37 | ) 38 | os.system( 39 | "echo \"@import url('./colors/light.css');\" > $HOME/.config/fabric/css/color.css" 40 | ) 41 | os.system( 42 | "wal -i $(swww query | grep -oP '(?<=currently displaying: image: ).*' | uniq) -l" 43 | ) 44 | elif args.dark or args.theme == "dark": 45 | os.system( 46 | "gsettings set org.gnome.desktop.interface gtk-theme 'adw-gtk3-dark'" 47 | ) 48 | os.system( 49 | "gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark'" 50 | ) 51 | os.system( 52 | "echo \"@import url('./dark.css');\" > $HOME/.config/wofi/styles/color.css" 53 | ) 54 | os.system( 55 | "echo \"@import url('./colors/dark.css');\" > $HOME/.config/fabric/css/color.css" 56 | ) 57 | os.system( 58 | "wal -i $(swww query | grep -oP '(?<=currently displaying: image: ).*' | uniq)" 59 | ) 60 | 61 | def setup(self) -> None: 62 | self.command.add_argument( 63 | "-l", "--light", help="Light mode", action="store_true" 64 | ) 65 | self.command.add_argument("-d", "--dark", help="Dark mode", action="store_true") 66 | self.command.add_argument("-t", "--theme", help="Mode (AI)", action="store") 67 | -------------------------------------------------------------------------------- /.pal/plugins/wallpaper.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import random 4 | import subprocess 5 | from pathlib import Path 6 | 7 | from InquirerPy import inquirer 8 | 9 | 10 | class Plugin: 11 | def __init__(self, commands: argparse._SubParsersAction) -> None: 12 | self.command = commands.add_parser( 13 | "wallpaper", 14 | help="Set current wallpaper", 15 | description="Set current wallpaper", 16 | ) 17 | self.function = { 18 | "name": "wallpaper", 19 | "description": "Set current wallpaper", 20 | "parameters": { 21 | "type": "object", 22 | "properties": { 23 | "file": { 24 | "type": "string", 25 | "description": "Filename of image to set as wallpaper", 26 | } 27 | }, 28 | "required": ["file"], 29 | }, 30 | } 31 | 32 | def run(self, args: argparse.Namespace, parser: argparse.ArgumentParser) -> None: 33 | if args.random: 34 | files = os.listdir(Path("Pictures")) 35 | file = random.choice(files) 36 | else: 37 | file = args.file 38 | 39 | if not file: 40 | files = os.listdir(Path("Pictures")) 41 | file = inquirer.fuzzy( 42 | message="Select wallpaper:", 43 | choices=files, 44 | raise_keyboard_interrupt=False, 45 | mandatory=False, 46 | long_instruction="Current: " 47 | + self.function["parameters"]["properties"]["file"]["enum"][ 48 | 0 49 | ], # set current wall 50 | ).execute() 51 | 52 | if file: 53 | if args.preview: 54 | os.system( 55 | f"swww img $HOME/Pictures/{file} --transition-step 100 --transition-fps 60 --transition-type grow --transition-angle 30 --transition-duration 1" 56 | ) 57 | os.system( 58 | "wal -i $(swww query | grep -oP '(?<=currently displaying: image: ).*' | uniq)" 59 | ) 60 | else: 61 | os.system(f"kitten icat $HOME/Pictures/{file}") 62 | 63 | def setup(self): 64 | current = subprocess.check_output( 65 | "swww query | grep -oP '(?<=currently displaying: image: /home/sofa/Pictures/).*' | uniq", 66 | shell=True, 67 | text=True, 68 | ) 69 | 70 | self.function["parameters"]["properties"]["file"]["enum"] = [ 71 | f"{str(current).strip()}" 72 | ] 73 | 74 | self.command.add_argument( 75 | "-f", "--file", help="Filename of image to set as wallpaper", action="store" 76 | ) 77 | self.command.add_argument( 78 | "-p", 79 | "--preview", 80 | help="Preview file without setting", 81 | action="store_false", 82 | ) 83 | self.command.add_argument( 84 | "-r", "--random", help="Set random wallpaper", action="store_true" 85 | ) 86 | -------------------------------------------------------------------------------- /.pal/templates/python-venv.sh: -------------------------------------------------------------------------------- 1 | # Create location 2 | 3 | mkdir $1 4 | cd $1 5 | 6 | # Add requirements file 7 | 8 | touch requirements.txt 9 | 10 | # Create venv 11 | 12 | python3 -m venv .venv 13 | 14 | echo "{ 15 | \"venvPath\": \".\", 16 | \"venv\": \".venv\" 17 | }" > pyrightconfig.json 18 | -------------------------------------------------------------------------------- /.pal/templates/sveltekit-tailwindcss-space.sh: -------------------------------------------------------------------------------- 1 | # Create sveltekit project and install packages 2 | 3 | yarn create svelte $1 4 | cd $1 5 | yarn install 6 | 7 | # Add tailwindcss 8 | 9 | yarn add -D tailwindcss postcss autoprefixer 10 | npx tailwindcss init -p 11 | 12 | echo "import adapter from '@sveltejs/adapter-auto'; 13 | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; 14 | /** @type {import('@sveltejs/kit').Config} */ 15 | const config = { 16 | kit: { 17 | adapter: adapter() 18 | }, 19 | preprocess: vitePreprocess() 20 | }; 21 | export default config;" > svelte.config.js 22 | echo "/** @type {import('tailwindcss').Config} */ 23 | export default { 24 | content: ['./src/**/*.{html,js,svelte,ts}'], 25 | theme: { 26 | extend: {} 27 | }, 28 | plugins: [] 29 | };" > tailwind.config.js 30 | 31 | touch ./src/app.css 32 | echo "@tailwind base; 33 | @tailwind components; 34 | @tailwind utilities;" > ./src/app.css 35 | 36 | touch ./src/routes/+layout.svelte 37 | echo " 40 | 41 | " > ./src/routes/+layout.svelte 42 | 43 | # Add deta space 44 | 45 | touch Spacefile 46 | echo "v: 0 47 | micros: 48 | - name: $1 49 | src: . 50 | engine: svelte-kit 51 | primary: true 52 | dev: yarn dev" > Spacefile 53 | -------------------------------------------------------------------------------- /.pal/weather.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": "hidden", 3 | "api_key": "hidden", 4 | "format": "celsius" 5 | } 6 | -------------------------------------------------------------------------------- /.wallpapers/Dark/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/Dark/1.jpg -------------------------------------------------------------------------------- /.wallpapers/Dark/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/Dark/14.jpg -------------------------------------------------------------------------------- /.wallpapers/Dark/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/Dark/2.jpg -------------------------------------------------------------------------------- /.wallpapers/Dark/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/Dark/5.jpg -------------------------------------------------------------------------------- /.wallpapers/Dark/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/Dark/8.jpg -------------------------------------------------------------------------------- /.wallpapers/Light/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/Light/10.jpg -------------------------------------------------------------------------------- /.wallpapers/Light/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/Light/11.jpg -------------------------------------------------------------------------------- /.wallpapers/Light/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/Light/12.jpg -------------------------------------------------------------------------------- /.wallpapers/Light/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/Light/13.jpg -------------------------------------------------------------------------------- /.wallpapers/Light/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/Light/3.jpg -------------------------------------------------------------------------------- /.wallpapers/Light/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/Light/4.jpg -------------------------------------------------------------------------------- /.wallpapers/Light/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/Light/6.jpg -------------------------------------------------------------------------------- /.wallpapers/Light/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/Light/9.jpg -------------------------------------------------------------------------------- /.wallpapers/readme.md: -------------------------------------------------------------------------------- 1 | See `wallpaper.png` for current wallpaper 2 | 3 | #### Credits 4 | 5 | ##### Dark 6 | 7 | - [Image 1](https://unsplash.com/photos/_41WmEwi8Ok) 8 | - [Image 2](https://unsplash.com/photos/xl2piFfdzyA) 9 | - [Image 5](https://unsplash.com/photos/cfKwE7k9qqA) 10 | - [Image 8](https://unsplash.com/photos/7NJE_JbVReo) 11 | - [Image 14](https://unsplash.com/photos/LluELtL5mK4) 12 | 13 | ##### Light 14 | 15 | - [Image 3](https://unsplash.com/photos/S3U-vCgnaqI) 16 | - [Image 4](https://unsplash.com/photos/ECxsxbjAmMY) 17 | - [Image 6](https://unsplash.com/photos/l8cvrt3Hpec) 18 | - [Image 9](https://unsplash.com/photos/GJKx5lhwU3M) 19 | - [Image 10](https://unsplash.com/photos/-n5F3fH0lIY) 20 | - [Image 11](https://unsplash.com/photos/FZWivbri0Xk) 21 | - [Image 12](https://unsplash.com/photos/uuCjYxJVf4o) 22 | - [Image 13](https://unsplash.com/photos/r8AFUpRp0J0) -------------------------------------------------------------------------------- /.wallpapers/wallpaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/.wallpapers/wallpaper.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dots 2 | 3 | ## Spacerice 4 | 5 | ![showcase](screenshots/image-1.png) 6 | > Bar and side panels open 7 | 8 | ![showcase](screenshots/image-2.png) 9 | > Bar with side panels hidden and notification 10 | 11 | ![showcase](screenshots/image-3.png) 12 | > Side menus 13 | 14 | ![showcase](screenshots/image-4.png) 15 | > fabricast, application launcher 16 | 17 | 18 | 19 | 22 | 23 | 24 | 34 |
20 | :warning: WARNING :warning: 21 |
25 | 26 | Some configs for hyprland are 27 | specifically made for my setup and 28 | may not work on yours! 29 | 30 | Make sure you understand the configs 31 | and can modify them accordingly. 32 | 33 |
35 | -------------------------------------------------------------------------------- /screenshots/image-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/screenshots/image-1.png -------------------------------------------------------------------------------- /screenshots/image-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/screenshots/image-2.png -------------------------------------------------------------------------------- /screenshots/image-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/screenshots/image-3.png -------------------------------------------------------------------------------- /screenshots/image-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlumberDemon/dotfiles/4d744ec5cfa0a4b7d26d4061705dc109a679efea/screenshots/image-4.png --------------------------------------------------------------------------------