├── .github ├── FUNDING.yml ├── IMG │ ├── arch screenshot2s.jpg │ ├── swappy-20240914-100412.png │ ├── swappy-20240914-100444.png │ ├── swappy-20240914-111735.png │ ├── swappy-20240914-112027.png │ ├── swappy-20250430-212144.png │ ├── swappy-20250430-212500.png │ └── swappy-20250430-212536.png ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ ├── documentation_update.md │ └── feature_request.md └── PULL_REQUEST_TEMPLATE.md ├── COMMIT_MESSAGE_GUIDELINES.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── config ├── Kvantum │ ├── Catppuccin-Mocha │ │ ├── Catppuccin-Mocha.kvconfig │ │ └── Catppuccin-Mocha.svg │ ├── Tokyo-Day │ │ ├── Tokyo-Day.kvconfig │ │ └── Tokyo-Day.svg │ ├── Tokyo-Night │ │ ├── Tokyo-Night.kvconfig │ │ └── Tokyo-Night.svg │ └── kvantum.kvconfig ├── ags │ ├── .eslintrc.yml │ ├── .gitignore │ ├── assets │ │ ├── battery-flash-symbolic.svg │ │ ├── chat-bubbles-symbolic.svg │ │ ├── controller-symbolic.svg │ │ ├── controls-symbolic.svg │ │ ├── dark-mode-symbolic.svg │ │ ├── hourglass-symbolic.svg │ │ ├── light-mode-symbolic.svg │ │ ├── mixer-symbolic.svg │ │ ├── nix-snowflake-symbolic.svg │ │ ├── preferences-desktop-theme-symbolic.svg │ │ ├── processor-symbolic.svg │ │ ├── terminal-symbolic.svg │ │ └── toolbars-symbolic.svg │ ├── config.js │ ├── default.nix │ ├── greeter.js │ ├── greeter │ │ ├── auth.ts │ │ ├── greeter.ts │ │ ├── session.ts │ │ └── statusbar.ts │ ├── lib │ │ ├── battery.ts │ │ ├── gtk.ts │ │ ├── hyprland.ts │ │ ├── icons.ts │ │ ├── init.ts │ │ ├── matugen.ts │ │ ├── notifications.ts │ │ ├── option.ts │ │ ├── session.ts │ │ ├── tmux.ts │ │ ├── utils.ts │ │ └── variables.ts │ ├── main.ts │ ├── options.ts │ ├── package.json │ ├── service │ │ ├── asusctl.ts │ │ ├── brightness.ts │ │ ├── colorpicker.ts │ │ ├── nix.ts │ │ ├── powermenu.ts │ │ ├── screenrecord.ts │ │ ├── sh.ts │ │ ├── wallpaper.ts │ │ └── weather.ts │ ├── style │ │ ├── extra.scss │ │ ├── mixins │ │ │ ├── a11y-button.scss │ │ │ ├── button.scss │ │ │ ├── floating-widget.scss │ │ │ ├── hidden.scss │ │ │ ├── media.scss │ │ │ ├── scrollable.scss │ │ │ ├── slider.scss │ │ │ ├── spacing.scss │ │ │ ├── switch.scss │ │ │ ├── unset.scss │ │ │ └── widget.scss │ │ ├── style.ts │ │ └── widgets │ │ │ ├── bar.scss │ │ │ ├── datemenu.scss │ │ │ ├── greeter.scss │ │ │ ├── launcher.scss │ │ │ ├── notifications.scss │ │ │ ├── osd.scss │ │ │ ├── overview.scss │ │ │ ├── powermenu.scss │ │ │ ├── quicksettings.scss │ │ │ ├── screencorner.scss │ │ │ └── settingsdialog.scss │ ├── tsconfig.json │ └── widget │ │ ├── PopupWindow.ts │ │ ├── RegularWindow.ts │ │ ├── bar │ │ ├── Bar.ts │ │ ├── PanelButton.ts │ │ ├── ScreenCorners.ts │ │ └── buttons │ │ │ ├── BatteryBar.ts │ │ │ ├── ColorPicker.ts │ │ │ ├── Date.ts │ │ │ ├── Launcher.ts │ │ │ ├── Media.ts │ │ │ ├── Messages.ts │ │ │ ├── PowerMenu.ts │ │ │ ├── ScreenRecord.ts │ │ │ ├── SysTray.ts │ │ │ ├── SystemIndicators.ts │ │ │ ├── Taskbar.ts │ │ │ └── Workspaces.ts │ │ ├── datemenu │ │ ├── DateColumn.ts │ │ ├── DateMenu.ts │ │ └── NotificationColumn.ts │ │ ├── desktop │ │ └── Desktop.ts │ │ ├── launcher │ │ ├── AppLauncher.ts │ │ ├── Launcher.ts │ │ ├── NixRun.ts │ │ └── ShRun.ts │ │ ├── notifications │ │ ├── Notification.ts │ │ └── NotificationPopups.ts │ │ ├── osd │ │ ├── OSD.ts │ │ └── Progress.ts │ │ ├── overview │ │ ├── Overview.ts │ │ ├── Window.ts │ │ └── Workspace.ts │ │ ├── powermenu │ │ ├── PowerMenu.ts │ │ └── Verification.ts │ │ ├── quicksettings │ │ ├── QuickSettings.ts │ │ ├── ToggleButton.ts │ │ └── widgets │ │ │ ├── Bluetooth.ts │ │ │ ├── Brightness.ts │ │ │ ├── DND.ts │ │ │ ├── DarkMode.ts │ │ │ ├── Header.ts │ │ │ ├── Media.ts │ │ │ ├── MicMute.ts │ │ │ ├── Network.ts │ │ │ ├── PowerProfile.ts │ │ │ └── Volume.ts │ │ └── settings │ │ ├── Group.ts │ │ ├── Page.ts │ │ ├── Row.ts │ │ ├── Setter.ts │ │ ├── SettingsDialog.ts │ │ ├── Wallpaper.ts │ │ └── layout.ts ├── alacritty │ └── alacritty.toml ├── btop │ ├── btop.conf │ └── themes │ │ ├── catppuccin_frappe.theme │ │ ├── catppuccin_latte.theme │ │ ├── catppuccin_macchiato.theme │ │ └── catppuccin_mocha.theme ├── cava │ ├── config │ └── shaders │ │ ├── bar_spectrum.frag │ │ ├── normalized_bars.frag │ │ └── pass_through.vert ├── hypr │ ├── UserConfigs │ │ ├── 00-Readme │ │ ├── ENVariables.conf │ │ ├── LaptopDisplay.conf │ │ ├── Laptops.conf │ │ ├── Monitors.conf │ │ ├── Startup_Apps.conf │ │ ├── UserKeybinds.conf │ │ ├── UserSettings.conf │ │ └── WindowRules.conf │ ├── configs │ │ ├── Keybinds.conf │ │ └── Settings.conf │ ├── hyprland.conf │ ├── hyprlock.conf │ ├── initial-boot.sh │ ├── scripts │ │ ├── ChangeBlur.sh │ │ ├── ChangeLayout.sh │ │ ├── ClipManager.sh │ │ ├── DarkLight.sh │ │ ├── GameMode.sh │ │ ├── KeyHints.sh │ │ ├── LockScreen.sh │ │ ├── MediaCtrl.sh │ │ ├── Polkit-NixOS.sh │ │ ├── Polkit.sh │ │ ├── PortalHyprland.sh │ │ ├── PywalSwww.sh │ │ ├── Refresh.sh │ │ ├── RofiEmoji.sh │ │ ├── ScreenShot.sh │ │ ├── SwitchKeyboardLayout.sh │ │ ├── TouchPad.sh │ │ └── Volume.sh │ └── v4.0 ├── kitty │ └── kitty.conf ├── nushell │ ├── config.nu │ ├── env.nu │ └── history.txt ├── nvim │ ├── .stylua.toml │ ├── init.lua │ └── lua │ │ ├── chadrc.lua │ │ ├── configs │ │ ├── conform.lua │ │ ├── lazy.lua │ │ └── lspconfig.lua │ │ ├── mappings.lua │ │ ├── options.lua │ │ └── plugins │ │ └── init.lua ├── qt5ct │ ├── colors │ │ ├── Catppuccin-Mocha.conf │ │ ├── Tokyo-Day.conf │ │ └── Tokyo-Night.conf │ └── qt5ct.conf ├── qt6ct │ ├── colors │ │ ├── Tokyo-Day.conf │ │ └── Tokyo-Night.conf │ └── qt6ct.conf ├── starship.toml ├── swappy │ └── config ├── tmux │ ├── README.md │ └── tmux.conf └── wal │ └── templates │ ├── cava-colors │ ├── color-alacritty.toml │ ├── colors-hyprland │ ├── colors-rofi-dark.rasi │ └── colors-rofi-light.rasi ├── copy.sh └── release.sh /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/T6T1RG2QY) 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.github/IMG/arch screenshot2s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AXWTV/Hyprland-DotFiles/f4c00b255651821cded0632e14a9f9f934b4caa9/.github/IMG/arch screenshot2s.jpg -------------------------------------------------------------------------------- /.github/IMG/swappy-20240914-100412.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AXWTV/Hyprland-DotFiles/f4c00b255651821cded0632e14a9f9f934b4caa9/.github/IMG/swappy-20240914-100412.png -------------------------------------------------------------------------------- /.github/IMG/swappy-20240914-100444.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AXWTV/Hyprland-DotFiles/f4c00b255651821cded0632e14a9f9f934b4caa9/.github/IMG/swappy-20240914-100444.png -------------------------------------------------------------------------------- /.github/IMG/swappy-20240914-111735.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AXWTV/Hyprland-DotFiles/f4c00b255651821cded0632e14a9f9f934b4caa9/.github/IMG/swappy-20240914-111735.png -------------------------------------------------------------------------------- /.github/IMG/swappy-20240914-112027.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AXWTV/Hyprland-DotFiles/f4c00b255651821cded0632e14a9f9f934b4caa9/.github/IMG/swappy-20240914-112027.png -------------------------------------------------------------------------------- /.github/IMG/swappy-20250430-212144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AXWTV/Hyprland-DotFiles/f4c00b255651821cded0632e14a9f9f934b4caa9/.github/IMG/swappy-20250430-212144.png -------------------------------------------------------------------------------- /.github/IMG/swappy-20250430-212500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AXWTV/Hyprland-DotFiles/f4c00b255651821cded0632e14a9f9f934b4caa9/.github/IMG/swappy-20250430-212500.png -------------------------------------------------------------------------------- /.github/IMG/swappy-20250430-212536.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AXWTV/Hyprland-DotFiles/f4c00b255651821cded0632e14a9f9f934b4caa9/.github/IMG/swappy-20250430-212536.png -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[Bug]: Short description of the issue" 5 | labels: "Something isn't working" 6 | --- 7 | 8 | ## Bug Report 9 | 10 | ### Description 11 | 12 | [Provide a clear and concise description of the bug.] 13 | 14 | ### Steps to Reproduce 15 | 16 | 1. [First Step] 17 | 2. [Second Step] 18 | 3. [and so on...] 19 | 20 | ### Expected Behavior 21 | 22 | [What did you expect to happen?] 23 | 24 | ### Actual Behavior 25 | 26 | [What actually happened?] 27 | 28 | ### Screenshots 29 | 30 | [If applicable, add screenshots to help explain your problem.] 31 | 32 | ### Environment 33 | 34 | [Please add any other relevant information about the bug and remove the unnecessary lines.] 35 | 36 | e.g., 37 | 38 | - Linux Distro: [e.g., Fedora 38, Fedora 39, Nobara 38, etc] 39 | - Linux Version, output of `uname -a`: 40 | - Hyprland Version, output of `hyprctl version`: 41 | - Installation Environment: [e.g., On The Main Hardware, On A Virtual Machine] 42 | - Other info: [e.g., Display Resolution, Resolution, etc] 43 | 44 | ### Additional Information 45 | 46 | [Add any other information about the problem here. For example, you might include the error message, any recent changes that you made to the project, or any other relevant details.] 47 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom template 3 | about: Use this template to submit a custom issue 4 | title: "[Custom]: Short description of the issue" 5 | labels: "custom" 6 | --- 7 | 8 | ## Custom Template 9 | 10 | ### Description 11 | 12 | [Provide a clear and concise description of the issue or request.] 13 | 14 | ### Steps to Reproduce (if applicable) 15 | 16 | 1. [First Step] 17 | 2. [Second Step] 18 | 3. [and so on...] 19 | 20 | ### Expected Behavior 21 | 22 | [What did you expect to happen?] 23 | 24 | ### Actual Behavior 25 | 26 | [What actually happened?] 27 | 28 | ### Screenshots (if applicable) 29 | 30 | [If applicable, add screenshots to help explain your problem.] 31 | 32 | ### Proposed Solution (if applicable) 33 | 34 | [If you have a specific solution in mind, describe it here. If not, you can skip this section.] 35 | 36 | ### Additional Information 37 | 38 | [Add any other information about the issue or request here. For example, you might include links to similar features in other projects, or screenshots or diagrams to help explain your idea.] 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation_update.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Documentation update 3 | about: Propose a change to the project documentation 4 | title: "[Docs]: Short description of the change" 5 | labels: "documentation update" 6 | --- 7 | 8 | ## Documentation Update 9 | 10 | ### Description 11 | 12 | [Provide a clear and concise description of the documentation update you'd like to see made.] 13 | 14 | ### Current Documentation 15 | 16 | [Provide a link to the current documentation or describe where it can be found.] 17 | 18 | ### Proposed Documentation 19 | 20 | [Provide a clear and concise description of the updated documentation that you'd like to see added.] 21 | 22 | ### Additional Information 23 | 24 | [Add any other information about the documentation update here. For example, you might include links to similar documentation in other projects, or screenshots or diagrams to help explain your idea.] 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest a feature for this project 4 | title: "[Feature Request]: Short description of the feature" 5 | labels: "enhancement, needs triage, feature request" 6 | --- 7 | 8 | ## Feature Request 9 | 10 | ### Description 11 | 12 | [Provide a clear and concise description of the feature you'd like to see added.] 13 | 14 | ### Use Case 15 | 16 | [Describe how this feature would be useful to you or to other users of the project.] 17 | 18 | ### Proposed Solution 19 | 20 | [If you have a specific solution in mind, describe it here. If not, you can skip this section.] 21 | 22 | ### Alternatives 23 | 24 | [Are there any alternative solutions or workarounds that you've considered? If so, describe them here.] 25 | 26 | ### Additional Information 27 | 28 | [Add any other information about the feature request here. For example, you might include links to similar features in other projects, or screenshots or diagrams to help explain your idea.] 29 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Pull Request 2 | 3 | ## Description 4 | 5 | Please read these instructions and remove unnecessary text. 6 | 7 | - Try to include a summary of the changes and which issue is fixed. 8 | - Also include relevant motivation and context (if applicable). 9 | - List any dependencies that are required for this change. (e.g., packages or other PRs) 10 | - Provide a link if there is an issue related to this pull request. e.g., Fixes # (issue) 11 | - Please add Reviewers, Assignees, Labels, Projects, and Milestones to the PR. (if applicable) 12 | 13 | ## Type of change 14 | 15 | Please put an `x` in the boxes that apply: 16 | 17 | - [ ] **Bug fix** (non-breaking change which fixes an issue) 18 | - [ ] **New feature** (non-breaking change which adds functionality) 19 | - [ ] **Breaking change** (fix or feature that would cause existing functionality to not work as expected) 20 | - [ ] **Documentation update** (non-breaking change; modified files are limited to the documentations) 21 | - [ ] **Technical debt** (a code change that does not fix a bug or add a feature but makes something clearer for devs) 22 | - [ ] **Other** (provide details below) 23 | 24 | ## Checklist 25 | 26 | Please put an `x` in the boxes that apply: 27 | 28 | - [ ] I have read the [CONTRIBUTING](https://github.com/AXWTV/Hyprland-Installer/blob/main/CONTRIBUTING.md) document. 29 | - [ ] My code follows the code style of this project. 30 | - [ ] My commit message follows the [commit guidelines](https://github.com/AXWTV/Fedora-Hyprland/blob/main/CONTRIBUTING.md#git-commit-messages). 31 | - [ ] My change requires a change to the documentation. 32 | - [ ] I want to add something in Fedora-Hyprland wiki. 33 | - [ ] I have added tests to cover my changes. 34 | - [ ] I have tested my code locally and it works as expected. 35 | - [ ] All new and existing tests passed. 36 | 37 | ## Screenshots 38 | 39 | (if appropriate) 40 | 41 | ## Additional context 42 | 43 | Add any other context about the problem here. 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 AXWTV 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # ----- AXWTV-HYPRLAND-DOTFILE ----- 4 | 5 | 6 | Stargazers 7 | 8 | License 9 | 10 | last-commit 11 | 12 | GitHub release 13 | 14 |
15 |
16 | 17 | ![alt text](https://github.com/AXWTV/Hyprland-DotFiles/blob/main/.github/IMG/arch%20screenshot2s.jpg?raw=true) 18 | 19 | ### 💥 Copying / Installation / Update instructions 💥 20 | - [`MORE INFO HERE`](https://github.com/AXWTV/Hyprland-DotFiles/wiki) 21 | > [!Note] 22 | > The auto copy script will create backups of intended folders to be copied. However, still a good idea to manually backup just incase script failed to backup! 23 | - ~/.config (ags alacritty btop cava hypr kitty rofi swappy swaylock swaync waybar wlogout) - These are folders to be copied. 24 | - ~/Pictures/wallpapers - Will be backed up 25 | - clone this repo by using git. Change directory, make executable and run the script 26 | ```bash 27 | git clone --depth=1 https://github.com/AXWTV/Hyprland-DotFiles.git 28 | cd Hyprland-DotFiles 29 | ``` 30 | - to copy/install from upstream (possible bugs) 31 | ```bash 32 | chmod +x copy.sh 33 | ./copy.sh 34 | ``` 35 | - to copy/install from releases (more "stable") 36 | ```bash 37 | chmod +x release.sh 38 | ./release.sh 39 | ``` 40 | 41 | ### Hyprland Installer will All The Dependencise for Arch and Fedora [Here](https://github.com/AXWTV/Hyprland-Installer). 42 | 43 | ## Having Problems with installation or Other stuff 44 | - Feel Free to open issues 45 | - Also for guids go to [Wiki](https://github.com/AXWTV/Hyprland-DotFiles/wiki) 46 | 47 | #### This repo is a fork of [JaKooLit's Hyprland-Dots](https://github.com/JaKooLit/Hyprland-Dots). 48 | 49 | ## CHEATSHEET 50 | 51 | -------------------------------------------------------------------------------- /config/Kvantum/kvantum.kvconfig: -------------------------------------------------------------------------------- 1 | [General] 2 | theme=Tokyo-Night 3 | -------------------------------------------------------------------------------- /config/ags/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es2022: true 3 | extends: 4 | - "eslint:recommended" 5 | - "plugin:@typescript-eslint/recommended" 6 | parser: "@typescript-eslint/parser" 7 | parserOptions: 8 | ecmaVersion: 2022 9 | sourceType: "module" 10 | project: "./tsconfig.json" 11 | warnOnUnsupportedTypeScriptVersion: false 12 | root: true 13 | ignorePatterns: 14 | - types/ 15 | plugins: 16 | - "@typescript-eslint" 17 | rules: 18 | "@typescript-eslint/ban-ts-comment": 19 | - "off" 20 | "@typescript-eslint/no-non-null-assertion": 21 | - "off" 22 | # "@typescript-eslint/no-explicit-any": 23 | # - "off" 24 | "@typescript-eslint/no-unused-vars": 25 | - error 26 | - varsIgnorePattern: (^unused|_$) 27 | argsIgnorePattern: ^(unused|_) 28 | "@typescript-eslint/no-empty-interface": 29 | - "off" 30 | 31 | arrow-parens: 32 | - error 33 | - as-needed 34 | comma-dangle: 35 | - error 36 | - always-multiline 37 | comma-spacing: 38 | - error 39 | - before: false 40 | after: true 41 | comma-style: 42 | - error 43 | - last 44 | curly: 45 | - error 46 | - multi-or-nest 47 | - consistent 48 | dot-location: 49 | - error 50 | - property 51 | eol-last: 52 | - error 53 | eqeqeq: 54 | - error 55 | - always 56 | indent: 57 | - error 58 | - 4 59 | - SwitchCase: 1 60 | keyword-spacing: 61 | - error 62 | - before: true 63 | lines-between-class-members: 64 | - error 65 | - always 66 | - exceptAfterSingleLine: true 67 | padded-blocks: 68 | - error 69 | - never 70 | - allowSingleLineBlocks: false 71 | prefer-const: 72 | - error 73 | quotes: 74 | - error 75 | - double 76 | - avoidEscape: true 77 | semi: 78 | - error 79 | - never 80 | nonblock-statement-body-position: 81 | - error 82 | - below 83 | no-trailing-spaces: 84 | - error 85 | no-useless-escape: 86 | - off 87 | max-len: 88 | - error 89 | - code: 100 90 | func-call-spacing: 91 | - error 92 | array-bracket-spacing: 93 | - error 94 | space-before-function-paren: 95 | - error 96 | - anonymous: never 97 | named: never 98 | asyncArrow: ignore 99 | space-before-blocks: 100 | - error 101 | key-spacing: 102 | - error 103 | object-curly-spacing: 104 | - error 105 | - always 106 | globals: 107 | Widget: readonly 108 | Utils: readonly 109 | App: readonly 110 | Variable: readonly 111 | Service: readonly 112 | pkg: readonly 113 | ARGV: readonly 114 | Debugger: readonly 115 | GIRepositoryGType: readonly 116 | globalThis: readonly 117 | imports: readonly 118 | Intl: readonly 119 | log: readonly 120 | logError: readonly 121 | print: readonly 122 | printerr: readonly 123 | window: readonly 124 | TextEncoder: readonly 125 | TextDecoder: readonly 126 | console: readonly 127 | setTimeout: readonly 128 | setInterval: readonly 129 | clearTimeout: readonly 130 | clearInterval: readonly 131 | -------------------------------------------------------------------------------- /config/ags/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | types 3 | package-lock.json 4 | bun.lockb 5 | flake.lock 6 | .weather 7 | -------------------------------------------------------------------------------- /config/ags/assets/battery-flash-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /config/ags/assets/chat-bubbles-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /config/ags/assets/controller-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /config/ags/assets/controls-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /config/ags/assets/dark-mode-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /config/ags/assets/hourglass-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /config/ags/assets/light-mode-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /config/ags/assets/mixer-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /config/ags/assets/processor-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /config/ags/assets/terminal-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /config/ags/assets/toolbars-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /config/ags/config.js: -------------------------------------------------------------------------------- 1 | import GLib from "gi://GLib" 2 | 3 | const main = "/tmp/asztal/main.js" 4 | const entry = `${App.configDir}/main.ts` 5 | const bundler = GLib.getenv("AGS_BUNDLER") || "bun" 6 | 7 | const v = { 8 | ags: pkg.version?.split(".").map(Number) || [], 9 | expect: [1, 9, 1], 10 | } 11 | 12 | try { 13 | switch (bundler) { 14 | case "bun": await Utils.execAsync([ 15 | "bun", "build", entry, 16 | "--outfile", main, 17 | "--external", "resource://*", 18 | "--external", "gi://*", 19 | "--external", "file://*", 20 | ]); break 21 | 22 | case "esbuild": await Utils.execAsync([ 23 | "esbuild", "--bundle", entry, 24 | "--format=esm", 25 | `--outfile=${main}`, 26 | "--external:resource://*", 27 | "--external:gi://*", 28 | "--external:file://*", 29 | ]); break 30 | 31 | default: 32 | throw `"${bundler}" is not a valid bundler` 33 | } 34 | 35 | // if (v.ags[1] < v.expect[1] || v.ags[2] < v.expect[2]) { 36 | // print(`my config needs at least v${v.expect.join(".")}, yours is v${v.ags.join(".")}`) 37 | // App.quit() 38 | // } 39 | 40 | await import(`file://${main}`) 41 | } catch (error) { 42 | console.error(error) 43 | App.quit() 44 | } 45 | 46 | export { } 47 | -------------------------------------------------------------------------------- /config/ags/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs, 3 | writeShellScript, 4 | system, 5 | stdenv, 6 | cage, 7 | swww, 8 | esbuild, 9 | dart-sass, 10 | fd, 11 | fzf, 12 | brightnessctl, 13 | accountsservice, 14 | slurp, 15 | wf-recorder, 16 | wl-clipboard, 17 | wayshot, 18 | swappy, 19 | hyprpicker, 20 | pavucontrol, 21 | networkmanager, 22 | gtk3, 23 | which, 24 | }: let 25 | name = "asztal"; 26 | 27 | ags = inputs.ags.packages.${system}.default.override { 28 | extraPackages = [accountsservice]; 29 | }; 30 | 31 | dependencies = [ 32 | which 33 | dart-sass 34 | fd 35 | fzf 36 | brightnessctl 37 | swww 38 | inputs.matugen.packages.${system}.default 39 | slurp 40 | wf-recorder 41 | wl-clipboard 42 | wayshot 43 | swappy 44 | hyprpicker 45 | pavucontrol 46 | networkmanager 47 | gtk3 48 | ]; 49 | 50 | addBins = list: builtins.concatStringsSep ":" (builtins.map (p: "${p}/bin") list); 51 | 52 | greeter = writeShellScript "greeter" '' 53 | export PATH=$PATH:${addBins dependencies} 54 | ${cage}/bin/cage -ds -m last ${ags}/bin/ags -- -c ${config}/greeter.js 55 | ''; 56 | 57 | desktop = writeShellScript name '' 58 | export PATH=$PATH:${addBins dependencies} 59 | ${ags}/bin/ags -b ${name} -c ${config}/config.js $@ 60 | ''; 61 | 62 | config = stdenv.mkDerivation { 63 | inherit name; 64 | src = ./.; 65 | 66 | buildPhase = '' 67 | ${esbuild}/bin/esbuild \ 68 | --bundle ./main.ts \ 69 | --outfile=main.js \ 70 | --format=esm \ 71 | --external:resource://\* \ 72 | --external:gi://\* \ 73 | 74 | ${esbuild}/bin/esbuild \ 75 | --bundle ./greeter/greeter.ts \ 76 | --outfile=greeter.js \ 77 | --format=esm \ 78 | --external:resource://\* \ 79 | --external:gi://\* \ 80 | ''; 81 | 82 | installPhase = '' 83 | mkdir -p $out 84 | cp -r assets $out 85 | cp -r style $out 86 | cp -r greeter $out 87 | cp -r widget $out 88 | cp -f main.js $out/config.js 89 | cp -f greeter.js $out/greeter.js 90 | ''; 91 | }; 92 | in 93 | stdenv.mkDerivation { 94 | inherit name; 95 | src = config; 96 | 97 | installPhase = '' 98 | mkdir -p $out/bin 99 | cp -r . $out 100 | cp ${desktop} $out/bin/${name} 101 | cp ${greeter} $out/bin/greeter 102 | ''; 103 | } 104 | -------------------------------------------------------------------------------- /config/ags/greeter.js: -------------------------------------------------------------------------------- 1 | const main = "/tmp/ags/greeter.js" 2 | const entry = `${App.configDir}/greeter/greeter.ts` 3 | 4 | try { 5 | await Utils.execAsync([ 6 | "bun", "build", entry, 7 | "--outfile", main, 8 | "--external", "resource://*", 9 | "--external", "gi://*", 10 | "--external", "file://*", 11 | ]) 12 | await import(`file://${main}`) 13 | } catch (error) { 14 | console.error(error) 15 | App.quit() 16 | } 17 | 18 | export { } 19 | -------------------------------------------------------------------------------- /config/ags/greeter/greeter.ts: -------------------------------------------------------------------------------- 1 | import "./session" 2 | import "style/style" 3 | import GLib from "gi://GLib?version=2.0" 4 | import RegularWindow from "widget/RegularWindow" 5 | import statusbar from "./statusbar" 6 | import auth from "./auth" 7 | 8 | const win = RegularWindow({ 9 | name: "greeter", 10 | setup: self => { 11 | self.set_default_size(500, 500) 12 | self.show_all() 13 | auth.attribute.password.grab_focus() 14 | }, 15 | child: Widget.Overlay({ 16 | child: Widget.Box({ expand: true }), 17 | overlays: [ 18 | Widget.Box({ 19 | vpack: "start", 20 | hpack: "fill", 21 | hexpand: true, 22 | child: statusbar, 23 | }), 24 | Widget.Box({ 25 | vpack: "center", 26 | hpack: "center", 27 | child: auth, 28 | }), 29 | ], 30 | }), 31 | }) 32 | 33 | App.config({ 34 | icons: "./assets", 35 | windows: [win], 36 | cursorTheme: GLib.getenv("XCURSOR_THEME")!, 37 | }) 38 | -------------------------------------------------------------------------------- /config/ags/greeter/session.ts: -------------------------------------------------------------------------------- 1 | import GLib from "gi://GLib?version=2.0" 2 | import { bash } from "lib/utils" 3 | 4 | // import AccountsService from "gi://AccountsService?version=1.0" 5 | // const { userName } = AccountsService.UserManager.get_default().list_users()[0] 6 | 7 | const userName = await bash("find /home -maxdepth 1 -printf '%f\n' | tail -n 1") 8 | 9 | declare global { 10 | const WALLPAPER: string 11 | } 12 | 13 | Object.assign(globalThis, { 14 | TMP: `${GLib.get_tmp_dir()}/greeter`, 15 | OPTIONS: "/var/cache/greeter/options.json", 16 | WALLPAPER: "/var/cache/greeter/background", 17 | // TMP: "/tmp/ags", 18 | // OPTIONS: Utils.CACHE_DIR + "/options.json", 19 | // WALLPAPER: Utils.HOME + "/.config/background", 20 | USER: userName, 21 | }) 22 | 23 | Utils.ensureDirectory(TMP) 24 | -------------------------------------------------------------------------------- /config/ags/greeter/statusbar.ts: -------------------------------------------------------------------------------- 1 | import { clock } from "lib/variables" 2 | import options from "options" 3 | import icons from "lib/icons" 4 | import BatteryBar from "widget/bar/buttons/BatteryBar" 5 | import PanelButton from "widget/bar/PanelButton" 6 | 7 | const { scheme } = options.theme 8 | const { monochrome } = options.bar.powermenu 9 | const { format } = options.bar.date 10 | 11 | const poweroff = PanelButton({ 12 | class_name: "powermenu", 13 | child: Widget.Icon(icons.powermenu.shutdown), 14 | on_clicked: () => Utils.exec("shutdown now"), 15 | setup: self => self.hook(monochrome, () => { 16 | self.toggleClassName("colored", !monochrome.value) 17 | self.toggleClassName("box") 18 | }), 19 | }) 20 | 21 | const date = PanelButton({ 22 | class_name: "date", 23 | child: Widget.Label({ 24 | label: clock.bind().as(c => c.format(`${format}`)!), 25 | }), 26 | }) 27 | 28 | const darkmode = PanelButton({ 29 | class_name: "darkmode", 30 | child: Widget.Icon({ icon: scheme.bind().as(s => icons.color[s]) }), 31 | on_clicked: () => scheme.value = scheme.value === "dark" ? "light" : "dark", 32 | }) 33 | 34 | export default Widget.CenterBox({ 35 | class_name: "bar", 36 | hexpand: true, 37 | center_widget: date, 38 | end_widget: Widget.Box({ 39 | hpack: "end", 40 | children: [ 41 | darkmode, 42 | BatteryBar(), 43 | poweroff, 44 | ], 45 | }), 46 | }) 47 | -------------------------------------------------------------------------------- /config/ags/lib/battery.ts: -------------------------------------------------------------------------------- 1 | import icons from "./icons" 2 | 3 | export default async function init() { 4 | const bat = await Service.import("battery") 5 | bat.connect("notify::percent", ({ percent, charging }) => { 6 | const low = 30 7 | if (percent !== low || percent !== low / 2 || !charging) 8 | return 9 | 10 | Utils.notify({ 11 | summary: `${percent}% Battery Percentage`, 12 | iconName: icons.battery.warning, 13 | urgency: "critical", 14 | }) 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /config/ags/lib/gtk.ts: -------------------------------------------------------------------------------- 1 | import Gio from "gi://Gio" 2 | import options from "options" 3 | 4 | const settings = new Gio.Settings({ 5 | schema: "org.gnome.desktop.interface", 6 | }) 7 | 8 | function gtk() { 9 | const scheme = options.theme.scheme.value 10 | settings.set_string("color-scheme", `prefer-${scheme}`) 11 | } 12 | 13 | export default function init() { 14 | options.theme.scheme.connect("changed", gtk) 15 | gtk() 16 | } 17 | -------------------------------------------------------------------------------- /config/ags/lib/hyprland.ts: -------------------------------------------------------------------------------- 1 | import options from "options" 2 | const { messageAsync } = await Service.import("hyprland") 3 | 4 | const { 5 | hyprland, 6 | theme: { 7 | spacing, 8 | radius, 9 | border: { width }, 10 | blur, 11 | shadows, 12 | dark: { 13 | primary: { bg: darkActive }, 14 | }, 15 | light: { 16 | primary: { bg: lightActive }, 17 | }, 18 | scheme, 19 | }, 20 | } = options 21 | 22 | const deps = [ 23 | "hyprland", 24 | spacing.id, 25 | radius.id, 26 | blur.id, 27 | width.id, 28 | shadows.id, 29 | darkActive.id, 30 | lightActive.id, 31 | scheme.id, 32 | ] 33 | 34 | function primary() { 35 | return scheme.value === "dark" 36 | ? darkActive.value 37 | : lightActive.value 38 | } 39 | 40 | function rgba(color: string) { 41 | return `rgba(${color}ff)`.replace("#", "") 42 | } 43 | 44 | function sendBatch(batch: string[]) { 45 | const cmd = batch 46 | .filter(x => !!x) 47 | .map(x => `keyword ${x}`) 48 | .join("; ") 49 | 50 | return messageAsync(`[[BATCH]]/${cmd}`) 51 | } 52 | 53 | async function setupHyprland() { 54 | const wm_gaps = Math.floor(hyprland.gaps.value * spacing.value) 55 | 56 | sendBatch([ 57 | `general:border_size ${width}`, 58 | `general:gaps_out ${wm_gaps}`, 59 | `general:gaps_in ${Math.floor(wm_gaps / 2)}`, 60 | `general:col.active_border ${rgba(primary())}`, 61 | `general:col.inactive_border ${rgba(hyprland.inactiveBorder.value)}`, 62 | `decoration:rounding ${radius}`, 63 | `decoration:drop_shadow ${shadows.value ? "yes" : "no"}`, 64 | `dwindle:no_gaps_when_only ${hyprland.gapsWhenOnly.value ? 0 : 1}`, 65 | `master:no_gaps_when_only ${hyprland.gapsWhenOnly.value ? 0 : 1}`, 66 | ]) 67 | 68 | await sendBatch(App.windows.map(({ name }) => `layerrule unset, ${name}`)) 69 | 70 | if (blur.value > 0) { 71 | sendBatch(App.windows.flatMap(({ name }) => [ 72 | `layerrule unset, ${name}`, 73 | `layerrule blur, ${name}`, 74 | `layerrule ignorealpha ${/* based on shadow color */.29}, ${name}`, 75 | ])) 76 | } 77 | } 78 | 79 | export default function init() { 80 | options.handler(deps, setupHyprland) 81 | setupHyprland() 82 | } 83 | -------------------------------------------------------------------------------- /config/ags/lib/init.ts: -------------------------------------------------------------------------------- 1 | import matugen from "./matugen" 2 | import hyprland from "./hyprland" 3 | import tmux from "./tmux" 4 | import gtk from "./gtk" 5 | import lowBattery from "./battery" 6 | import notifications from "./notifications" 7 | 8 | export default function init() { 9 | try { 10 | gtk() 11 | tmux() 12 | matugen() 13 | lowBattery() 14 | notifications() 15 | hyprland() 16 | } catch (error) { 17 | logError(error) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /config/ags/lib/notifications.ts: -------------------------------------------------------------------------------- 1 | import options from "options" 2 | const notifs = await Service.import("notifications") 3 | 4 | // TODO: consider adding this to upstream 5 | 6 | const { blacklist } = options.notifications 7 | 8 | export default function init() { 9 | const notify = notifs.constructor.prototype.Notify.bind(notifs) 10 | notifs.constructor.prototype.Notify = function(appName: string, ...rest: unknown[]) { 11 | if (blacklist.value.includes(appName)) 12 | return Number.MAX_SAFE_INTEGER 13 | 14 | return notify(appName, ...rest) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /config/ags/lib/session.ts: -------------------------------------------------------------------------------- 1 | import GLib from "gi://GLib?version=2.0" 2 | 3 | declare global { 4 | const OPTIONS: string 5 | const TMP: string 6 | const USER: string 7 | } 8 | 9 | Object.assign(globalThis, { 10 | OPTIONS: `${GLib.get_user_cache_dir()}/ags/options.json`, 11 | TMP: `${GLib.get_tmp_dir()}/asztal`, 12 | USER: GLib.get_user_name(), 13 | }) 14 | 15 | Utils.ensureDirectory(TMP) 16 | App.addIcons(`${App.configDir}/assets`) 17 | -------------------------------------------------------------------------------- /config/ags/lib/tmux.ts: -------------------------------------------------------------------------------- 1 | import options from "options" 2 | import { sh } from "./utils" 3 | 4 | export async function tmux() { 5 | const { scheme, dark, light } = options.theme 6 | const hex = scheme.value === "dark" ? dark.primary.bg.value : light.primary.bg.value 7 | if (await sh("which tmux").catch(() => false)) 8 | sh(`tmux set @main_accent "${hex}"`) 9 | } 10 | 11 | export default function init() { 12 | options.theme.dark.primary.bg.connect("changed", tmux) 13 | options.theme.light.primary.bg.connect("changed", tmux) 14 | } 15 | -------------------------------------------------------------------------------- /config/ags/lib/variables.ts: -------------------------------------------------------------------------------- 1 | import GLib from "gi://GLib" 2 | // import options from "options" 3 | // 4 | // const intval = options.system.fetchInterval.value 5 | // const tempPath = options.system.temperature.value 6 | 7 | export const clock = Variable(GLib.DateTime.new_now_local(), { 8 | poll: [1000, () => GLib.DateTime.new_now_local()], 9 | }) 10 | 11 | export const uptime = Variable(0, { 12 | poll: [60_000, "cat /proc/uptime", line => 13 | Number.parseInt(line.split(".")[0]) / 60, 14 | ], 15 | }) 16 | 17 | export const distro = { 18 | id: GLib.get_os_info("ID"), 19 | logo: GLib.get_os_info("LOGO"), 20 | } 21 | 22 | // const divide = ([total, free]: string[]) => Number.parseInt(free) / Number.parseInt(total) 23 | // 24 | // export const cpu = Variable(0, { 25 | // poll: [intval, "top -b -n 1", out => divide(["100", out.split("\n") 26 | // .find(line => line.includes("Cpu(s)")) 27 | // ?.split(/\s+/)[1] 28 | // .replace(",", ".") || "0"])], 29 | // }) 30 | // 31 | // export const ram = Variable(0, { 32 | // poll: [intval, "free", out => divide(out.split("\n") 33 | // .find(line => line.includes("Mem:")) 34 | // ?.split(/\s+/) 35 | // .splice(1, 2) || ["1", "1"])], 36 | // }) 37 | // 38 | // export const temperature = Variable(0, { 39 | // poll: [intval, `cat ${tempPath}`, n => { 40 | // return Number.parseInt(n) / 100_000 41 | // }], 42 | // }) 43 | -------------------------------------------------------------------------------- /config/ags/main.ts: -------------------------------------------------------------------------------- 1 | import "lib/session" 2 | import "style/style" 3 | import init from "lib/init" 4 | import options from "options" 5 | import Bar from "widget/bar/Bar" 6 | import Launcher from "widget/launcher/Launcher" 7 | import NotificationPopups from "widget/notifications/NotificationPopups" 8 | import OSD from "widget/osd/OSD" 9 | import Overview from "widget/overview/Overview" 10 | import PowerMenu from "widget/powermenu/PowerMenu" 11 | import ScreenCorners from "widget/bar/ScreenCorners" 12 | import SettingsDialog from "widget/settings/SettingsDialog" 13 | import Verification from "widget/powermenu/Verification" 14 | import { forMonitors } from "lib/utils" 15 | import { setupQuickSettings } from "widget/quicksettings/QuickSettings" 16 | import { setupDateMenu } from "widget/datemenu/DateMenu" 17 | 18 | App.config({ 19 | onConfigParsed: () => { 20 | setupQuickSettings() 21 | setupDateMenu() 22 | init() 23 | }, 24 | closeWindowDelay: { 25 | "launcher": options.transition.value, 26 | "overview": options.transition.value, 27 | "quicksettings": options.transition.value, 28 | "datemenu": options.transition.value, 29 | }, 30 | windows: () => [ 31 | ...forMonitors(Bar), 32 | ...forMonitors(NotificationPopups), 33 | ...forMonitors(ScreenCorners), 34 | ...forMonitors(OSD), 35 | Launcher(), 36 | Overview(), 37 | PowerMenu(), 38 | SettingsDialog(), 39 | Verification(), 40 | ], 41 | }) 42 | -------------------------------------------------------------------------------- /config/ags/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ags-dotfiles", 3 | "author": "Aylur", 4 | "kofi": "https://ko-fi.com/aylur", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/Aylur/dotfiles.git" 8 | }, 9 | "devDependencies": { 10 | "@girs/accountsservice-1.0": "^1.0.0-3.2.7", 11 | "@typescript-eslint/eslint-plugin": "^6.20.0", 12 | "eslint": "^8.56.0", 13 | "eslint-config-standard-with-typescript": "^43.0.1", 14 | "eslint-plugin-import": "^2.29.1", 15 | "eslint-plugin-n": "^16.6.2", 16 | "eslint-plugin-promise": "^6.1.1", 17 | "typescript": "^5.3.3" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /config/ags/service/asusctl.ts: -------------------------------------------------------------------------------- 1 | import { sh } from "lib/utils" 2 | 3 | type Profile = "Performance" | "Balanced" | "Quiet" 4 | type Mode = "Hybrid" | "Integrated" 5 | 6 | class Asusctl extends Service { 7 | static { 8 | Service.register(this, {}, { 9 | "profile": ["string", "r"], 10 | "mode": ["string", "r"], 11 | }) 12 | } 13 | 14 | get available() { 15 | return Utils.exec("which asusctl", () => true, () => false) 16 | } 17 | 18 | #profile: Profile = "Balanced" 19 | #mode: Mode = "Hybrid" 20 | 21 | async nextProfile() { 22 | await sh("asusctl profile -n") 23 | const profile = await sh("asusctl profile -p") 24 | const p = profile.split(" ")[3] as Profile 25 | this.#profile = p 26 | this.changed("profile") 27 | } 28 | 29 | async setProfile(prof: Profile) { 30 | await sh(`asusctl profile --profile-set ${prof}`) 31 | this.#profile = prof 32 | this.changed("profile") 33 | } 34 | 35 | async nextMode() { 36 | await sh(`supergfxctl -m ${this.#mode === "Hybrid" ? "Integrated" : "Hybrid"}`) 37 | this.#mode = await sh("supergfxctl -g") as Mode 38 | this.changed("profile") 39 | } 40 | 41 | constructor() { 42 | super() 43 | 44 | if (this.available) { 45 | sh("asusctl profile -p").then(p => this.#profile = p.split(" ")[3] as Profile) 46 | sh("supergfxctl -g").then(m => this.#mode = m as Mode) 47 | } 48 | } 49 | 50 | get profiles(): Profile[] { return ["Performance", "Balanced", "Quiet"] } 51 | get profile() { return this.#profile } 52 | get mode() { return this.#mode } 53 | } 54 | 55 | export default new Asusctl 56 | -------------------------------------------------------------------------------- /config/ags/service/brightness.ts: -------------------------------------------------------------------------------- 1 | import { bash, dependencies, sh } from "lib/utils" 2 | 3 | if (!dependencies("brightnessctl")) 4 | App.quit() 5 | 6 | const get = (args: string) => Number(Utils.exec(`brightnessctl ${args}`)) 7 | const screen = await bash`ls -w1 /sys/class/backlight | head -1` 8 | const kbd = await bash`ls -w1 /sys/class/leds | head -1` 9 | 10 | class Brightness extends Service { 11 | static { 12 | Service.register(this, {}, { 13 | "screen": ["float", "rw"], 14 | "kbd": ["int", "rw"], 15 | }) 16 | } 17 | 18 | #kbdMax = get(`--device ${kbd} max`) 19 | #kbd = get(`--device ${kbd} get`) 20 | #screenMax = get("max") 21 | #screen = get("get") / (get("max") || 1) 22 | 23 | get kbd() { return this.#kbd } 24 | get screen() { return this.#screen } 25 | 26 | set kbd(value) { 27 | if (value < 0 || value > this.#kbdMax) 28 | return 29 | 30 | sh(`brightnessctl -d ${kbd} s ${value} -q`).then(() => { 31 | this.#kbd = value 32 | this.changed("kbd") 33 | }) 34 | } 35 | 36 | set screen(percent) { 37 | if (percent < 0) 38 | percent = 0 39 | 40 | if (percent > 1) 41 | percent = 1 42 | 43 | sh(`brightnessctl set ${Math.floor(percent * 100)}% -q`).then(() => { 44 | this.#screen = percent 45 | this.changed("screen") 46 | }) 47 | } 48 | 49 | constructor() { 50 | super() 51 | 52 | const screenPath = `/sys/class/backlight/${screen}/brightness` 53 | const kbdPath = `/sys/class/leds/${kbd}/brightness` 54 | 55 | Utils.monitorFile(screenPath, async f => { 56 | const v = await Utils.readFileAsync(f) 57 | this.#screen = Number(v) / this.#screenMax 58 | this.changed("screen") 59 | }) 60 | 61 | Utils.monitorFile(kbdPath, async f => { 62 | const v = await Utils.readFileAsync(f) 63 | this.#kbd = Number(v) / this.#kbdMax 64 | this.changed("kbd") 65 | }) 66 | } 67 | } 68 | 69 | export default new Brightness 70 | -------------------------------------------------------------------------------- /config/ags/service/colorpicker.ts: -------------------------------------------------------------------------------- 1 | import icons from "lib/icons" 2 | import { bash, dependencies } from "lib/utils" 3 | 4 | const COLORS_CACHE = Utils.CACHE_DIR + "/colorpicker.json" 5 | const MAX_NUM_COLORS = 10 6 | 7 | class ColorPicker extends Service { 8 | static { 9 | Service.register(this, {}, { 10 | "colors": ["jsobject"], 11 | }) 12 | } 13 | 14 | #notifID = 0 15 | #colors = JSON.parse(Utils.readFile(COLORS_CACHE) || "[]") as string[] 16 | 17 | get colors() { return [...this.#colors] } 18 | set colors(colors) { 19 | this.#colors = colors 20 | this.changed("colors") 21 | } 22 | 23 | // TODO: doesn't work? 24 | async wlCopy(color: string) { 25 | if (dependencies("wl-copy")) 26 | bash(`wl-copy ${color}`) 27 | } 28 | 29 | readonly pick = async () => { 30 | if (!dependencies("hyprpicker")) 31 | return 32 | 33 | const color = await bash("hyprpicker -a -r") 34 | if (!color) 35 | return 36 | 37 | this.wlCopy(color) 38 | const list = this.colors 39 | if (!list.includes(color)) { 40 | list.push(color) 41 | if (list.length > MAX_NUM_COLORS) 42 | list.shift() 43 | 44 | this.colors = list 45 | Utils.writeFile(JSON.stringify(list, null, 2), COLORS_CACHE) 46 | } 47 | 48 | this.#notifID = await Utils.notify({ 49 | id: this.#notifID, 50 | iconName: icons.ui.colorpicker, 51 | summary: color, 52 | }) 53 | } 54 | } 55 | 56 | export default new ColorPicker 57 | -------------------------------------------------------------------------------- /config/ags/service/nix.ts: -------------------------------------------------------------------------------- 1 | import icons from "lib/icons" 2 | import { bash, dependencies } from "lib/utils" 3 | import options from "options" 4 | 5 | const CACHE = `${Utils.CACHE_DIR}/nixpkgs` 6 | const PREFIX = "legacyPackages.x86_64-linux." 7 | const MAX = options.launcher.nix.max 8 | const nixpkgs = options.launcher.nix.pkgs 9 | 10 | export type Nixpkg = { 11 | name: string 12 | description: string 13 | pname: string 14 | version: string 15 | } 16 | 17 | class Nix extends Service { 18 | static { 19 | Service.register(this, {}, { 20 | "available": ["boolean", "r"], 21 | "ready": ["boolean", "rw"], 22 | }) 23 | } 24 | 25 | #db: { [name: string]: Nixpkg } = {} 26 | #ready = true 27 | 28 | private set ready(r: boolean) { 29 | this.#ready = r 30 | this.changed("ready") 31 | } 32 | 33 | get db() { return this.#db } 34 | get ready() { return this.#ready } 35 | get available() { 36 | return Utils.exec("which nix", () => true, () => false) 37 | } 38 | 39 | constructor() { 40 | super() 41 | if (!this.available) 42 | return this 43 | 44 | this.#updateList() 45 | nixpkgs.connect("changed", this.#updateList) 46 | } 47 | 48 | query = async (filter: string) => { 49 | if (!dependencies("fzf", "nix") || !this.#ready) 50 | return [] as string[] 51 | 52 | return bash(`cat ${CACHE} | fzf -f ${filter} -e | head -n ${MAX} `) 53 | .then(str => str.split("\n").filter(i => i)) 54 | } 55 | 56 | nix(cmd: string, bin: string, args: string) { 57 | return Utils.execAsync(`nix ${cmd} ${nixpkgs}#${bin} --impure ${args}`) 58 | } 59 | 60 | run = async (input: string) => { 61 | if (!dependencies("nix")) 62 | return 63 | 64 | try { 65 | const [bin, ...args] = input.trim().split(/\s+/) 66 | 67 | this.ready = false 68 | await this.nix("shell", bin, "--command sh -c 'exit'") 69 | this.ready = true 70 | 71 | this.nix("run", bin, ["--", ...args].join(" ")) 72 | } catch (err) { 73 | if (typeof err === "string") 74 | Utils.notify("NixRun Error", err, icons.nix.nix) 75 | else 76 | logError(err) 77 | } finally { 78 | this.ready = true 79 | } 80 | } 81 | 82 | #updateList = async () => { 83 | if (!dependencies("nix")) 84 | return 85 | 86 | this.ready = false 87 | this.#db = {} 88 | 89 | const search = await bash(`nix search ${nixpkgs} --json`) 90 | if (!search) { 91 | this.ready = true 92 | return 93 | } 94 | 95 | const json = Object.entries(JSON.parse(search) as { 96 | [name: string]: Nixpkg 97 | }) 98 | 99 | for (const [pkg, info] of json) { 100 | const name = pkg.replace(PREFIX, "") 101 | this.#db[name] = { ...info, name } 102 | } 103 | 104 | const list = Object.keys(this.#db).join("\n") 105 | await Utils.writeFile(list, CACHE) 106 | this.ready = true 107 | } 108 | } 109 | 110 | export default new Nix 111 | -------------------------------------------------------------------------------- /config/ags/service/powermenu.ts: -------------------------------------------------------------------------------- 1 | import options from "options" 2 | 3 | const { sleep, reboot, logout, shutdown } = options.powermenu 4 | 5 | export type Action = "sleep" | "reboot" | "logout" | "shutdown" 6 | 7 | class PowerMenu extends Service { 8 | static { 9 | Service.register(this, {}, { 10 | "title": ["string"], 11 | "cmd": ["string"], 12 | }) 13 | } 14 | 15 | #title = "" 16 | #cmd = "" 17 | 18 | get title() { return this.#title } 19 | 20 | action(action: Action) { 21 | [this.#cmd, this.#title] = { 22 | sleep: [sleep.value, "Sleep"], 23 | reboot: [reboot.value, "Reboot"], 24 | logout: [logout.value, "Log Out"], 25 | shutdown: [shutdown.value, "Shutdown"], 26 | }[action] 27 | 28 | this.notify("cmd") 29 | this.notify("title") 30 | this.emit("changed") 31 | App.closeWindow("powermenu") 32 | App.openWindow("verification") 33 | } 34 | 35 | readonly shutdown = () => { 36 | this.action("shutdown") 37 | } 38 | 39 | readonly exec = () => { 40 | App.closeWindow("verification") 41 | Utils.exec(this.#cmd) 42 | } 43 | } 44 | 45 | const powermenu = new PowerMenu 46 | Object.assign(globalThis, { powermenu }) 47 | export default powermenu 48 | -------------------------------------------------------------------------------- /config/ags/service/screenrecord.ts: -------------------------------------------------------------------------------- 1 | import GLib from "gi://GLib" 2 | import icons from "lib/icons" 3 | import { dependencies, sh, bash } from "lib/utils" 4 | 5 | const now = () => GLib.DateTime.new_now_local().format("%Y-%m-%d_%H-%M-%S") 6 | 7 | class Recorder extends Service { 8 | static { 9 | Service.register(this, {}, { 10 | "timer": ["int"], 11 | "recording": ["boolean"], 12 | }) 13 | } 14 | 15 | #recordings = Utils.HOME + "/Videos/Screencasting" 16 | #screenshots = Utils.HOME + "/Pictures/Screenshots" 17 | #file = "" 18 | #interval = 0 19 | 20 | recording = false 21 | timer = 0 22 | 23 | async start() { 24 | if (!dependencies("slurp", "wf-recorder")) 25 | return 26 | 27 | if (this.recording) 28 | return 29 | 30 | Utils.ensureDirectory(this.#recordings) 31 | this.#file = `${this.#recordings}/${now()}.mp4` 32 | sh(`wf-recorder -g "${await sh("slurp")}" -f ${this.#file} --pixel-format yuv420p`) 33 | 34 | this.recording = true 35 | this.changed("recording") 36 | 37 | this.timer = 0 38 | this.#interval = Utils.interval(1000, () => { 39 | this.changed("timer") 40 | this.timer++ 41 | }) 42 | } 43 | 44 | async stop() { 45 | if (!this.recording) 46 | return 47 | 48 | await bash("killall -INT wf-recorder") 49 | this.recording = false 50 | this.changed("recording") 51 | GLib.source_remove(this.#interval) 52 | 53 | Utils.notify({ 54 | iconName: icons.fallback.video, 55 | summary: "Screenrecord", 56 | body: this.#file, 57 | actions: { 58 | "Show in Files": () => sh(`xdg-open ${this.#recordings}`), 59 | "View": () => sh(`xdg-open ${this.#file}`), 60 | }, 61 | }) 62 | } 63 | 64 | async screenshot(full = false) { 65 | if (!dependencies("slurp", "wayshot")) 66 | return 67 | 68 | const file = `${this.#screenshots}/${now()}.png` 69 | Utils.ensureDirectory(this.#screenshots) 70 | 71 | if (full) { 72 | await sh(`wayshot -f ${file}`) 73 | } 74 | else { 75 | const size = await sh("slurp") 76 | if (!size) 77 | return 78 | 79 | await sh(`wayshot -f ${file} -s "${size}"`) 80 | } 81 | 82 | bash(`wl-copy < ${file}`) 83 | 84 | Utils.notify({ 85 | image: file, 86 | summary: "Screenshot", 87 | body: file, 88 | actions: { 89 | "Show in Files": () => sh(`xdg-open ${this.#screenshots}`), 90 | "View": () => sh(`xdg-open ${file}`), 91 | "Edit": () => { 92 | if (dependencies("swappy")) 93 | sh(`swappy -f ${file}`) 94 | }, 95 | }, 96 | }) 97 | } 98 | } 99 | 100 | const recorder = new Recorder 101 | Object.assign(globalThis, { recorder }) 102 | export default recorder 103 | -------------------------------------------------------------------------------- /config/ags/service/sh.ts: -------------------------------------------------------------------------------- 1 | import GLib from "gi://GLib?version=2.0" 2 | import { bash, dependencies } from "lib/utils" 3 | import icons from "lib/icons" 4 | import options from "options" 5 | 6 | const MAX = options.launcher.sh.max 7 | const BINS = `${Utils.CACHE_DIR}/binaries` 8 | 9 | async function ls(path: string) { 10 | return Utils.execAsync(`ls ${path}`).catch(() => "") 11 | } 12 | 13 | async function reload() { 14 | const bins = await Promise.all(GLib.getenv("PATH")! 15 | .split(":") 16 | .map(ls)) 17 | 18 | Utils.writeFile(bins.join("\n"), BINS) 19 | } 20 | 21 | async function query(filter: string) { 22 | if (!dependencies("fzf")) 23 | return [] as string[] 24 | 25 | return bash(`cat ${BINS} | fzf -f ${filter} | head -n ${MAX}`) 26 | .then(str => Array.from(new Set(str.split("\n").filter(i => i)).values())) 27 | .catch(err => { print(err); return [] }) 28 | } 29 | 30 | function run(args: string) { 31 | Utils.execAsync(args) 32 | .then(out => { 33 | print(`:sh ${args.trim()}:`) 34 | print(out) 35 | }) 36 | .catch(err => { 37 | Utils.notify("ShRun Error", err, icons.app.terminal) 38 | }) 39 | } 40 | 41 | class Sh extends Service { 42 | static { Service.register(this) } 43 | constructor() { super(); reload() } 44 | query = query 45 | run = run 46 | } 47 | 48 | export default new Sh 49 | -------------------------------------------------------------------------------- /config/ags/service/wallpaper.ts: -------------------------------------------------------------------------------- 1 | import options from "options"; 2 | import { dependencies, sh} from "lib/utils"; 3 | 4 | export type Resolution = 1920 | 1366 | 3840; 5 | export type Market = 6 | | "random" 7 | | "en-US" 8 | | "ja-JP" 9 | | "en-AU" 10 | | "en-GB" 11 | | "de-DE" 12 | | "en-NZ" 13 | | "en-CA"; 14 | 15 | const WP = `${Utils.HOME}/.config/background`; 16 | const Cache = `${Utils.HOME}/Pictures/Wallpapers/Bing`; 17 | 18 | class Wallpaper extends Service { 19 | static { 20 | Service.register(this, {}, { 21 | "wallpaper": ["string"], 22 | }); 23 | } 24 | 25 | #blockMonitor = false; 26 | 27 | async #setWallpaper(path: string) { 28 | this.#blockMonitor = true; 29 | 30 | await sh(`cp ${path} ${WP}`); 31 | await this.#wallpaper(); 32 | 33 | if (dependencies("wal")) { 34 | await sh("wal -i " + path); 35 | } 36 | 37 | this.#blockMonitor = false; 38 | } 39 | 40 | async #wallpaper() { 41 | if (!dependencies("swww")) return; 42 | 43 | const pos = await sh("hyprctl cursorpos"); 44 | await sh([ 45 | "swww", 46 | "img", 47 | "--transition-type", 48 | "grow", 49 | "--transition-pos", 50 | pos.replace(" ", ""), 51 | WP, 52 | ]); 53 | this.changed("wallpaper"); 54 | } 55 | 56 | async #fetchBing() { 57 | const res = await Utils.fetch("https://bing.biturl.top/", { 58 | params: { 59 | resolution: options.wallpaper.resolution.value, 60 | format: "json", 61 | image_format: "jpg", 62 | index: "random", 63 | mkt: options.wallpaper.market.value, 64 | }, 65 | }).then((res) => res.text()); 66 | 67 | if (!res.startsWith("{")) { 68 | console.warn("bing api", res); 69 | return; 70 | } 71 | 72 | const { url } = JSON.parse(res); 73 | const file = `${Cache}/${url.replace("https://www.bing.com/th?id=", "")}`; 74 | 75 | if (dependencies("curl")) { 76 | Utils.ensureDirectory(Cache); 77 | await sh(`curl "${url}" --output ${file}`); 78 | await this.#setWallpaper(file); 79 | } 80 | } 81 | 82 | readonly random = () => { 83 | this.#fetchBing(); 84 | }; 85 | 86 | readonly set = (path: string) => { 87 | this.#setWallpaper(path); 88 | }; 89 | 90 | get wallpaper() { 91 | return WP; 92 | } 93 | 94 | constructor() { 95 | super(); 96 | 97 | if (!dependencies("swww")) return this; 98 | 99 | // gtk portal 100 | Utils.monitorFile(WP, () => { 101 | if (!this.#blockMonitor) { 102 | this.#wallpaper(); 103 | } 104 | }); 105 | 106 | Utils.execAsync("swww-daemon") 107 | .then(this.#wallpaper) 108 | .catch(() => null); 109 | } 110 | } 111 | 112 | export default new Wallpaper(); -------------------------------------------------------------------------------- /config/ags/service/weather.ts: -------------------------------------------------------------------------------- 1 | import options from "options" 2 | 3 | const { interval, key, cities, unit } = options.datemenu.weather 4 | 5 | class Weather extends Service { 6 | static { 7 | Service.register(this, {}, { 8 | "forecasts": ["jsobject"], 9 | }) 10 | } 11 | 12 | #forecasts: Forecast[] = [] 13 | get forecasts() { return this.#forecasts } 14 | 15 | async #fetch(placeid: number) { 16 | const url = "https://api.openweathermap.org/data/2.5/forecast" 17 | const res = await Utils.fetch(url, { 18 | params: { 19 | id: placeid, 20 | appid: key.value, 21 | untis: unit.value, 22 | }, 23 | }) 24 | return await res.json() 25 | } 26 | 27 | constructor() { 28 | super() 29 | if (!key.value) 30 | return this 31 | 32 | Utils.interval(interval.value, () => { 33 | Promise.all(cities.value.map(this.#fetch)).then(forecasts => { 34 | this.#forecasts = forecasts as Forecast[] 35 | this.changed("forecasts") 36 | }) 37 | }) 38 | } 39 | } 40 | 41 | export default new Weather 42 | 43 | type Forecast = { 44 | city: { 45 | name: string, 46 | } 47 | list: Array<{ 48 | dt: number 49 | main: { 50 | temp: number 51 | feels_like: number 52 | }, 53 | weather: Array<{ 54 | main: string, 55 | description: string, 56 | icon: string, 57 | }> 58 | }> 59 | } 60 | -------------------------------------------------------------------------------- /config/ags/style/extra.scss: -------------------------------------------------------------------------------- 1 | @import './mixins/button.scss'; 2 | 3 | * { 4 | font-size: $font-size; 5 | font-family: $font-name; 6 | } 7 | 8 | separator { 9 | &.horizontal { 10 | min-height: $border-width; 11 | } 12 | 13 | &.vertical { 14 | min-width: $border-width; 15 | } 16 | } 17 | 18 | window.popup { 19 | >* { 20 | border: none; 21 | box-shadow: none; 22 | } 23 | 24 | menu { 25 | border-radius: $popover-radius; 26 | background-color: $bg; 27 | padding: $popover-padding; 28 | border: $border-width solid $popover-border-color; 29 | 30 | separator { 31 | background-color: $border-color; 32 | } 33 | 34 | menuitem { 35 | @include button; 36 | padding: $spacing * .5; 37 | margin: ($spacing * .5) 0; 38 | 39 | &:first-child { 40 | margin-top: 0; 41 | } 42 | 43 | &:last-child { 44 | margin-bottom: 0; 45 | } 46 | } 47 | } 48 | } 49 | 50 | tooltip { 51 | * { 52 | all: unset; 53 | } 54 | 55 | background-color: transparent; 56 | border: none; 57 | 58 | >*>* { 59 | background-color: $bg; 60 | border-radius: $radius; 61 | border: $border-width solid $popover-border-color; 62 | color: $fg; 63 | padding: 8px; 64 | margin: 4px; 65 | box-shadow: 0 0 3px 0 $shadow-color; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /config/ags/style/mixins/a11y-button.scss: -------------------------------------------------------------------------------- 1 | @import './button'; 2 | 3 | @mixin accs-button($flat: false, $reactive: true) { 4 | @include unset; 5 | color: $fg; 6 | 7 | >* { 8 | border-radius: $radius; 9 | transition: $transition; 10 | 11 | @if $flat { 12 | background-color: transparent; 13 | box-shadow: none; 14 | } 15 | 16 | @else { 17 | background-color: $widget-bg; 18 | box-shadow: inset 0 0 0 $border-width $border-color; 19 | } 20 | } 21 | 22 | 23 | @if $reactive { 24 | 25 | &:focus>*, 26 | &.focused>* { 27 | @include button-focus; 28 | } 29 | 30 | &:hover>* { 31 | @include button-hover; 32 | } 33 | 34 | &:active, 35 | &.active, 36 | &.on, 37 | &:checked { 38 | >* { 39 | @include button-active; 40 | } 41 | 42 | &:hover>* { 43 | box-shadow: inset 0 0 0 $border-width $border-color, 44 | inset 0 0 0 99px $hover-bg; 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /config/ags/style/mixins/button.scss: -------------------------------------------------------------------------------- 1 | @mixin button-focus() { 2 | box-shadow: inset 0 0 0 $border-width $primary-bg; 3 | background-color: $hover-bg; 4 | color: $hover-fg; 5 | } 6 | 7 | @mixin button-hover() { 8 | box-shadow: inset 0 0 0 $border-width $border-color; 9 | background-color: $hover-bg; 10 | color: $hover-fg; 11 | } 12 | 13 | @mixin button-active() { 14 | box-shadow: inset 0 0 0 $border-width $border-color; 15 | background-image: $active-gradient; 16 | background-color: $primary-bg; 17 | color: $primary-fg; 18 | } 19 | 20 | @mixin button-disabled() { 21 | box-shadow: none; 22 | background-color: transparent; 23 | color: transparentize($fg, 0.7); 24 | } 25 | 26 | @mixin button($flat: false, $reactive: true, $radius: $radius, $focusable: true) { 27 | all: unset; 28 | transition: $transition; 29 | border-radius: $radius; 30 | color: $fg; 31 | 32 | @if $flat { 33 | background-color: transparent; 34 | background-image: none; 35 | box-shadow: none; 36 | } 37 | 38 | @else { 39 | background-color: $widget-bg; 40 | box-shadow: inset 0 0 0 $border-width $border-color; 41 | } 42 | 43 | @if $reactive { 44 | @if $focusable { 45 | &:focus { 46 | @include button-focus; 47 | } 48 | } 49 | 50 | &:hover { 51 | @include button-hover; 52 | } 53 | 54 | &:active, 55 | &.on, 56 | &.active, 57 | &:checked { 58 | @include button-active; 59 | 60 | &:hover { 61 | box-shadow: inset 0 0 0 $border-width $border-color, 62 | inset 0 0 0 99px $hover-bg; 63 | } 64 | } 65 | } 66 | 67 | &:disabled { 68 | @include button-disabled; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /config/ags/style/mixins/floating-widget.scss: -------------------------------------------------------------------------------- 1 | @mixin floating-widget { 2 | @if $shadows { 3 | box-shadow: 0 0 5px 0 $shadow-color; 4 | } 5 | 6 | margin: max($spacing, 8px); 7 | border: $border-width solid $popover-border-color; 8 | background-color: $bg; 9 | color: $fg; 10 | border-radius: $popover-radius; 11 | padding: $popover-padding; 12 | } 13 | -------------------------------------------------------------------------------- /config/ags/style/mixins/hidden.scss: -------------------------------------------------------------------------------- 1 | @mixin hidden { 2 | background-color: transparent; 3 | background-image: none; 4 | border-color: transparent; 5 | box-shadow: none; 6 | -gtk-icon-transform: scale(0); 7 | 8 | * { 9 | background-color: transparent; 10 | background-image: none; 11 | border-color: transparent; 12 | box-shadow: none; 13 | -gtk-icon-transform: scale(0); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /config/ags/style/mixins/media.scss: -------------------------------------------------------------------------------- 1 | @mixin media() { 2 | @include widget; 3 | padding: $padding; 4 | 5 | .cover { 6 | @if $shadows { 7 | box-shadow: 2px 2px 2px 0 $shadow-color; 8 | } 9 | 10 | background-size: cover; 11 | background-position: center; 12 | border-radius: $radius*0.8; 13 | margin-right: $spacing; 14 | } 15 | 16 | button { 17 | @include button($flat: true); 18 | padding: $padding * .5; 19 | 20 | &.play-pause { 21 | margin: 0 ($spacing * .5); 22 | } 23 | 24 | image { 25 | font-size: 1.2em; 26 | } 27 | } 28 | 29 | .artist { 30 | color: transparentize($fg, .2); 31 | font-size: .9em; 32 | } 33 | 34 | scale { 35 | @include slider($width: .5em, $slider: false, $gradient: linear-gradient($fg, $fg)); 36 | margin-bottom: $padding * .5; 37 | 38 | trough { 39 | border: none; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /config/ags/style/mixins/scrollable.scss: -------------------------------------------------------------------------------- 1 | @mixin scrollable($top: false, $bottom: false) { 2 | 3 | @if $top and $shadows { 4 | undershoot.top { 5 | background: linear-gradient(to bottom, $shadow-color, transparent, transparent, transparent, transparent, transparent); 6 | } 7 | } 8 | 9 | @if $bottom and $shadows { 10 | undershoot.bottom { 11 | background: linear-gradient(to top, $shadow-color, transparent, transparent, transparent, transparent, transparent); 12 | } 13 | } 14 | 15 | scrollbar, 16 | scrollbar * { 17 | all: unset; 18 | } 19 | 20 | scrollbar.vertical { 21 | transition: $transition; 22 | background-color: transparentize($bg, 0.7); 23 | 24 | &:hover { 25 | background-color: transparentize($bg, 0.3); 26 | 27 | slider { 28 | background-color: transparentize($fg, 0.3); 29 | min-width: .6em; 30 | } 31 | } 32 | } 33 | 34 | 35 | scrollbar.vertical slider { 36 | background-color: transparentize($fg, 0.5); 37 | border-radius: $radius; 38 | min-width: .4em; 39 | min-height: 2em; 40 | transition: $transition; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /config/ags/style/mixins/slider.scss: -------------------------------------------------------------------------------- 1 | @import './unset'; 2 | 3 | @mixin slider($width: 0.7em, $slider-width: .5em, $gradient: $active-gradient, $slider: true, $focusable: true, $radius: $radius) { 4 | @include unset($rec: true); 5 | 6 | trough { 7 | transition: $transition; 8 | border-radius: $radius; 9 | border: $border; 10 | background-color: $widget-bg; 11 | min-height: $width; 12 | min-width: $width; 13 | 14 | highlight, 15 | progress { 16 | border-radius: max($radius - $border-width, 0); 17 | background-image: $gradient; 18 | min-height: $width; 19 | min-width: $width; 20 | } 21 | } 22 | 23 | slider { 24 | box-shadow: none; 25 | background-color: transparent; 26 | border: $border-width solid transparent; 27 | transition: $transition; 28 | border-radius: $radius; 29 | min-height: $width; 30 | min-width: $width; 31 | margin: -$slider-width; 32 | } 33 | 34 | &:hover { 35 | trough { 36 | background-color: $hover-bg; 37 | } 38 | 39 | slider { 40 | @if $slider { 41 | background-color: $fg; 42 | border-color: $border-color; 43 | 44 | @if $shadows { 45 | box-shadow: 0 0 3px 0 $shadow-color; 46 | } 47 | } 48 | } 49 | } 50 | 51 | &:disabled { 52 | 53 | highlight, 54 | progress { 55 | background-color: transparentize($fg, 0.4); 56 | background-image: none; 57 | } 58 | } 59 | 60 | @if $focusable { 61 | trough:focus { 62 | background-color: $hover-bg; 63 | box-shadow: inset 0 0 0 $border-width $primary-bg; 64 | 65 | slider { 66 | @if $slider { 67 | background-color: $fg; 68 | box-shadow: inset 0 0 0 $border-width $primary-bg; 69 | } 70 | } 71 | } 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /config/ags/style/mixins/spacing.scss: -------------------------------------------------------------------------------- 1 | @mixin spacing($multiplier: 1, $spacing: $spacing, $rec: false) { 2 | &.horizontal>* { 3 | margin: 0 calc($spacing * $multiplier / 2); 4 | 5 | &:first-child { 6 | margin-left: 0; 7 | } 8 | 9 | &:last-child { 10 | margin-right: 0; 11 | } 12 | } 13 | 14 | &.vertical>* { 15 | margin: calc($spacing * $multiplier / 2) 0; 16 | 17 | &:first-child { 18 | margin-top: 0; 19 | } 20 | 21 | &:last-child { 22 | margin-bottom: 0; 23 | } 24 | } 25 | 26 | @if $rec { 27 | box { 28 | &.horizontal>* { 29 | margin: 0 $spacing * $multiplier / 2; 30 | 31 | &:first-child { 32 | margin-left: 0; 33 | } 34 | 35 | &:last-child { 36 | margin-right: 0; 37 | } 38 | } 39 | 40 | &.vertical>* { 41 | margin: $spacing * $multiplier / 2 0; 42 | 43 | &:first-child { 44 | margin-top: 0; 45 | } 46 | 47 | &:last-child { 48 | margin-bottom: 0; 49 | } 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /config/ags/style/mixins/switch.scss: -------------------------------------------------------------------------------- 1 | @import './button'; 2 | 3 | @mixin switch { 4 | @include button; 5 | 6 | slider { 7 | background-color: $primary-fg; 8 | border-radius: $radius; 9 | min-width: 24px; 10 | min-height: 24px; 11 | } 12 | 13 | image { 14 | color: transparent; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /config/ags/style/mixins/unset.scss: -------------------------------------------------------------------------------- 1 | @mixin unset($rec: false) { 2 | all: unset; 3 | 4 | @if $rec { 5 | * { 6 | all: unset 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /config/ags/style/mixins/widget.scss: -------------------------------------------------------------------------------- 1 | @mixin widget { 2 | transition: $transition; 3 | border-radius: $radius; 4 | color: $fg; 5 | background-color: $widget-bg; 6 | border: $border; 7 | } 8 | -------------------------------------------------------------------------------- /config/ags/style/widgets/datemenu.scss: -------------------------------------------------------------------------------- 1 | @import "./notifications.scss"; 2 | 3 | @mixin calendar { 4 | @include widget; 5 | padding: $padding*2 $padding*2 0; 6 | 7 | calendar { 8 | all: unset; 9 | 10 | &.button { 11 | @include button($flat: true); 12 | } 13 | 14 | &:selected { 15 | box-shadow: inset 0 -8px 0 0 transparentize($primary-bg, 0.5), 16 | inset 0 0 0 1px $primary-bg; 17 | border-radius: $radius*0.6; 18 | } 19 | 20 | &.header { 21 | background-color: transparent; 22 | border: none; 23 | color: transparentize($fg, 0.5); 24 | } 25 | 26 | &.highlight { 27 | background-color: transparent; 28 | color: transparentize($primary-bg, 0.5); 29 | } 30 | 31 | &:indeterminate { 32 | color: transparentize($fg, 0.9); 33 | } 34 | 35 | font-size: 1.1em; 36 | padding: .2em; 37 | } 38 | } 39 | 40 | window#datemenu .datemenu { 41 | @include floating-widget; 42 | 43 | .notifications { 44 | .header { 45 | margin-bottom: $spacing; 46 | margin-right: $spacing; 47 | 48 | >label { 49 | margin-left: $radius * .5; 50 | } 51 | 52 | button { 53 | @include button; 54 | padding: $padding*.7 $padding; 55 | } 56 | } 57 | 58 | .notification-scrollable { 59 | @include scrollable($top: true, $bottom: true); 60 | } 61 | 62 | .notification-list { 63 | margin-right: $spacing; 64 | } 65 | 66 | .notification { 67 | @include notification; 68 | @include widget; 69 | padding: $padding; 70 | margin-bottom: $spacing; 71 | } 72 | 73 | .placeholder { 74 | image { 75 | font-size: 7em; 76 | } 77 | 78 | label { 79 | font-size: 1.2em; 80 | } 81 | } 82 | } 83 | 84 | 85 | separator { 86 | background-color: $popover-border-color; 87 | border-radius: $radius; 88 | margin-right: $spacing; 89 | } 90 | 91 | .datemenu { 92 | @include spacing; 93 | } 94 | 95 | .clock-box { 96 | padding: $padding; 97 | 98 | .clock { 99 | font-size: 5em; 100 | } 101 | 102 | .uptime { 103 | color: transparentize($fg, 0.2); 104 | } 105 | } 106 | 107 | .calendar { 108 | @include calendar; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /config/ags/style/widgets/greeter.scss: -------------------------------------------------------------------------------- 1 | @import "../mixins/floating-widget.scss"; 2 | @import "../mixins/widget.scss"; 3 | @import "../mixins/spacing.scss"; 4 | @import "../mixins/unset.scss"; 5 | @import "../mixins/a11y-button.scss"; 6 | @import "./bar.scss"; 7 | 8 | window#greeter { 9 | background-color: lighten($bg, 6%); 10 | color: $fg; 11 | 12 | .bar { 13 | background-color: transparent; 14 | 15 | .date { 16 | @include unset($rec: true); 17 | @include panel-button($flat: true, $reactive: false); 18 | } 19 | } 20 | 21 | .auth { 22 | @include floating_widget; 23 | border-radius: $radius; 24 | min-width: 400px; 25 | padding: 0; 26 | 27 | .wallpaper { 28 | min-height: 220px; 29 | background-size: cover; 30 | border-top-left-radius: $radius; 31 | border-top-right-radius: $radius; 32 | } 33 | 34 | .wallpaper-contrast { 35 | min-height: 100px; 36 | } 37 | 38 | .avatar { 39 | border-radius: 99px; 40 | min-width: 140px; 41 | min-height: 140px; 42 | background-size: cover; 43 | box-shadow: 3px 3px 6px 0 $shadow-color; 44 | margin-bottom: $spacing; 45 | } 46 | 47 | 48 | .password { 49 | entry { 50 | @include button; 51 | padding: $padding*.7 $padding; 52 | margin-left: $spacing*.5; 53 | } 54 | 55 | margin: 0 $padding*4; 56 | margin-top: $spacing; 57 | } 58 | 59 | .response-box { 60 | color: $error-bg; 61 | margin: $spacing 0; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /config/ags/style/widgets/launcher.scss: -------------------------------------------------------------------------------- 1 | @use "sass:math"; 2 | @use "sass:color"; 3 | 4 | window#launcher .launcher { 5 | @include floating_widget; 6 | 7 | .quicklaunch { 8 | @include spacing; 9 | 10 | button { 11 | @include button($flat: true); 12 | padding: $padding; 13 | } 14 | } 15 | 16 | entry { 17 | @include button; 18 | padding: $padding; 19 | margin: $spacing; 20 | 21 | selection { 22 | color: color.mix($fg, $bg, 50%); 23 | background-color: transparent; 24 | } 25 | 26 | label, 27 | image { 28 | color: $fg; 29 | } 30 | } 31 | 32 | image.spinner { 33 | color: $primary-bg; 34 | margin-right: $spacing; 35 | } 36 | 37 | separator { 38 | margin: 4pt 0; 39 | background-color: $popover-border-color; 40 | } 41 | 42 | button.app-item { 43 | @include button($flat: true, $reactive: false); 44 | 45 | >box { 46 | @include spacing(0.5); 47 | } 48 | 49 | transition: $transition; 50 | padding: $padding; 51 | 52 | label { 53 | transition: $transition; 54 | 55 | &.title { 56 | color: $fg; 57 | } 58 | 59 | &.description { 60 | color: transparentize($fg, 0.3); 61 | } 62 | } 63 | 64 | image { 65 | transition: $transition; 66 | } 67 | 68 | &:hover, 69 | &:focus { 70 | .title { 71 | color: $primary-bg; 72 | } 73 | 74 | .description { 75 | color: transparentize($primary-bg, .4); 76 | } 77 | 78 | image { 79 | -gtk-icon-shadow: 2px 2px $primary-bg; 80 | } 81 | } 82 | 83 | &:active { 84 | background-color: transparentize($primary-bg, 0.5); 85 | border-radius: $radius; 86 | box-shadow: inset 0 0 0 $border-width $border-color; 87 | 88 | .title { 89 | color: $fg; 90 | } 91 | } 92 | } 93 | 94 | button.help, 95 | button.nix-item { 96 | @include button($flat: true, $reactive: false); 97 | padding: 0 ($padding * .5); 98 | 99 | label { 100 | transition: $transition; 101 | color: $fg; 102 | } 103 | 104 | .name { 105 | font-size: 1.2em; 106 | font-weight: bold; 107 | } 108 | 109 | .description { 110 | color: transparentize($fg, .3) 111 | } 112 | 113 | &:hover, 114 | &:focus { 115 | label { 116 | text-shadow: $text-shadow; 117 | } 118 | 119 | .name, 120 | .version { 121 | color: $primary-bg; 122 | } 123 | 124 | .description { 125 | color: transparentize($primary-bg, .3) 126 | } 127 | } 128 | } 129 | 130 | button.sh-item { 131 | @include button($flat: true, $reactive: false); 132 | padding: 0 ($padding * .5); 133 | 134 | transition: $transition; 135 | color: $fg; 136 | 137 | &:hover, 138 | &:focus { 139 | color: $primary-bg; 140 | text-shadow: $text-shadow; 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /config/ags/style/widgets/notifications.scss: -------------------------------------------------------------------------------- 1 | @mixin notification() { 2 | &.critical { 3 | box-shadow: inset 0 0 .5em 0 $error-bg; 4 | } 5 | 6 | &:hover button.close-button { 7 | @include button-hover; 8 | background-color: transparentize($error-bg, .5); 9 | } 10 | 11 | .content { 12 | .title { 13 | margin-right: $spacing; 14 | color: $fg; 15 | font-size: 1.1em; 16 | } 17 | 18 | .time { 19 | color: transparentize($fg, .2); 20 | } 21 | 22 | .description { 23 | font-size: .9em; 24 | color: transparentize($fg, .2); 25 | } 26 | 27 | .icon { 28 | border-radius: $radius*0.8; 29 | margin-right: $spacing; 30 | 31 | &.img { 32 | border: $border; 33 | } 34 | } 35 | } 36 | 37 | box.actions { 38 | @include spacing(0.5); 39 | margin-top: $spacing; 40 | 41 | button { 42 | @include button; 43 | border-radius: $radius*0.8; 44 | font-size: 1.2em; 45 | padding: $padding * 0.7; 46 | } 47 | } 48 | 49 | button.close-button { 50 | @include button($flat: true); 51 | margin-left: $spacing / 2; 52 | border-radius: $radius*0.8; 53 | min-width: 1.2em; 54 | min-height: 1.2em; 55 | 56 | &:hover { 57 | background-color: transparentize($error-bg, .2); 58 | } 59 | 60 | &:active { 61 | background-image: none; 62 | background-color: $error-bg; 63 | } 64 | } 65 | } 66 | 67 | window.notifications { 68 | @include unset; 69 | 70 | .notification { 71 | @include notification; 72 | @include floating-widget; 73 | border-radius: $radius; 74 | 75 | .description { 76 | min-width: 350px; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /config/ags/style/widgets/osd.scss: -------------------------------------------------------------------------------- 1 | window.indicator { 2 | .progress { 3 | @include floating-widget; 4 | padding: $padding * .5; 5 | border-radius: if($radius >0, calc($radius + $padding*.5), 0); 6 | @debug $radius; 7 | 8 | .fill { 9 | border-radius: $radius; 10 | background-color: $primary-bg; 11 | color: $primary-fg; 12 | 13 | image { 14 | -gtk-icon-transform: scale(0.7); 15 | } 16 | } 17 | } 18 | 19 | .microphone { 20 | @include floating-widget; 21 | margin: $spacing * 2; 22 | padding: $popover-padding * 2; 23 | font-size: 58px; 24 | color: transparentize($fg, .1) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /config/ags/style/widgets/overview.scss: -------------------------------------------------------------------------------- 1 | window#overview .overview { 2 | @include floating-widget; 3 | @include spacing; 4 | 5 | .workspace { 6 | &.active>widget { 7 | border-color: $primary-bg 8 | } 9 | 10 | >widget { 11 | @include widget; 12 | border-radius: if($radius ==0, 0, $radius + $padding); 13 | 14 | &:hover { 15 | background-color: $hover-bg; 16 | } 17 | 18 | &:drop(active) { 19 | border-color: $primary-bg; 20 | } 21 | } 22 | } 23 | 24 | .client { 25 | @include button; 26 | border-radius: $radius; 27 | margin: $padding; 28 | 29 | &.hidden { 30 | @include hidden; 31 | transition: 0; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /config/ags/style/widgets/powermenu.scss: -------------------------------------------------------------------------------- 1 | window#powermenu, 2 | window#verification { 3 | // the fraction has to be more than hyprland ignorealpha 4 | background-color: rgba(0, 0, 0, .4); 5 | } 6 | 7 | window#verification .verification { 8 | @include floating-widget; 9 | padding: $popover-padding * 1.5; 10 | min-width: 300px; 11 | min-height: 100px; 12 | 13 | .text-box { 14 | margin-bottom: $spacing; 15 | 16 | .title { 17 | font-size: 1.6em; 18 | } 19 | 20 | .desc { 21 | color: transparentize($fg, 0.1); 22 | font-size: 1.1em; 23 | } 24 | } 25 | 26 | .buttons { 27 | @include spacing; 28 | margin-top: $padding; 29 | 30 | button { 31 | @include button; 32 | font-size: 1.5em; 33 | padding: $padding; 34 | } 35 | } 36 | } 37 | 38 | window#powermenu .powermenu { 39 | @include floating-widget; 40 | 41 | &.line { 42 | padding: $popover-padding * 1.5; 43 | 44 | button { 45 | padding: $popover-padding; 46 | } 47 | 48 | label { 49 | margin-bottom: $spacing * -.5; 50 | } 51 | } 52 | 53 | &.box { 54 | padding: $popover-padding * 2; 55 | 56 | button { 57 | padding: $popover-padding * 1.5; 58 | } 59 | 60 | label { 61 | margin-bottom: $spacing * -1; 62 | } 63 | } 64 | 65 | button { 66 | @include unset; 67 | 68 | image { 69 | @include button; 70 | border-radius: $radius + ($popover-padding * 1.4); 71 | min-width: 1.7em; 72 | min-height: 1.7em; 73 | font-size: 4em; 74 | } 75 | 76 | label, 77 | image { 78 | color: transparentize($fg, 0.1); 79 | } 80 | 81 | label { 82 | margin-top: $spacing * .3; 83 | } 84 | 85 | &:hover { 86 | image { 87 | @include button-hover; 88 | } 89 | 90 | label { 91 | color: $fg; 92 | } 93 | } 94 | 95 | &:focus image { 96 | @include button-focus; 97 | } 98 | 99 | &:active image { 100 | @include button-active; 101 | } 102 | 103 | &:focus, 104 | &:active { 105 | label { 106 | color: $primary-bg; 107 | } 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /config/ags/style/widgets/screencorner.scss: -------------------------------------------------------------------------------- 1 | $_shadow-size: $padding; 2 | $_radius: $radius * $hyprland-gaps-multiplier * $screen-corner-multiplier; 3 | $_margin: 99px; 4 | 5 | window.screen-corner:not(.hidden) { 6 | transition: $transition; 7 | 8 | box.shadow { 9 | margin-right: $_margin * -1; 10 | margin-left: $_margin * -1; 11 | 12 | @if $shadows { 13 | box-shadow: inset 0 0 $_shadow-size 0 $shadow-color; 14 | } 15 | 16 | @if $bar-position =="top" { 17 | margin-bottom: $_margin * -1; 18 | } 19 | 20 | @if $bar-position =="bottom" { 21 | margin-top: $_margin * -1; 22 | } 23 | } 24 | 25 | box.border { 26 | @if $bar-position =="top" { 27 | border-top: $border-width solid $bg; 28 | } 29 | 30 | @if $bar-position =="bottom" { 31 | border-bottom: $border-width solid $bg; 32 | } 33 | 34 | margin-right: $_margin; 35 | margin-left: $_margin; 36 | } 37 | 38 | box.corner { 39 | box-shadow: 0 0 0 $border-width $border-color; 40 | } 41 | 42 | &.corners { 43 | box.border { 44 | border-radius: if($radius>0, $_radius, 0); 45 | box-shadow: 0 0 0 $_radius $bg; 46 | } 47 | 48 | box.corner { 49 | border-radius: if($radius>0, $_radius, 0); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /config/ags/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "ES2022", 5 | "lib": [ 6 | "ES2022" 7 | ], 8 | "allowJs": true, 9 | "checkJs": true, 10 | "strict": true, 11 | "noImplicitAny": false, 12 | "baseUrl": ".", 13 | "typeRoots": [ 14 | "./types", 15 | "./node_modules/@girs" 16 | ], 17 | "skipLibCheck": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /config/ags/widget/RegularWindow.ts: -------------------------------------------------------------------------------- 1 | import Gtk from "gi://Gtk?version=3.0" 2 | 3 | export default Widget.subclass(Gtk.Window) 4 | -------------------------------------------------------------------------------- /config/ags/widget/bar/Bar.ts: -------------------------------------------------------------------------------- 1 | import BatteryBar from "./buttons/BatteryBar" 2 | import ColorPicker from "./buttons/ColorPicker" 3 | import Date from "./buttons/Date" 4 | import Launcher from "./buttons/Launcher" 5 | import Media from "./buttons/Media" 6 | import PowerMenu from "./buttons/PowerMenu" 7 | import SysTray from "./buttons/SysTray" 8 | import SystemIndicators from "./buttons/SystemIndicators" 9 | import Taskbar from "./buttons/Taskbar" 10 | import Workspaces from "./buttons/Workspaces" 11 | import ScreenRecord from "./buttons/ScreenRecord" 12 | import Messages from "./buttons/Messages" 13 | import options from "options" 14 | 15 | const { start, center, end } = options.bar.layout 16 | const { transparent, position } = options.bar 17 | 18 | export type BarWidget = keyof typeof widget 19 | 20 | const widget = { 21 | battery: BatteryBar, 22 | colorpicker: ColorPicker, 23 | date: Date, 24 | launcher: Launcher, 25 | media: Media, 26 | powermenu: PowerMenu, 27 | systray: SysTray, 28 | system: SystemIndicators, 29 | taskbar: Taskbar, 30 | workspaces: Workspaces, 31 | screenrecord: ScreenRecord, 32 | messages: Messages, 33 | expander: () => Widget.Box({ expand: true }), 34 | } 35 | 36 | export default (monitor: number) => Widget.Window({ 37 | monitor, 38 | class_name: "bar", 39 | name: `bar${monitor}`, 40 | exclusivity: "exclusive", 41 | anchor: position.bind().as(pos => [pos, "right", "left"]), 42 | child: Widget.CenterBox({ 43 | css: "min-width: 2px; min-height: 2px;", 44 | startWidget: Widget.Box({ 45 | hexpand: true, 46 | children: start.bind().as(s => s.map(w => widget[w]())), 47 | }), 48 | centerWidget: Widget.Box({ 49 | hpack: "center", 50 | children: center.bind().as(c => c.map(w => widget[w]())), 51 | }), 52 | endWidget: Widget.Box({ 53 | hexpand: true, 54 | children: end.bind().as(e => e.map(w => widget[w]())), 55 | }), 56 | }), 57 | setup: self => self.hook(transparent, () => { 58 | self.toggleClassName("transparent", transparent.value) 59 | }), 60 | }) 61 | -------------------------------------------------------------------------------- /config/ags/widget/bar/PanelButton.ts: -------------------------------------------------------------------------------- 1 | import options from "options" 2 | import { ButtonProps } from "types/widgets/button" 3 | 4 | type PanelButtonProps = ButtonProps & { 5 | window?: string, 6 | flat?: boolean 7 | } 8 | 9 | export default ({ 10 | window = "", 11 | flat, 12 | child, 13 | setup, 14 | ...rest 15 | }: PanelButtonProps) => Widget.Button({ 16 | child: Widget.Box({ child }), 17 | setup: self => { 18 | let open = false 19 | 20 | self.toggleClassName("panel-button") 21 | self.toggleClassName(window) 22 | 23 | self.hook(options.bar.flatButtons, () => { 24 | self.toggleClassName("flat", flat ?? options.bar.flatButtons.value) 25 | }) 26 | 27 | self.hook(App, (_, win, visible) => { 28 | if (win !== window) 29 | return 30 | 31 | if (open && !visible) { 32 | open = false 33 | self.toggleClassName("active", false) 34 | } 35 | 36 | if (visible) { 37 | open = true 38 | self.toggleClassName("active") 39 | } 40 | }) 41 | 42 | if (setup) 43 | setup(self) 44 | }, 45 | ...rest, 46 | }) 47 | -------------------------------------------------------------------------------- /config/ags/widget/bar/ScreenCorners.ts: -------------------------------------------------------------------------------- 1 | import options from "options" 2 | 3 | const { corners, transparent } = options.bar 4 | 5 | export default (monitor: number) => Widget.Window({ 6 | monitor, 7 | name: `corner${monitor}`, 8 | class_name: "screen-corner", 9 | anchor: ["top", "bottom", "right", "left"], 10 | click_through: true, 11 | child: Widget.Box({ 12 | class_name: "shadow", 13 | child: Widget.Box({ 14 | class_name: "border", 15 | expand: true, 16 | child: Widget.Box({ 17 | class_name: "corner", 18 | expand: true, 19 | }), 20 | }), 21 | }), 22 | setup: self => self 23 | .hook(corners, () => { 24 | self.toggleClassName("corners", corners.value > 0) 25 | }) 26 | .hook(transparent, () => { 27 | self.toggleClassName("hidden", transparent.value) 28 | }), 29 | }) 30 | -------------------------------------------------------------------------------- /config/ags/widget/bar/buttons/BatteryBar.ts: -------------------------------------------------------------------------------- 1 | import icons from "lib/icons" 2 | import options from "options" 3 | import PanelButton from "../PanelButton" 4 | 5 | const battery = await Service.import("battery") 6 | const { bar, percentage, blocks, width, low } = options.bar.battery 7 | 8 | const Indicator = () => Widget.Icon({ 9 | setup: self => self.hook(battery, () => { 10 | self.icon = battery.charging || battery.charged 11 | ? icons.battery.charging 12 | : battery.icon_name 13 | }), 14 | }) 15 | 16 | const PercentLabel = () => Widget.Revealer({ 17 | transition: "slide_right", 18 | click_through: true, 19 | reveal_child: percentage.bind(), 20 | child: Widget.Label({ 21 | label: battery.bind("percent").as(p => `${p}%`), 22 | }), 23 | }) 24 | 25 | const LevelBar = () => { 26 | const level = Widget.LevelBar({ 27 | bar_mode: "discrete", 28 | max_value: blocks.bind(), 29 | visible: bar.bind().as(b => b !== "hidden"), 30 | value: battery.bind("percent").as(p => (p / 100) * blocks.value), 31 | }) 32 | const update = () => { 33 | level.value = (battery.percent / 100) * blocks.value 34 | level.css = `block { min-width: ${width.value / blocks.value}pt; }` 35 | } 36 | return level 37 | .hook(width, update) 38 | .hook(blocks, update) 39 | .hook(bar, () => { 40 | level.vpack = bar.value === "whole" ? "fill" : "center" 41 | level.hpack = bar.value === "whole" ? "fill" : "center" 42 | }) 43 | } 44 | 45 | const WholeButton = () => Widget.Overlay({ 46 | vexpand: true, 47 | child: LevelBar(), 48 | class_name: "whole", 49 | pass_through: true, 50 | overlay: Widget.Box({ 51 | hpack: "center", 52 | children: [ 53 | Widget.Icon({ 54 | icon: icons.battery.charging, 55 | visible: Utils.merge([ 56 | battery.bind("charging"), 57 | battery.bind("charged"), 58 | ], (ing, ed) => ing || ed), 59 | }), 60 | Widget.Box({ 61 | hpack: "center", 62 | vpack: "center", 63 | child: PercentLabel(), 64 | }), 65 | ], 66 | }), 67 | }) 68 | 69 | const Regular = () => Widget.Box({ 70 | class_name: "regular", 71 | children: [ 72 | Indicator(), 73 | PercentLabel(), 74 | LevelBar(), 75 | ], 76 | }) 77 | 78 | export default () => PanelButton({ 79 | class_name: "battery-bar", 80 | hexpand: false, 81 | on_clicked: () => { percentage.value = !percentage.value }, 82 | visible: battery.bind("available"), 83 | child: Widget.Box({ 84 | expand: true, 85 | visible: battery.bind("available"), 86 | child: bar.bind().as(b => b === "whole" ? WholeButton() : Regular()), 87 | }), 88 | setup: self => self 89 | .hook(bar, w => w.toggleClassName("bar-hidden", bar.value === "hidden")) 90 | .hook(battery, w => { 91 | w.toggleClassName("charging", battery.charging || battery.charged) 92 | w.toggleClassName("low", battery.percent < low.value) 93 | }), 94 | }) 95 | -------------------------------------------------------------------------------- /config/ags/widget/bar/buttons/ColorPicker.ts: -------------------------------------------------------------------------------- 1 | import PanelButton from "../PanelButton" 2 | import colorpicker from "service/colorpicker" 3 | import Gdk from "gi://Gdk" 4 | 5 | const css = (color: string) => ` 6 | * { 7 | background-color: ${color}; 8 | color: transparent; 9 | } 10 | *:hover { 11 | color: white; 12 | text-shadow: 2px 2px 3px rgba(0,0,0,.8); 13 | }` 14 | 15 | export default () => { 16 | const menu = Widget.Menu({ 17 | class_name: "colorpicker", 18 | children: colorpicker.bind("colors").as(c => c.map(color => Widget.MenuItem({ 19 | child: Widget.Label(color), 20 | css: css(color), 21 | on_activate: () => colorpicker.wlCopy(color), 22 | }))), 23 | }) 24 | 25 | return PanelButton({ 26 | class_name: "color-picker", 27 | child: Widget.Icon("color-select-symbolic"), 28 | tooltip_text: colorpicker.bind("colors").as(v => `${v.length} colors`), 29 | on_clicked: colorpicker.pick, 30 | on_secondary_click: self => { 31 | if (colorpicker.colors.length === 0) 32 | return 33 | 34 | menu.popup_at_widget(self, Gdk.Gravity.SOUTH, Gdk.Gravity.NORTH, null) 35 | }, 36 | }) 37 | } 38 | -------------------------------------------------------------------------------- /config/ags/widget/bar/buttons/Date.ts: -------------------------------------------------------------------------------- 1 | import { clock } from "lib/variables" 2 | import PanelButton from "../PanelButton" 3 | import options from "options" 4 | 5 | const { format, action } = options.bar.date 6 | const time = Utils.derive([clock, format], (c, f) => c.format(f) || "") 7 | 8 | export default () => PanelButton({ 9 | window: "datemenu", 10 | on_clicked: action.bind(), 11 | child: Widget.Label({ 12 | justification: "center", 13 | label: time.bind(), 14 | }), 15 | }) 16 | -------------------------------------------------------------------------------- /config/ags/widget/bar/buttons/Launcher.ts: -------------------------------------------------------------------------------- 1 | import PanelButton from "../PanelButton" 2 | import options from "options" 3 | import nix from "service/nix" 4 | 5 | const { icon, label, action } = options.bar.launcher 6 | 7 | function Spinner() { 8 | const child = Widget.Icon({ 9 | icon: icon.icon.bind(), 10 | class_name: Utils.merge([ 11 | icon.colored.bind(), 12 | nix.bind("ready"), 13 | ], (c, r) => `${c ? "colored" : ""} ${r ? "" : "spinning"}`), 14 | css: ` 15 | @keyframes spin { 16 | to { -gtk-icon-transform: rotate(1turn); } 17 | } 18 | 19 | image.spinning { 20 | animation-name: spin; 21 | animation-duration: 1s; 22 | animation-timing-function: linear; 23 | animation-iteration-count: infinite; 24 | } 25 | `, 26 | }) 27 | 28 | return Widget.Revealer({ 29 | transition: "slide_left", 30 | child, 31 | reveal_child: Utils.merge([ 32 | icon.icon.bind(), 33 | nix.bind("ready"), 34 | ], (i, r) => Boolean(i || r)), 35 | }) 36 | } 37 | 38 | export default () => PanelButton({ 39 | window: "launcher", 40 | on_clicked: action.bind(), 41 | child: Widget.Box([ 42 | Spinner(), 43 | Widget.Label({ 44 | class_name: label.colored.bind().as(c => c ? "colored" : ""), 45 | visible: label.label.bind().as(v => !!v), 46 | label: label.label.bind(), 47 | }), 48 | ]), 49 | }) 50 | -------------------------------------------------------------------------------- /config/ags/widget/bar/buttons/Media.ts: -------------------------------------------------------------------------------- 1 | import { type MprisPlayer } from "types/service/mpris" 2 | import PanelButton from "../PanelButton" 3 | import options from "options" 4 | import icons from "lib/icons" 5 | import { icon } from "lib/utils" 6 | 7 | const mpris = await Service.import("mpris") 8 | const { length, direction, preferred, monochrome, format } = options.bar.media 9 | 10 | const getPlayer = (name = preferred.value) => 11 | mpris.getPlayer(name) || mpris.players[0] || null 12 | 13 | const Content = (player: MprisPlayer) => { 14 | const revealer = Widget.Revealer({ 15 | click_through: true, 16 | visible: length.bind().as(l => l > 0), 17 | transition: direction.bind().as(d => `slide_${d}` as const), 18 | setup: self => { 19 | let current = "" 20 | self.hook(player, () => { 21 | if (current === player.track_title) 22 | return 23 | 24 | current = player.track_title 25 | self.reveal_child = true 26 | Utils.timeout(3000, () => { 27 | !self.is_destroyed && (self.reveal_child = false) 28 | }) 29 | }) 30 | }, 31 | child: Widget.Label({ 32 | truncate: "end", 33 | max_width_chars: length.bind().as(n => n > 0 ? n : -1), 34 | label: Utils.merge([ 35 | player.bind("track_title"), 36 | player.bind("track_artists"), 37 | format.bind(), 38 | ], () => `${format}` 39 | .replace("{title}", player.track_title) 40 | .replace("{artists}", player.track_artists.join(", ")) 41 | .replace("{artist}", player.track_artists[0] || "") 42 | .replace("{album}", player.track_album) 43 | .replace("{name}", player.name) 44 | .replace("{identity}", player.identity), 45 | ), 46 | }), 47 | }) 48 | 49 | const playericon = Widget.Icon({ 50 | icon: Utils.merge([player.bind("entry"), monochrome.bind()], (entry => { 51 | const name = `${entry}${monochrome.value ? "-symbolic" : ""}` 52 | return icon(name, icons.fallback.audio) 53 | })), 54 | }) 55 | 56 | return Widget.Box({ 57 | attribute: { revealer }, 58 | children: direction.bind().as(d => d === "right" 59 | ? [playericon, revealer] : [revealer, playericon]), 60 | }) 61 | } 62 | 63 | export default () => { 64 | let player = getPlayer() 65 | 66 | const btn = PanelButton({ 67 | class_name: "media", 68 | child: Widget.Icon(icons.fallback.audio), 69 | }) 70 | 71 | const update = () => { 72 | player = getPlayer() 73 | btn.visible = !!player 74 | 75 | if (!player) 76 | return 77 | 78 | const content = Content(player) 79 | const { revealer } = content.attribute 80 | btn.child = content 81 | btn.on_primary_click = () => { player.playPause() } 82 | btn.on_secondary_click = () => { player.playPause() } 83 | btn.on_scroll_up = () => { player.next() } 84 | btn.on_scroll_down = () => { player.previous() } 85 | btn.on_hover = () => { revealer.reveal_child = true } 86 | btn.on_hover_lost = () => { revealer.reveal_child = false } 87 | } 88 | 89 | return btn 90 | .hook(preferred, update) 91 | .hook(mpris, update, "notify::players") 92 | } 93 | -------------------------------------------------------------------------------- /config/ags/widget/bar/buttons/Messages.ts: -------------------------------------------------------------------------------- 1 | import icons from "lib/icons" 2 | import PanelButton from "../PanelButton" 3 | import options from "options" 4 | 5 | const n = await Service.import("notifications") 6 | const notifs = n.bind("notifications") 7 | const action = options.bar.messages.action.bind() 8 | 9 | export default () => PanelButton({ 10 | class_name: "messages", 11 | on_clicked: action, 12 | visible: notifs.as(n => n.length > 0), 13 | child: Widget.Box([ 14 | Widget.Icon(icons.notifications.message), 15 | ]), 16 | }) 17 | -------------------------------------------------------------------------------- /config/ags/widget/bar/buttons/PowerMenu.ts: -------------------------------------------------------------------------------- 1 | import icons from "lib/icons" 2 | import PanelButton from "../PanelButton" 3 | import options from "options" 4 | 5 | const { monochrome, action } = options.bar.powermenu 6 | 7 | export default () => PanelButton({ 8 | window: "powermenu", 9 | on_clicked: action.bind(), 10 | child: Widget.Icon(icons.powermenu.shutdown), 11 | setup: self => self.hook(monochrome, () => { 12 | self.toggleClassName("colored", !monochrome.value) 13 | self.toggleClassName("box") 14 | }), 15 | }) 16 | -------------------------------------------------------------------------------- /config/ags/widget/bar/buttons/ScreenRecord.ts: -------------------------------------------------------------------------------- 1 | import PanelButton from "../PanelButton" 2 | import screenrecord from "service/screenrecord" 3 | import icons from "lib/icons" 4 | 5 | export default () => PanelButton({ 6 | class_name: "recorder", 7 | on_clicked: () => screenrecord.stop(), 8 | visible: screenrecord.bind("recording"), 9 | child: Widget.Box({ 10 | children: [ 11 | Widget.Icon(icons.recorder.recording), 12 | Widget.Label({ 13 | label: screenrecord.bind("timer").as(time => { 14 | const sec = time % 60 15 | const min = Math.floor(time / 60) 16 | return `${min}:${sec < 10 ? "0" + sec : sec}` 17 | }), 18 | }), 19 | ], 20 | }), 21 | }) 22 | -------------------------------------------------------------------------------- /config/ags/widget/bar/buttons/SysTray.ts: -------------------------------------------------------------------------------- 1 | import { type TrayItem } from "types/service/systemtray" 2 | import PanelButton from "../PanelButton" 3 | import Gdk from "gi://Gdk" 4 | import options from "options" 5 | 6 | const systemtray = await Service.import("systemtray") 7 | const { ignore } = options.bar.systray 8 | 9 | const SysTrayItem = (item: TrayItem) => PanelButton({ 10 | class_name: "tray-item", 11 | child: Widget.Icon({ icon: item.bind("icon") }), 12 | tooltip_markup: item.bind("tooltip_markup"), 13 | setup: self => { 14 | const { menu } = item 15 | if (!menu) 16 | return 17 | 18 | const id = menu.connect("popped-up", () => { 19 | self.toggleClassName("active") 20 | menu.connect("notify::visible", () => { 21 | self.toggleClassName("active", menu.visible) 22 | }) 23 | menu.disconnect(id!) 24 | }) 25 | 26 | self.connect("destroy", () => menu.disconnect(id)) 27 | }, 28 | 29 | on_primary_click: btn => item.menu?.popup_at_widget( 30 | btn, Gdk.Gravity.SOUTH, Gdk.Gravity.NORTH, null), 31 | 32 | on_secondary_click: btn => item.menu?.popup_at_widget( 33 | btn, Gdk.Gravity.SOUTH, Gdk.Gravity.NORTH, null), 34 | }) 35 | 36 | export default () => Widget.Box() 37 | .bind("children", systemtray, "items", i => i 38 | .filter(({ id }) => !ignore.value.includes(id)) 39 | .map(SysTrayItem)) 40 | -------------------------------------------------------------------------------- /config/ags/widget/bar/buttons/Taskbar.ts: -------------------------------------------------------------------------------- 1 | import { launchApp, icon } from "lib/utils" 2 | import icons from "lib/icons" 3 | import options from "options" 4 | import PanelButton from "../PanelButton" 5 | 6 | const hyprland = await Service.import("hyprland") 7 | const apps = await Service.import("applications") 8 | const { monochrome, exclusive, iconSize } = options.bar.taskbar 9 | const { position } = options.bar 10 | 11 | const focus = (address: string) => hyprland.messageAsync( 12 | `dispatch focuswindow address:${address}`) 13 | 14 | const DummyItem = (address: string) => Widget.Box({ 15 | attribute: { address }, 16 | visible: false, 17 | }) 18 | 19 | const AppItem = (address: string) => { 20 | const client = hyprland.getClient(address) 21 | if (!client || client.class === "") 22 | return DummyItem(address) 23 | 24 | const app = apps.list.find(app => app.match(client.class)) 25 | 26 | const btn = PanelButton({ 27 | class_name: "panel-button", 28 | tooltip_text: Utils.watch(client.title, hyprland, () => 29 | hyprland.getClient(address)?.title || "", 30 | ), 31 | on_primary_click: () => focus(address), 32 | on_middle_click: () => app && launchApp(app), 33 | child: Widget.Icon({ 34 | size: iconSize.bind(), 35 | icon: monochrome.bind().as(m => icon( 36 | (app?.icon_name || client.class) + (m ? "-symbolic" : ""), 37 | icons.fallback.executable + (m ? "-symbolic" : ""), 38 | )), 39 | }), 40 | }) 41 | 42 | return Widget.Box( 43 | { 44 | attribute: { address }, 45 | visible: Utils.watch(true, [exclusive, hyprland], () => { 46 | return exclusive.value 47 | ? hyprland.active.workspace.id === client.workspace.id 48 | : true 49 | }), 50 | }, 51 | Widget.Overlay({ 52 | child: btn, 53 | pass_through: true, 54 | overlay: Widget.Box({ 55 | className: "indicator", 56 | hpack: "center", 57 | vpack: position.bind().as(p => p === "top" ? "start" : "end"), 58 | setup: w => w.hook(hyprland, () => { 59 | w.toggleClassName("active", hyprland.active.client.address === address) 60 | }), 61 | }), 62 | }), 63 | ) 64 | } 65 | 66 | function sortItems(arr: T[]) { 67 | return arr.sort(({ attribute: a }, { attribute: b }) => { 68 | const aclient = hyprland.getClient(a.address)! 69 | const bclient = hyprland.getClient(b.address)! 70 | return aclient.workspace.id - bclient.workspace.id 71 | }) 72 | } 73 | 74 | export default () => Widget.Box({ 75 | class_name: "taskbar", 76 | children: sortItems(hyprland.clients.map(c => AppItem(c.address))), 77 | setup: w => w 78 | .hook(hyprland, (w, address?: string) => { 79 | if (typeof address === "string") 80 | w.children = w.children.filter(ch => ch.attribute.address !== address) 81 | }, "client-removed") 82 | .hook(hyprland, (w, address?: string) => { 83 | if (typeof address === "string") 84 | w.children = sortItems([...w.children, AppItem(address)]) 85 | }, "client-added") 86 | .hook(hyprland, (w, event?: string) => { 87 | if (event === "movewindow") 88 | w.children = sortItems(w.children) 89 | }, "event"), 90 | }) 91 | -------------------------------------------------------------------------------- /config/ags/widget/bar/buttons/Workspaces.ts: -------------------------------------------------------------------------------- 1 | import PanelButton from "../PanelButton" 2 | import options from "options" 3 | import { sh, range } from "lib/utils" 4 | 5 | const hyprland = await Service.import("hyprland") 6 | const { workspaces } = options.bar.workspaces 7 | 8 | const dispatch = (arg: string | number) => { 9 | sh(`hyprctl dispatch workspace ${arg}`) 10 | } 11 | 12 | const Workspaces = (ws: number) => Widget.Box({ 13 | children: range(ws || 20).map(i => Widget.Label({ 14 | attribute: i, 15 | vpack: "center", 16 | label: `${i}`, 17 | setup: self => self.hook(hyprland, () => { 18 | self.toggleClassName("active", hyprland.active.workspace.id === i) 19 | self.toggleClassName("occupied", (hyprland.getWorkspace(i)?.windows || 0) > 0) 20 | }), 21 | })), 22 | setup: box => { 23 | if (ws === 0) { 24 | box.hook(hyprland.active.workspace, () => box.children.map(btn => { 25 | btn.visible = hyprland.workspaces.some(ws => ws.id === btn.attribute) 26 | })) 27 | } 28 | }, 29 | }) 30 | 31 | export default () => PanelButton({ 32 | window: "overview", 33 | class_name: "workspaces", 34 | on_scroll_up: () => dispatch("m+1"), 35 | on_scroll_down: () => dispatch("m-1"), 36 | on_clicked: () => App.toggleWindow("overview"), 37 | child: workspaces.bind().as(Workspaces), 38 | }) 39 | -------------------------------------------------------------------------------- /config/ags/widget/datemenu/DateColumn.ts: -------------------------------------------------------------------------------- 1 | import { clock, uptime } from "lib/variables" 2 | 3 | function up(up: number) { 4 | const h = Math.floor(up / 60) 5 | const m = Math.floor(up % 60) 6 | return `uptime: ${h}:${m < 10 ? "0" + m : m}` 7 | } 8 | 9 | export default () => Widget.Box({ 10 | vertical: true, 11 | class_name: "date-column vertical", 12 | children: [ 13 | Widget.Box({ 14 | class_name: "clock-box", 15 | vertical: true, 16 | children: [ 17 | Widget.Label({ 18 | class_name: "clock", 19 | label: clock.bind().as(t => t.format("%H:%M")!), 20 | }), 21 | Widget.Label({ 22 | class_name: "uptime", 23 | label: uptime.bind().as(up), 24 | }), 25 | ], 26 | }), 27 | Widget.Box({ 28 | class_name: "calendar", 29 | children: [ 30 | Widget.Calendar({ 31 | hexpand: true, 32 | hpack: "center", 33 | }), 34 | ], 35 | }), 36 | ], 37 | }) 38 | -------------------------------------------------------------------------------- /config/ags/widget/datemenu/DateMenu.ts: -------------------------------------------------------------------------------- 1 | import PopupWindow from "widget/PopupWindow" 2 | import NotificationColumn from "./NotificationColumn" 3 | import DateColumn from "./DateColumn" 4 | import options from "options" 5 | 6 | const { bar, datemenu } = options 7 | const pos = bar.position.bind() 8 | const layout = Utils.derive([bar.position, datemenu.position], (bar, qs) => 9 | `${bar}-${qs}` as const, 10 | ) 11 | 12 | const Settings = () => Widget.Box({ 13 | class_name: "datemenu horizontal", 14 | vexpand: false, 15 | children: [ 16 | NotificationColumn(), 17 | Widget.Separator({ orientation: 1 }), 18 | DateColumn(), 19 | ], 20 | }) 21 | 22 | const DateMenu = () => PopupWindow({ 23 | name: "datemenu", 24 | exclusivity: "exclusive", 25 | transition: pos.as(pos => pos === "top" ? "slide_down" : "slide_up"), 26 | layout: layout.value, 27 | child: Settings(), 28 | }) 29 | 30 | export function setupDateMenu() { 31 | App.addWindow(DateMenu()) 32 | layout.connect("changed", () => { 33 | App.removeWindow("datemenu") 34 | App.addWindow(DateMenu()) 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /config/ags/widget/desktop/Desktop.ts: -------------------------------------------------------------------------------- 1 | import options from "options" 2 | import { matugen } from "lib/matugen" 3 | const mpris = await Service.import("mpris") 4 | 5 | const pref = () => options.bar.media.preferred.value 6 | 7 | export default (monitor: number) => Widget.Window({ 8 | monitor, 9 | layer: "bottom", 10 | name: `desktop${monitor}`, 11 | class_name: "desktop", 12 | anchor: ["top", "bottom", "left", "right"], 13 | child: Widget.Box({ 14 | expand: true, 15 | css: options.theme.dark.primary.bg.bind().as(c => ` 16 | transition: 500ms; 17 | background-color: ${c}`), 18 | child: Widget.Box({ 19 | class_name: "wallpaper", 20 | expand: true, 21 | vpack: "center", 22 | hpack: "center", 23 | setup: self => self 24 | .hook(mpris, () => { 25 | const img = mpris.getPlayer(pref())!.cover_path 26 | matugen("image", img) 27 | Utils.timeout(500, () => self.css = ` 28 | background-image: url('${img}'); 29 | background-size: contain; 30 | background-repeat: no-repeat; 31 | transition: 200ms; 32 | min-width: 700px; 33 | min-height: 700px; 34 | border-radius: 30px; 35 | box-shadow: 25px 25px 30px 0 rgba(0,0,0,0.5);`, 36 | ) 37 | }), 38 | }), 39 | }), 40 | }) 41 | -------------------------------------------------------------------------------- /config/ags/widget/launcher/ShRun.ts: -------------------------------------------------------------------------------- 1 | import icons from "lib/icons" 2 | import sh from "service/sh" 3 | 4 | const iconVisible = Variable(false) 5 | 6 | function Item(bin: string) { 7 | return Widget.Box( 8 | { 9 | attribute: { bin }, 10 | vertical: true, 11 | }, 12 | Widget.Separator(), 13 | Widget.Button({ 14 | child: Widget.Label({ 15 | label: bin, 16 | hpack: "start", 17 | }), 18 | class_name: "sh-item", 19 | on_clicked: () => { 20 | Utils.execAsync(bin) 21 | App.closeWindow("launcher") 22 | }, 23 | }), 24 | ) 25 | } 26 | 27 | export function Icon() { 28 | const icon = Widget.Icon({ 29 | icon: icons.app.terminal, 30 | class_name: "spinner", 31 | }) 32 | 33 | return Widget.Revealer({ 34 | transition: "slide_left", 35 | child: icon, 36 | reveal_child: iconVisible.bind(), 37 | }) 38 | } 39 | 40 | export function ShRun() { 41 | const list = Widget.Box>({ 42 | vertical: true, 43 | }) 44 | 45 | const revealer = Widget.Revealer({ 46 | child: list, 47 | }) 48 | 49 | async function filter(term: string) { 50 | iconVisible.value = Boolean(term) 51 | 52 | if (!term) 53 | revealer.reveal_child = false 54 | 55 | if (term.trim()) { 56 | const found = await sh.query(term) 57 | list.children = found.map(Item) 58 | revealer.reveal_child = true 59 | } 60 | } 61 | 62 | return Object.assign(revealer, { 63 | filter, 64 | run: sh.run, 65 | }) 66 | } 67 | -------------------------------------------------------------------------------- /config/ags/widget/notifications/NotificationPopups.ts: -------------------------------------------------------------------------------- 1 | import Notification from "./Notification" 2 | import options from "options" 3 | 4 | const notifications = await Service.import("notifications") 5 | const { transition } = options 6 | const { position } = options.notifications 7 | const { timeout, idle } = Utils 8 | 9 | function Animated(id: number) { 10 | const n = notifications.getNotification(id)! 11 | const widget = Notification(n) 12 | 13 | const inner = Widget.Revealer({ 14 | transition: "slide_left", 15 | transition_duration: transition.value, 16 | child: widget, 17 | }) 18 | 19 | const outer = Widget.Revealer({ 20 | transition: "slide_down", 21 | transition_duration: transition.value, 22 | child: inner, 23 | }) 24 | 25 | const box = Widget.Box({ 26 | hpack: "end", 27 | child: outer, 28 | }) 29 | 30 | idle(() => { 31 | outer.reveal_child = true 32 | timeout(transition.value, () => { 33 | inner.reveal_child = true 34 | }) 35 | }) 36 | 37 | return Object.assign(box, { 38 | dismiss() { 39 | inner.reveal_child = false 40 | timeout(transition.value, () => { 41 | outer.reveal_child = false 42 | timeout(transition.value, () => { 43 | box.destroy() 44 | }) 45 | }) 46 | }, 47 | }) 48 | } 49 | 50 | function PopupList() { 51 | const map: Map> = new Map 52 | const box = Widget.Box({ 53 | hpack: "end", 54 | vertical: true, 55 | css: options.notifications.width.bind().as(w => `min-width: ${w}px;`), 56 | }) 57 | 58 | function remove(_: unknown, id: number) { 59 | map.get(id)?.dismiss() 60 | map.delete(id) 61 | } 62 | 63 | return box 64 | .hook(notifications, (_, id: number) => { 65 | if (id !== undefined) { 66 | if (map.has(id)) 67 | remove(null, id) 68 | 69 | if (notifications.dnd) 70 | return 71 | 72 | const w = Animated(id) 73 | map.set(id, w) 74 | box.children = [w, ...box.children] 75 | } 76 | }, "notified") 77 | .hook(notifications, remove, "dismissed") 78 | .hook(notifications, remove, "closed") 79 | } 80 | 81 | export default (monitor: number) => Widget.Window({ 82 | monitor, 83 | name: `notifications${monitor}`, 84 | anchor: position.bind(), 85 | class_name: "notifications", 86 | child: Widget.Box({ 87 | css: "padding: 2px;", 88 | child: PopupList(), 89 | }), 90 | }) 91 | -------------------------------------------------------------------------------- /config/ags/widget/osd/Progress.ts: -------------------------------------------------------------------------------- 1 | import type Gtk from "gi://Gtk?version=3.0" 2 | import GLib from "gi://GLib?version=2.0" 3 | import { range } from "lib/utils" 4 | import options from "options" 5 | 6 | type ProgressProps = { 7 | height?: number 8 | width?: number 9 | vertical?: boolean 10 | child: Gtk.Widget 11 | } 12 | 13 | export default ({ 14 | height = 18, 15 | width = 180, 16 | vertical = false, 17 | child, 18 | }: ProgressProps) => { 19 | const fill = Widget.Box({ 20 | class_name: "fill", 21 | hexpand: vertical, 22 | vexpand: !vertical, 23 | hpack: vertical ? "fill" : "start", 24 | vpack: vertical ? "end" : "fill", 25 | child, 26 | }) 27 | 28 | const container = Widget.Box({ 29 | class_name: "progress", 30 | child: fill, 31 | css: ` 32 | min-width: ${width}px; 33 | min-height: ${height}px; 34 | `, 35 | }) 36 | 37 | let fill_size = 0 38 | let animations: number[] = [] 39 | 40 | return Object.assign(container, { 41 | setValue(value: number) { 42 | if (value < 0) 43 | return 44 | 45 | if (animations.length > 0) { 46 | for (const id of animations) 47 | GLib.source_remove(id) 48 | 49 | animations = [] 50 | } 51 | 52 | const axis = vertical ? "height" : "width" 53 | const axisv = vertical ? height : width 54 | const min = vertical ? width : height 55 | const preferred = (axisv - min) * value + min 56 | 57 | if (!fill_size) { 58 | fill_size = preferred 59 | fill.css = `min-${axis}: ${preferred}px;` 60 | return 61 | } 62 | 63 | const frames = options.transition.value / 10 64 | const goal = preferred - fill_size 65 | const step = goal / frames 66 | 67 | animations = range(frames, 0).map(i => Utils.timeout(5 * i, () => { 68 | fill_size += step 69 | fill.css = `min-${axis}: ${fill_size}px` 70 | animations.shift() 71 | })) 72 | }, 73 | }) 74 | } 75 | -------------------------------------------------------------------------------- /config/ags/widget/overview/Overview.ts: -------------------------------------------------------------------------------- 1 | import PopupWindow from "widget/PopupWindow" 2 | import Workspace from "./Workspace" 3 | import options from "options" 4 | import { range } from "lib/utils" 5 | 6 | const hyprland = await Service.import("hyprland") 7 | 8 | const Overview = (ws: number) => Widget.Box({ 9 | class_name: "overview horizontal", 10 | children: ws > 0 11 | ? range(ws).map(Workspace) 12 | : hyprland.workspaces 13 | .map(({ id }) => Workspace(id)) 14 | .sort((a, b) => a.attribute.id - b.attribute.id), 15 | 16 | setup: w => { 17 | if (ws > 0) 18 | return 19 | 20 | w.hook(hyprland, (w, id?: string) => { 21 | if (id === undefined) 22 | return 23 | 24 | w.children = w.children 25 | .filter(ch => ch.attribute.id !== Number(id)) 26 | }, "workspace-removed") 27 | w.hook(hyprland, (w, id?: string) => { 28 | if (id === undefined) 29 | return 30 | 31 | w.children = [...w.children, Workspace(Number(id))] 32 | .sort((a, b) => a.attribute.id - b.attribute.id) 33 | }, "workspace-added") 34 | }, 35 | }) 36 | 37 | export default () => PopupWindow({ 38 | name: "overview", 39 | layout: "center", 40 | child: options.overview.workspaces.bind().as(Overview), 41 | }) 42 | -------------------------------------------------------------------------------- /config/ags/widget/overview/Window.ts: -------------------------------------------------------------------------------- 1 | import { type Client } from "types/service/hyprland" 2 | import { createSurfaceFromWidget, icon } from "lib/utils" 3 | import Gdk from "gi://Gdk" 4 | import Gtk from "gi://Gtk?version=3.0" 5 | import options from "options" 6 | import icons from "lib/icons" 7 | 8 | const monochrome = options.overview.monochromeIcon 9 | const TARGET = [Gtk.TargetEntry.new("text/plain", Gtk.TargetFlags.SAME_APP, 0)] 10 | const hyprland = await Service.import("hyprland") 11 | const apps = await Service.import("applications") 12 | const dispatch = (args: string) => hyprland.messageAsync(`dispatch ${args}`) 13 | 14 | export default ({ address, size: [w, h], class: c, title }: Client) => Widget.Button({ 15 | class_name: "client", 16 | attribute: { address }, 17 | tooltip_text: `${title}`, 18 | child: Widget.Icon({ 19 | css: options.overview.scale.bind().as(v => ` 20 | min-width: ${(v / 100) * w}px; 21 | min-height: ${(v / 100) * h}px; 22 | `), 23 | icon: monochrome.bind().as(m => { 24 | const app = apps.list.find(app => app.match(c)) 25 | if (!app) 26 | return icons.fallback.executable + (m ? "-symbolic" : "") 27 | 28 | 29 | return icon( 30 | app.icon_name + (m ? "-symbolic" : ""), 31 | icons.fallback.executable + (m ? "-symbolic" : ""), 32 | ) 33 | }), 34 | }), 35 | on_secondary_click: () => dispatch(`closewindow address:${address}`), 36 | on_clicked: () => { 37 | dispatch(`focuswindow address:${address}`) 38 | App.closeWindow("overview") 39 | }, 40 | setup: btn => btn 41 | .on("drag-data-get", (_w, _c, data) => data.set_text(address, address.length)) 42 | .on("drag-begin", (_, context) => { 43 | Gtk.drag_set_icon_surface(context, createSurfaceFromWidget(btn)) 44 | btn.toggleClassName("hidden", true) 45 | }) 46 | .on("drag-end", () => btn.toggleClassName("hidden", false)) 47 | .drag_source_set(Gdk.ModifierType.BUTTON1_MASK, TARGET, Gdk.DragAction.COPY), 48 | }) 49 | -------------------------------------------------------------------------------- /config/ags/widget/overview/Workspace.ts: -------------------------------------------------------------------------------- 1 | import Window from "./Window" 2 | import Gdk from "gi://Gdk" 3 | import Gtk from "gi://Gtk?version=3.0" 4 | import options from "options" 5 | 6 | const TARGET = [Gtk.TargetEntry.new("text/plain", Gtk.TargetFlags.SAME_APP, 0)] 7 | const scale = (size: number) => (options.overview.scale.value / 100) * size 8 | const hyprland = await Service.import("hyprland") 9 | 10 | const dispatch = (args: string) => hyprland.messageAsync(`dispatch ${args}`) 11 | 12 | const size = (id: number) => { 13 | const def = { h: 1080, w: 1920 } 14 | const ws = hyprland.getWorkspace(id) 15 | if (!ws) 16 | return def 17 | 18 | const mon = hyprland.getMonitor(ws.monitorID) 19 | return mon ? { h: mon.height, w: mon.width } : def 20 | } 21 | 22 | export default (id: number) => { 23 | const fixed = Widget.Fixed() 24 | 25 | // TODO: early return if position is unchaged 26 | async function update() { 27 | const json = await hyprland.messageAsync("j/clients").catch(() => null) 28 | if (!json) 29 | return 30 | 31 | fixed.get_children().forEach(ch => ch.destroy()) 32 | const clients = JSON.parse(json) as typeof hyprland.clients 33 | clients 34 | .filter(({ workspace }) => workspace.id === id) 35 | .forEach(c => { 36 | const x = c.at[0] - (hyprland.getMonitor(c.monitor)?.x || 0) 37 | const y = c.at[1] - (hyprland.getMonitor(c.monitor)?.y || 0) 38 | c.mapped && fixed.put(Window(c), scale(x), scale(y)) 39 | }) 40 | fixed.show_all() 41 | } 42 | 43 | return Widget.Box({ 44 | attribute: { id }, 45 | tooltipText: `${id}`, 46 | class_name: "workspace", 47 | vpack: "center", 48 | css: options.overview.scale.bind().as(v => ` 49 | min-width: ${(v / 100) * size(id).w}px; 50 | min-height: ${(v / 100) * size(id).h}px; 51 | `), 52 | setup(box) { 53 | box.hook(options.overview.scale, update) 54 | box.hook(hyprland, update, "notify::clients") 55 | box.hook(hyprland.active.client, update) 56 | box.hook(hyprland.active.workspace, () => { 57 | box.toggleClassName("active", hyprland.active.workspace.id === id) 58 | }) 59 | }, 60 | child: Widget.EventBox({ 61 | expand: true, 62 | on_primary_click: () => { 63 | App.closeWindow("overview") 64 | dispatch(`workspace ${id}`) 65 | }, 66 | setup: eventbox => { 67 | eventbox.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY) 68 | eventbox.connect("drag-data-received", (_w, _c, _x, _y, data) => { 69 | const address = new TextDecoder().decode(data.get_data()) 70 | dispatch(`movetoworkspacesilent ${id},address:${address}`) 71 | }) 72 | }, 73 | child: fixed, 74 | }), 75 | }) 76 | } 77 | -------------------------------------------------------------------------------- /config/ags/widget/powermenu/PowerMenu.ts: -------------------------------------------------------------------------------- 1 | import PopupWindow from "widget/PopupWindow" 2 | import powermenu, { type Action } from "service/powermenu" 3 | import icons from "lib/icons" 4 | import options from "options" 5 | import type Gtk from "gi://Gtk?version=3.0" 6 | 7 | const { layout, labels } = options.powermenu 8 | 9 | const SysButton = (action: Action, label: string) => Widget.Button({ 10 | on_clicked: () => powermenu.action(action), 11 | child: Widget.Box({ 12 | vertical: true, 13 | class_name: "system-button", 14 | children: [ 15 | Widget.Icon(icons.powermenu[action]), 16 | Widget.Label({ 17 | label, 18 | visible: labels.bind(), 19 | }), 20 | ], 21 | }), 22 | }) 23 | 24 | export default () => PopupWindow({ 25 | name: "powermenu", 26 | transition: "crossfade", 27 | child: Widget.Box({ 28 | class_name: "powermenu horizontal", 29 | setup: self => self.hook(layout, () => { 30 | self.toggleClassName("box", layout.value === "box") 31 | self.toggleClassName("line", layout.value === "line") 32 | }), 33 | children: layout.bind().as(layout => { 34 | switch (layout) { 35 | case "line": return [ 36 | SysButton("shutdown", "Shutdown"), 37 | SysButton("logout", "Log Out"), 38 | SysButton("reboot", "Reboot"), 39 | SysButton("sleep", "Sleep"), 40 | ] 41 | case "box": return [ 42 | Widget.Box( 43 | { vertical: true }, 44 | SysButton("shutdown", "Shutdown"), 45 | SysButton("logout", "Log Out"), 46 | ), 47 | Widget.Box( 48 | { vertical: true }, 49 | SysButton("reboot", "Reboot"), 50 | SysButton("sleep", "Sleep"), 51 | ), 52 | ] 53 | } 54 | }), 55 | }), 56 | }) 57 | -------------------------------------------------------------------------------- /config/ags/widget/powermenu/Verification.ts: -------------------------------------------------------------------------------- 1 | import PopupWindow from "widget/PopupWindow" 2 | import powermenu from "service/powermenu" 3 | 4 | export default () => PopupWindow({ 5 | name: "verification", 6 | transition: "crossfade", 7 | child: Widget.Box({ 8 | class_name: "verification", 9 | vertical: true, 10 | children: [ 11 | Widget.Box({ 12 | class_name: "text-box", 13 | vertical: true, 14 | children: [ 15 | Widget.Label({ 16 | class_name: "title", 17 | label: powermenu.bind("title"), 18 | }), 19 | Widget.Label({ 20 | class_name: "desc", 21 | label: "Are you sure?", 22 | }), 23 | ], 24 | }), 25 | Widget.Box({ 26 | class_name: "buttons horizontal", 27 | vexpand: true, 28 | vpack: "end", 29 | homogeneous: true, 30 | children: [ 31 | Widget.Button({ 32 | child: Widget.Label("No"), 33 | on_clicked: () => App.toggleWindow("verification"), 34 | setup: self => self.hook(App, (_, name: string, visible: boolean) => { 35 | if (name === "verification" && visible) 36 | self.grab_focus() 37 | }), 38 | }), 39 | Widget.Button({ 40 | child: Widget.Label("Yes"), 41 | on_clicked: powermenu.exec, 42 | }), 43 | ], 44 | }), 45 | ], 46 | }), 47 | }) 48 | -------------------------------------------------------------------------------- /config/ags/widget/quicksettings/QuickSettings.ts: -------------------------------------------------------------------------------- 1 | import type Gtk from "gi://Gtk?version=3.0" 2 | import { ProfileSelector, ProfileToggle } from "./widgets/PowerProfile" 3 | import { Header } from "./widgets/Header" 4 | import { Volume, Microphone, SinkSelector, AppMixer } from "./widgets/Volume" 5 | import { Brightness } from "./widgets/Brightness" 6 | import { NetworkToggle, WifiSelection } from "./widgets/Network" 7 | import { BluetoothToggle, BluetoothDevices } from "./widgets/Bluetooth" 8 | import { DND } from "./widgets/DND" 9 | import { DarkModeToggle } from "./widgets/DarkMode" 10 | import { MicMute } from "./widgets/MicMute" 11 | import { Media } from "./widgets/Media" 12 | import PopupWindow from "widget/PopupWindow" 13 | import options from "options" 14 | 15 | const { bar, quicksettings } = options 16 | const media = (await Service.import("mpris")).bind("players") 17 | const layout = Utils.derive([bar.position, quicksettings.position], (bar, qs) => 18 | `${bar}-${qs}` as const, 19 | ) 20 | 21 | const Row = ( 22 | toggles: Array<() => Gtk.Widget> = [], 23 | menus: Array<() => Gtk.Widget> = [], 24 | ) => Widget.Box({ 25 | vertical: true, 26 | children: [ 27 | Widget.Box({ 28 | homogeneous: true, 29 | class_name: "row horizontal", 30 | children: toggles.map(w => w()), 31 | }), 32 | ...menus.map(w => w()), 33 | ], 34 | }) 35 | 36 | const Settings = () => Widget.Box({ 37 | vertical: true, 38 | class_name: "quicksettings vertical", 39 | css: quicksettings.width.bind().as(w => `min-width: ${w}px;`), 40 | children: [ 41 | Header(), 42 | Widget.Box({ 43 | class_name: "sliders-box vertical", 44 | vertical: true, 45 | children: [ 46 | Row( 47 | [Volume], 48 | [SinkSelector, AppMixer], 49 | ), 50 | Microphone(), 51 | Brightness(), 52 | ], 53 | }), 54 | Row( 55 | [NetworkToggle, BluetoothToggle], 56 | [WifiSelection, BluetoothDevices], 57 | ), 58 | Row( 59 | [ProfileToggle, DarkModeToggle], 60 | [ProfileSelector], 61 | ), 62 | Row([MicMute, DND]), 63 | Widget.Box({ 64 | visible: media.as(l => l.length > 0), 65 | child: Media(), 66 | }), 67 | ], 68 | }) 69 | 70 | const QuickSettings = () => PopupWindow({ 71 | name: "quicksettings", 72 | exclusivity: "exclusive", 73 | transition: bar.position.bind().as(pos => pos === "top" ? "slide_down" : "slide_up"), 74 | layout: layout.value, 75 | child: Settings(), 76 | }) 77 | 78 | export function setupQuickSettings() { 79 | App.addWindow(QuickSettings()) 80 | layout.connect("changed", () => { 81 | App.removeWindow("quicksettings") 82 | App.addWindow(QuickSettings()) 83 | }) 84 | } 85 | -------------------------------------------------------------------------------- /config/ags/widget/quicksettings/widgets/Bluetooth.ts: -------------------------------------------------------------------------------- 1 | import { type BluetoothDevice } from "types/service/bluetooth" 2 | import { Menu, ArrowToggleButton } from "../ToggleButton" 3 | import icons from "lib/icons" 4 | 5 | const bluetooth = await Service.import("bluetooth") 6 | 7 | export const BluetoothToggle = () => ArrowToggleButton({ 8 | name: "bluetooth", 9 | icon: bluetooth.bind("enabled").as(p => icons.bluetooth[p ? "enabled" : "disabled"]), 10 | label: Utils.watch("Disabled", bluetooth, () => { 11 | if (!bluetooth.enabled) 12 | return "Disabled" 13 | 14 | if (bluetooth.connected_devices.length === 1) 15 | return bluetooth.connected_devices[0].alias 16 | 17 | return `${bluetooth.connected_devices.length} Connected` 18 | }), 19 | connection: [bluetooth, () => bluetooth.enabled], 20 | deactivate: () => bluetooth.enabled = false, 21 | activate: () => bluetooth.enabled = true, 22 | }) 23 | 24 | const DeviceItem = (device: BluetoothDevice) => Widget.Box({ 25 | children: [ 26 | Widget.Icon(device.icon_name + "-symbolic"), 27 | Widget.Label(device.name), 28 | Widget.Label({ 29 | label: `${device.battery_percentage}%`, 30 | visible: device.bind("battery_percentage").as(p => p > 0), 31 | }), 32 | Widget.Box({ hexpand: true }), 33 | Widget.Spinner({ 34 | active: device.bind("connecting"), 35 | visible: device.bind("connecting"), 36 | }), 37 | Widget.Switch({ 38 | active: device.connected, 39 | visible: device.bind("connecting").as(p => !p), 40 | setup: self => self.on("notify::active", () => { 41 | device.setConnection(self.active) 42 | }), 43 | }), 44 | ], 45 | }) 46 | 47 | export const BluetoothDevices = () => Menu({ 48 | name: "bluetooth", 49 | icon: icons.bluetooth.disabled, 50 | title: "Bluetooth", 51 | content: [ 52 | Widget.Box({ 53 | class_name: "bluetooth-devices", 54 | hexpand: true, 55 | vertical: true, 56 | children: bluetooth.bind("devices").as(ds => ds 57 | .filter(d => d.name) 58 | .map(DeviceItem)), 59 | }), 60 | ], 61 | }) 62 | -------------------------------------------------------------------------------- /config/ags/widget/quicksettings/widgets/Brightness.ts: -------------------------------------------------------------------------------- 1 | import icons from "lib/icons" 2 | import brightness from "service/brightness" 3 | 4 | const BrightnessSlider = () => Widget.Slider({ 5 | draw_value: false, 6 | hexpand: true, 7 | value: brightness.bind("screen"), 8 | on_change: ({ value }) => brightness.screen = value, 9 | }) 10 | 11 | export const Brightness = () => Widget.Box({ 12 | class_name: "brightness", 13 | children: [ 14 | Widget.Button({ 15 | vpack: "center", 16 | child: Widget.Icon(icons.brightness.indicator), 17 | on_clicked: () => brightness.screen = 0, 18 | tooltip_text: brightness.bind("screen").as(v => 19 | `Screen Brightness: ${Math.floor(v * 100)}%`), 20 | }), 21 | BrightnessSlider(), 22 | ], 23 | }) 24 | -------------------------------------------------------------------------------- /config/ags/widget/quicksettings/widgets/DND.ts: -------------------------------------------------------------------------------- 1 | import { SimpleToggleButton } from "../ToggleButton" 2 | import icons from "lib/icons" 3 | 4 | const n = await Service.import("notifications") 5 | const dnd = n.bind("dnd") 6 | 7 | export const DND = () => SimpleToggleButton({ 8 | icon: dnd.as(dnd => icons.notifications[dnd ? "silent" : "noisy"]), 9 | label: dnd.as(dnd => dnd ? "Silent" : "Noisy"), 10 | toggle: () => n.dnd = !n.dnd, 11 | connection: [n, () => n.dnd], 12 | }) 13 | -------------------------------------------------------------------------------- /config/ags/widget/quicksettings/widgets/DarkMode.ts: -------------------------------------------------------------------------------- 1 | import { SimpleToggleButton } from "../ToggleButton" 2 | import icons from "lib/icons" 3 | import options from "options" 4 | 5 | const { scheme } = options.theme 6 | 7 | export const DarkModeToggle = () => SimpleToggleButton({ 8 | icon: scheme.bind().as(s => icons.color[s]), 9 | label: scheme.bind().as(s => s === "dark" ? "Dark" : "Light"), 10 | toggle: () => scheme.value = scheme.value === "dark" ? "light" : "dark", 11 | connection: [scheme, () => scheme.value === "dark"], 12 | }) 13 | -------------------------------------------------------------------------------- /config/ags/widget/quicksettings/widgets/Header.ts: -------------------------------------------------------------------------------- 1 | import icons from "lib/icons" 2 | import { uptime } from "lib/variables" 3 | import options from "options" 4 | import powermenu, { Action } from "service/powermenu" 5 | 6 | const battery = await Service.import("battery") 7 | const { image, size } = options.quicksettings.avatar 8 | 9 | function up(up: number) { 10 | const h = Math.floor(up / 60) 11 | const m = Math.floor(up % 60) 12 | return `${h}h ${m < 10 ? "0" + m : m}m` 13 | } 14 | 15 | const Avatar = () => Widget.Box({ 16 | class_name: "avatar", 17 | css: Utils.merge([image.bind(), size.bind()], (img, size) => ` 18 | min-width: ${size}px; 19 | min-height: ${size}px; 20 | background-image: url('${img}'); 21 | background-size: cover; 22 | `), 23 | }) 24 | 25 | const SysButton = (action: Action) => Widget.Button({ 26 | vpack: "center", 27 | child: Widget.Icon(icons.powermenu[action]), 28 | on_clicked: () => powermenu.action(action), 29 | }) 30 | 31 | export const Header = () => Widget.Box( 32 | { class_name: "header horizontal" }, 33 | Avatar(), 34 | Widget.Box({ 35 | vertical: true, 36 | vpack: "center", 37 | children: [ 38 | Widget.Box({ 39 | visible: battery.bind("available"), 40 | children: [ 41 | Widget.Icon({ icon: battery.bind("icon_name") }), 42 | Widget.Label({ label: battery.bind("percent").as(p => `${p}%`) }), 43 | ], 44 | }), 45 | Widget.Box([ 46 | Widget.Icon({ icon: icons.ui.time }), 47 | Widget.Label({ label: uptime.bind().as(up) }), 48 | ]), 49 | ], 50 | }), 51 | Widget.Box({ hexpand: true }), 52 | Widget.Button({ 53 | vpack: "center", 54 | child: Widget.Icon(icons.ui.settings), 55 | on_clicked: () => { 56 | App.closeWindow("quicksettings") 57 | App.closeWindow("settings-dialog") 58 | App.openWindow("settings-dialog") 59 | }, 60 | }), 61 | SysButton("logout"), 62 | SysButton("shutdown"), 63 | ) 64 | -------------------------------------------------------------------------------- /config/ags/widget/quicksettings/widgets/MicMute.ts: -------------------------------------------------------------------------------- 1 | import { SimpleToggleButton } from "../ToggleButton" 2 | import icons from "lib/icons" 3 | const { microphone } = await Service.import("audio") 4 | 5 | const icon = () => microphone.is_muted || microphone.stream?.is_muted 6 | ? icons.audio.mic.muted 7 | : icons.audio.mic.high 8 | 9 | const label = () => microphone.is_muted || microphone.stream?.is_muted 10 | ? "Muted" 11 | : "Unmuted" 12 | 13 | export const MicMute = () => SimpleToggleButton({ 14 | icon: Utils.watch(icon(), microphone, icon), 15 | label: Utils.watch(label(), microphone, label), 16 | toggle: () => microphone.is_muted = !microphone.is_muted, 17 | connection: [microphone, () => microphone?.is_muted || false], 18 | }) 19 | -------------------------------------------------------------------------------- /config/ags/widget/quicksettings/widgets/Network.ts: -------------------------------------------------------------------------------- 1 | import { Menu, ArrowToggleButton } from "../ToggleButton" 2 | import icons from "lib/icons.js" 3 | import { dependencies, sh } from "lib/utils" 4 | import options from "options" 5 | const { wifi } = await Service.import("network") 6 | 7 | export const NetworkToggle = () => ArrowToggleButton({ 8 | name: "network", 9 | icon: wifi.bind("icon_name"), 10 | label: wifi.bind("ssid").as(ssid => ssid || "Not Connected"), 11 | connection: [wifi, () => wifi.enabled], 12 | deactivate: () => wifi.enabled = false, 13 | activate: () => { 14 | wifi.enabled = true 15 | wifi.scan() 16 | }, 17 | }) 18 | 19 | export const WifiSelection = () => Menu({ 20 | name: "network", 21 | icon: wifi.bind("icon_name"), 22 | title: "Wifi Selection", 23 | content: [ 24 | Widget.Box({ 25 | vertical: true, 26 | setup: self => self.hook(wifi, () => self.children = 27 | wifi.access_points 28 | .sort((a, b) => b.strength - a.strength) 29 | .slice(0, 10) 30 | .map(ap => Widget.Button({ 31 | on_clicked: () => { 32 | if (dependencies("nmcli")) 33 | Utils.execAsync(`nmcli device wifi connect ${ap.bssid}`) 34 | }, 35 | child: Widget.Box({ 36 | children: [ 37 | Widget.Icon(ap.iconName), 38 | Widget.Label(ap.ssid || ""), 39 | Widget.Icon({ 40 | icon: icons.ui.tick, 41 | hexpand: true, 42 | hpack: "end", 43 | setup: self => Utils.idle(() => { 44 | if (!self.is_destroyed) 45 | self.visible = ap.active 46 | }), 47 | }), 48 | ], 49 | }), 50 | })), 51 | ), 52 | }), 53 | Widget.Separator(), 54 | Widget.Button({ 55 | on_clicked: () => sh(options.quicksettings.networkSettings.value), 56 | child: Widget.Box({ 57 | children: [ 58 | Widget.Icon(icons.ui.settings), 59 | Widget.Label("Network"), 60 | ], 61 | }), 62 | }), 63 | ], 64 | }) 65 | -------------------------------------------------------------------------------- /config/ags/widget/settings/Group.ts: -------------------------------------------------------------------------------- 1 | import icons from "lib/icons" 2 | import Row from "./Row" 3 | 4 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 5 | export default (title: string, ...rows: ReturnType>[]) => Widget.Box( 6 | { 7 | class_name: "group", 8 | vertical: true, 9 | }, 10 | Widget.Box([ 11 | Widget.Label({ 12 | hpack: "start", 13 | vpack: "end", 14 | class_name: "group-title", 15 | label: title, 16 | setup: w => Utils.idle(() => w.visible = !!title), 17 | }), 18 | title ? Widget.Button({ 19 | hexpand: true, 20 | hpack: "end", 21 | child: Widget.Icon(icons.ui.refresh), 22 | class_name: "group-reset", 23 | sensitive: Utils.merge( 24 | rows.map(({ attribute: { opt } }) => opt.bind().as(v => v !== opt.initial)), 25 | (...values) => values.some(b => b), 26 | ), 27 | on_clicked: () => rows.forEach(row => row.attribute.opt.reset()), 28 | }) : Widget.Box(), 29 | ]), 30 | Widget.Box({ 31 | vertical: true, 32 | children: rows, 33 | }), 34 | ) 35 | -------------------------------------------------------------------------------- /config/ags/widget/settings/Page.ts: -------------------------------------------------------------------------------- 1 | import Group from "./Group" 2 | 3 | export default ( 4 | name: string, 5 | icon: string, 6 | ...groups: ReturnType>[] 7 | ) => Widget.Box({ 8 | class_name: "page", 9 | attribute: { name, icon }, 10 | child: Widget.Scrollable({ 11 | css: "min-height: 300px;", 12 | child: Widget.Box({ 13 | class_name: "page-content", 14 | vexpand: true, 15 | vertical: true, 16 | children: groups, 17 | }), 18 | }), 19 | }) 20 | -------------------------------------------------------------------------------- /config/ags/widget/settings/Row.ts: -------------------------------------------------------------------------------- 1 | import { Opt } from "lib/option" 2 | import Setter from "./Setter" 3 | import icons from "lib/icons" 4 | 5 | export type RowProps = { 6 | opt: Opt 7 | title: string 8 | note?: string 9 | type?: 10 | | "number" 11 | | "color" 12 | | "float" 13 | | "object" 14 | | "string" 15 | | "enum" 16 | | "boolean" 17 | | "img" 18 | | "font" 19 | enums?: string[] 20 | max?: number 21 | min?: number 22 | } 23 | 24 | export default (props: RowProps) => Widget.Box( 25 | { 26 | attribute: { opt: props.opt }, 27 | class_name: "row", 28 | tooltip_text: props.note ? `note: ${props.note}` : "", 29 | }, 30 | Widget.Box( 31 | { vertical: true, vpack: "center" }, 32 | Widget.Label({ 33 | xalign: 0, 34 | class_name: "row-title", 35 | label: props.title, 36 | }), 37 | Widget.Label({ 38 | xalign: 0, 39 | class_name: "id", 40 | label: props.opt.id, 41 | }), 42 | ), 43 | Widget.Box({ hexpand: true }), 44 | Widget.Box( 45 | { vpack: "center" }, 46 | Setter(props), 47 | ), 48 | Widget.Button({ 49 | vpack: "center", 50 | class_name: "reset", 51 | child: Widget.Icon(icons.ui.refresh), 52 | on_clicked: () => props.opt.reset(), 53 | sensitive: props.opt.bind().as(v => v !== props.opt.initial), 54 | }), 55 | ) 56 | -------------------------------------------------------------------------------- /config/ags/widget/settings/SettingsDialog.ts: -------------------------------------------------------------------------------- 1 | import RegularWindow from "widget/RegularWindow" 2 | import layout from "./layout" 3 | import icons from "lib/icons" 4 | import options from "options" 5 | 6 | const current = Variable(layout[0].attribute.name) 7 | 8 | const Header = () => Widget.CenterBox({ 9 | class_name: "header", 10 | start_widget: Widget.Button({ 11 | class_name: "reset", 12 | on_clicked: options.reset, 13 | hpack: "start", 14 | vpack: "start", 15 | child: Widget.Icon(icons.ui.refresh), 16 | tooltip_text: "Reset", 17 | }), 18 | center_widget: Widget.Box({ 19 | class_name: "pager horizontal", 20 | children: layout.map(({ attribute: { name, icon } }) => Widget.Button({ 21 | xalign: 0, 22 | class_name: current.bind().as(v => `${v === name ? "active" : ""}`), 23 | on_clicked: () => current.value = name, 24 | child: Widget.Box([ 25 | Widget.Icon(icon), 26 | Widget.Label(name), 27 | ]), 28 | })), 29 | }), 30 | end_widget: Widget.Button({ 31 | class_name: "close", 32 | hpack: "end", 33 | vpack: "start", 34 | child: Widget.Icon(icons.ui.close), 35 | on_clicked: () => App.closeWindow("settings-dialog"), 36 | }), 37 | }) 38 | 39 | const PagesStack = () => Widget.Stack({ 40 | transition: "slide_left_right", 41 | children: layout.reduce((obj, page) => ({ ...obj, [page.attribute.name]: page }), {}), 42 | shown: current.bind() as never, 43 | }) 44 | 45 | export default () => RegularWindow({ 46 | name: "settings-dialog", 47 | class_name: "settings-dialog", 48 | title: "Settings", 49 | setup(win) { 50 | win.on("delete-event", () => { 51 | win.hide() 52 | return true 53 | }) 54 | win.set_default_size(500, 600) 55 | }, 56 | child: Widget.Box({ 57 | vertical: true, 58 | children: [ 59 | Header(), 60 | PagesStack(), 61 | ], 62 | }), 63 | }) 64 | -------------------------------------------------------------------------------- /config/ags/widget/settings/Wallpaper.ts: -------------------------------------------------------------------------------- 1 | import wallpaper from "service/wallpaper" 2 | 3 | export default () => Widget.Box( 4 | { class_name: "row wallpaper" }, 5 | Widget.Box( 6 | { vertical: true }, 7 | Widget.Label({ 8 | xalign: 0, 9 | class_name: "row-title", 10 | label: "Wallpaper", 11 | vpack: "start", 12 | }), 13 | Widget.Button({ 14 | on_clicked: wallpaper.random, 15 | label: "Random", 16 | }), 17 | Widget.FileChooserButton({ 18 | on_file_set: ({ uri }) => wallpaper.set(uri!.replace("file://", "")), 19 | }), 20 | ), 21 | Widget.Box({ hexpand: true }), 22 | Widget.Box({ 23 | class_name: "preview", 24 | css: wallpaper.bind("wallpaper").as(wp => ` 25 | min-height: 120px; 26 | min-width: 200px; 27 | background-image: url('${wp}'); 28 | background-size: cover; 29 | `), 30 | }), 31 | ) 32 | -------------------------------------------------------------------------------- /config/alacritty/alacritty.toml: -------------------------------------------------------------------------------- 1 | 2 | [colors] 3 | draw_bold_text_with_bright_colors = true 4 | 5 | [font] 6 | size = 10 7 | 8 | [font.bold] 9 | family = "JetbrainsMono Nerd Font" 10 | style = "Bold" 11 | 12 | [font.bold_italic] 13 | family = "JetbrainsMono Nerd Font" 14 | style = "Bold Italic" 15 | 16 | [font.italic] 17 | family = "JetbrainsMono Nerd Font" 18 | style = "Italic" 19 | 20 | [font.normal] 21 | family = "JetbrainsMono Nerd Font" 22 | style = "Regular" 23 | 24 | [[keyboard.bindings]] 25 | action = "SpawnNewInstance" 26 | key = "Return" 27 | mods = "Super|Shift" 28 | 29 | [scrolling] 30 | history = 10000 31 | multiplier = 3 32 | 33 | [selection] 34 | save_to_clipboard = false 35 | 36 | [terminal.shell] 37 | program = "/usr/bin/zsh" 38 | 39 | [general] 40 | import = ["~/.cache/wal/color-alacritty.toml"] 41 | 42 | [window] 43 | opacity = 0.8 44 | 45 | [window.class] 46 | general = "Alacritty" 47 | instance = "Alacritty" 48 | 49 | [window.padding] 50 | x = 1 51 | y = 5 52 | 53 | -------------------------------------------------------------------------------- /config/btop/themes/catppuccin_frappe.theme: -------------------------------------------------------------------------------- 1 | theme[main_bg]="#303446" 2 | theme[main_fg]="#C6D0F5" 3 | theme[title]="#C6D0F5" 4 | theme[hi_fg]="#8CAAEE" 5 | theme[selected_bg]="#51576D" 6 | theme[selected_fg]="#8CAAEE" 7 | theme[inactive_fg]="#838BA7" 8 | theme[graph_text]="#F2D5CF" 9 | theme[meter_bg]="#51576D" 10 | theme[proc_misc]="#F2D5CF" 11 | theme[cpu_box]="#85C1DC" 12 | theme[mem_box]="#A6D189" 13 | theme[net_box]="#CA9EE6" 14 | theme[proc_box]="#EEBEBE" 15 | theme[div_line]="#737994" 16 | theme[temp_start]="#E5C890" 17 | theme[temp_mid]="#EF9F76" 18 | theme[temp_end]="#E78284" 19 | theme[cpu_start]="#85C1DC" 20 | theme[cpu_mid]="#99D1DB" 21 | theme[cpu_end]="#81C8BE" 22 | theme[free_start]="#81C8BE" 23 | theme[free_mid]="#81C8BE" 24 | theme[free_end]="#A6D189" 25 | theme[cached_start]="#F4B8E4" 26 | theme[cached_mid]="#F4B8E4" 27 | theme[cached_end]="#CA9EE6" 28 | theme[available_start]="#F2D5CF" 29 | theme[available_mid]="#EEBEBE" 30 | theme[available_end]="#EEBEBE" 31 | theme[used_start]="#EF9F76" 32 | theme[used_mid]="#EF9F76" 33 | theme[used_end]="#E78284" 34 | theme[download_start]="#BABBF1" 35 | theme[download_mid]="#BABBF1" 36 | theme[download_end]="#CA9EE6" 37 | theme[upload_start]="#BABBF1" 38 | theme[upload_mid]="#BABBF1" 39 | theme[upload_end]="#CA9EE6" 40 | theme[process_start]="#85C1DC" 41 | theme[process_mid]="#99D1DB" 42 | theme[process_end]="#81C8BE" 43 | -------------------------------------------------------------------------------- /config/btop/themes/catppuccin_latte.theme: -------------------------------------------------------------------------------- 1 | theme[main_bg]="#EFF1F5" 2 | theme[main_fg]="#4C4F69" 3 | theme[title]="#4C4F69" 4 | theme[hi_fg]="#1E66F5" 5 | theme[selected_bg]="#BCC0CC" 6 | theme[selected_fg]="#1E66F5" 7 | theme[inactive_fg]="#8C8FA1" 8 | theme[graph_text]="#DC8A78" 9 | theme[meter_bg]="#BCC0CC" 10 | theme[proc_misc]="#DC8A78" 11 | theme[cpu_box]="#209FB5" 12 | theme[mem_box]="#40A02B" 13 | theme[net_box]="#8839EF" 14 | theme[proc_box]="#DD7878" 15 | theme[div_line]="#9CA0B0" 16 | theme[temp_start]="#DF8E1D" 17 | theme[temp_mid]="#FE640B" 18 | theme[temp_end]="#D20F39" 19 | theme[cpu_start]="#209FB5" 20 | theme[cpu_mid]="#04A5E5" 21 | theme[cpu_end]="#179299" 22 | theme[free_start]="#179299" 23 | theme[free_mid]="#179299" 24 | theme[free_end]="#40A02B" 25 | theme[cached_start]="#EA76CB" 26 | theme[cached_mid]="#EA76CB" 27 | theme[cached_end]="#8839EF" 28 | theme[available_start]="#DC8A78" 29 | theme[available_mid]="#DD7878" 30 | theme[available_end]="#DD7878" 31 | theme[used_start]="#FE640B" 32 | theme[used_mid]="#FE640B" 33 | theme[used_end]="#D20F39" 34 | theme[download_start]="#7287FD" 35 | theme[download_mid]="#7287FD" 36 | theme[download_end]="#8839EF" 37 | theme[upload_start]="#7287FD" 38 | theme[upload_mid]="#7287FD" 39 | theme[upload_end]="#8839EF" 40 | theme[process_start]="#209FB5" 41 | theme[process_mid]="#04A5E5" 42 | theme[process_end]="#179299" 43 | -------------------------------------------------------------------------------- /config/btop/themes/catppuccin_macchiato.theme: -------------------------------------------------------------------------------- 1 | theme[main_bg]="#24273A" 2 | theme[main_fg]="#CAD3F5" 3 | theme[title]="#CAD3F5" 4 | theme[hi_fg]="#8AADF4" 5 | theme[selected_bg]="#494D64" 6 | theme[selected_fg]="#8AADF4" 7 | theme[inactive_fg]="#8087A2" 8 | theme[graph_text]="#F4DBD6" 9 | theme[meter_bg]="#494D64" 10 | theme[proc_misc]="#F4DBD6" 11 | theme[cpu_box]="#7DC4E4" 12 | theme[mem_box]="#A6DA95" 13 | theme[net_box]="#C6A0F6" 14 | theme[proc_box]="#F0C6C6" 15 | theme[div_line]="#6E738D" 16 | theme[temp_start]="#EED49F" 17 | theme[temp_mid]="#F5A97F" 18 | theme[temp_end]="#ED8796" 19 | theme[cpu_start]="#7DC4E4" 20 | theme[cpu_mid]="#91D7E3" 21 | theme[cpu_end]="#8BD5CA" 22 | theme[free_start]="#8BD5CA" 23 | theme[free_mid]="#8BD5CA" 24 | theme[free_end]="#A6DA95" 25 | theme[cached_start]="#F5BDE6" 26 | theme[cached_mid]="#F5BDE6" 27 | theme[cached_end]="#C6A0F6" 28 | theme[available_start]="#F4DBD6" 29 | theme[available_mid]="#F0C6C6" 30 | theme[available_end]="#F0C6C6" 31 | theme[used_start]="#F5A97F" 32 | theme[used_mid]="#F5A97F" 33 | theme[used_end]="#ED8796" 34 | theme[download_start]="#B7BDF8" 35 | theme[download_mid]="#B7BDF8" 36 | theme[download_end]="#C6A0F6" 37 | theme[upload_start]="#B7BDF8" 38 | theme[upload_mid]="#B7BDF8" 39 | theme[upload_end]="#C6A0F6" 40 | theme[process_start]="#7DC4E4" 41 | theme[process_mid]="#91D7E3" 42 | theme[process_end]="#8BD5CA" 43 | -------------------------------------------------------------------------------- /config/btop/themes/catppuccin_mocha.theme: -------------------------------------------------------------------------------- 1 | theme[main_bg]="#1E1E2E" 2 | theme[main_fg]="#CDD6F4" 3 | theme[title]="#CDD6F4" 4 | theme[hi_fg]="#89B4FA" 5 | theme[selected_bg]="#45475A" 6 | theme[selected_fg]="#89B4FA" 7 | theme[inactive_fg]="#7F849C" 8 | theme[graph_text]="#F5E0DC" 9 | theme[meter_bg]="#45475A" 10 | theme[proc_misc]="#F5E0DC" 11 | theme[cpu_box]="#74C7EC" 12 | theme[mem_box]="#A6E3A1" 13 | theme[net_box]="#CBA6F7" 14 | theme[proc_box]="#F2CDCD" 15 | theme[div_line]="#6C7086" 16 | theme[temp_start]="#F9E2AF" 17 | theme[temp_mid]="#FAB387" 18 | theme[temp_end]="#F38BA8" 19 | theme[cpu_start]="#74C7EC" 20 | theme[cpu_mid]="#89DCEB" 21 | theme[cpu_end]="#94E2D5" 22 | theme[free_start]="#94E2D5" 23 | theme[free_mid]="#94E2D5" 24 | theme[free_end]="#A6E3A1" 25 | theme[cached_start]="#F5C2E7" 26 | theme[cached_mid]="#F5C2E7" 27 | theme[cached_end]="#CBA6F7" 28 | theme[available_start]="#F5E0DC" 29 | theme[available_mid]="#F2CDCD" 30 | theme[available_end]="#F2CDCD" 31 | theme[used_start]="#FAB387" 32 | theme[used_mid]="#FAB387" 33 | theme[used_end]="#F38BA8" 34 | theme[download_start]="#B4BEFE" 35 | theme[download_mid]="#B4BEFE" 36 | theme[download_end]="#CBA6F7" 37 | theme[upload_start]="#B4BEFE" 38 | theme[upload_mid]="#B4BEFE" 39 | theme[upload_end]="#CBA6F7" 40 | theme[process_start]="#74C7EC" 41 | theme[process_mid]="#89DCEB" 42 | theme[process_end]="#94E2D5" 43 | -------------------------------------------------------------------------------- /config/cava/shaders/bar_spectrum.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | in vec2 fragCoord; 4 | out vec4 fragColor; 5 | 6 | // bar values. defaults to left channels first (low to high), then right (high to low). 7 | uniform float bars[512]; 8 | 9 | uniform int bars_count; // number of bars (left + right) (configurable) 10 | uniform int bar_width; // bar width (configurable), not used here 11 | uniform int bar_spacing; // space bewteen bars (configurable) 12 | 13 | uniform vec3 u_resolution; // window resolution 14 | 15 | //colors, configurable in cava config file (r,g,b) (0.0 - 1.0) 16 | uniform vec3 bg_color; // background color 17 | uniform vec3 fg_color; // foreground color 18 | 19 | uniform int gradient_count; 20 | uniform vec3 gradient_colors[8]; // gradient colors 21 | 22 | vec3 normalize_C(float y,vec3 col_1, vec3 col_2, float y_min, float y_max) 23 | { 24 | //create color based on fraction of this color and next color 25 | float yr = (y - y_min) / (y_max - y_min); 26 | return col_1 * (1.0 - yr) + col_2 * yr; 27 | } 28 | 29 | void main() 30 | { 31 | // find which bar to use based on where we are on the x axis 32 | float x = u_resolution.x * fragCoord.x; 33 | int bar = int(bars_count * fragCoord.x); 34 | 35 | //calculate a bar size 36 | float bar_size = u_resolution.x / bars_count; 37 | 38 | //the y coordinate and bar values are the same 39 | float y = bars[bar]; 40 | 41 | // make sure there is a thin line at bottom 42 | if (y * u_resolution.y < 1.0) 43 | { 44 | y = 1.0 / u_resolution.y; 45 | } 46 | 47 | //draw the bar up to current height 48 | if (y > fragCoord.y) 49 | { 50 | //make some space between bars basen on settings 51 | if (x > (bar + 1) * (bar_size) - bar_spacing) 52 | { 53 | fragColor = vec4(bg_color,1.0); 54 | } 55 | else 56 | { 57 | if (gradient_count == 0) 58 | { 59 | fragColor = vec4(fg_color,1.0); 60 | } 61 | else 62 | { 63 | //find which color in the configured gradient we are at 64 | int color = int((gradient_count - 1) * fragCoord.y); 65 | 66 | //find where on y this and next color is supposed to be 67 | float y_min = color / (gradient_count - 1.0); 68 | float y_max = (color + 1.0) / (gradient_count - 1.0); 69 | 70 | //make color 71 | fragColor = vec4(normalize_C(fragCoord.y, gradient_colors[color], gradient_colors[color + 1], y_min, y_max), 1.0); 72 | } 73 | } 74 | } 75 | else 76 | { 77 | fragColor = vec4(bg_color,1.0); 78 | } 79 | } -------------------------------------------------------------------------------- /config/cava/shaders/normalized_bars.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | in vec2 fragCoord; 4 | out vec4 fragColor; 5 | 6 | // bar values. defaults to left channels first (low to high), then right (high to low). 7 | uniform float bars[512]; 8 | 9 | uniform int bars_count; // number of bars (left + right) (configurable) 10 | 11 | uniform vec3 u_resolution; // window resolution, not used here 12 | 13 | //colors, configurable in cava config file 14 | uniform vec3 bg_color; // background color(r,g,b) (0.0 - 1.0), not used here 15 | uniform vec3 fg_color; // foreground color, not used here 16 | 17 | float normalize_C(float x, float x_min, float x_max, float r_min, float r_max ) 18 | { 19 | float xr; 20 | xr = (r_max-r_min) * (x - x_min) / (x_max - x_min) + r_min; 21 | return xr; 22 | } 23 | 24 | void main() 25 | { 26 | // find which bar to use based on where we are on the x axis 27 | int bar = int(bars_count * fragCoord.x); 28 | 29 | // create a normal along the y axis based on the bar height 30 | float x = normalize_C(fragCoord.y, 1.0, 0.0, 0.0, bars[bar]); 31 | 32 | // set color 33 | fragColor.r=fg_color.x*x; 34 | fragColor.g=fg_color.y*x; 35 | fragColor.b=fg_color.z*x; 36 | fragColor.a=1.0; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /config/cava/shaders/pass_through.vert: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | 4 | // Input vertex data, different for all executions of this shader. 5 | layout(location = 0) in vec3 vertexPosition_modelspace; 6 | 7 | // Output data ; will be interpolated for each fragment. 8 | out vec2 fragCoord; 9 | 10 | void main() 11 | { 12 | gl_Position = vec4(vertexPosition_modelspace,1); 13 | fragCoord = (vertexPosition_modelspace.xy+vec2(1,1))/2.0; 14 | } 15 | -------------------------------------------------------------------------------- /config/hypr/UserConfigs/00-Readme: -------------------------------------------------------------------------------- 1 | www.github.com/AXWTV 2 | 3 | Hyprland-Dots v1.0.5 4 | 5 | 1.) Suggest not to rename any files in this folder. As this is connected and being sourced from hyprland.conf in ~/.config/hypr 6 | 7 | 2.) This folder, along with UserScripts folder will NOT be touch during update. 8 | 9 | 3.) However, if hyprland has a big change in settings, i.e., blur section is moved into another group, you should managed the change. 10 | 11 | 4.) Guidance on the keybinds. Suggest NOT to assign a keybind which I set on the default Keybinds. Else will conflict. Once Hyprland decided to have a global keybinds, then I will adjust. 12 | 13 | 5.) If you think that the default keybinds SHOULD be adjusted, open an issue on my github page and present me a valid argument. Like conflicting to GLOBAL keybinds, etc etc etc. 14 | 15 | 16 | I will update the Hyprland-Dotfiles wiki for guidance. Make sure to check out changelogs as well 17 | -------------------------------------------------------------------------------- /config/hypr/UserConfigs/ENVariables.conf: -------------------------------------------------------------------------------- 1 | # /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ # 2 | 3 | #environment-variables 4 | env = CLUTTER_BACKEND,wayland 5 | env = GDK_BACKEND,wayland,x11 6 | env = QT_AUTO_SCREEN_SCALE_FACTOR,1 7 | env = QT_QPA_PLATFORM,wayland;xcb 8 | env = QT_QPA_PLATFORMTHEME,qt5ct 9 | env = QT_SCALE_FACTOR,1 10 | env = QT_WAYLAND_DISABLE_WINDOWDECORATION,1 11 | env = XDG_CURRENT_DESKTOP,Hyprland 12 | env = XDG_SESSION_DESKTOP,Hyprland 13 | env = XDG_SESSION_TYPE,wayland 14 | 15 | # vulkan 16 | #env = WLR_RENDERER,vulkan 17 | 18 | # firefox 19 | env = MOZ_ENABLE_WAYLAND,1 20 | 21 | # NVIDIA 22 | # This is from Hyprland Wiki. As a start, WLR_NO_HARDWARE_CURSORS 1 will be activated if nvidia gpu detected 23 | #env = WLR_NO_HARDWARE_CURSORS,1 24 | #env = LIBVA_DRIVER_NAME,nvidia 25 | #env = __GLX_VENDOR_LIBRARY_NAME,nvidia 26 | #env = GBM_BACKEND,nvidia-drm 27 | 28 | #env = __NV_PRIME_RENDER_OFFLOAD,1 29 | #env = __VK_LAYER_NV_optimus,NVIDIA_only 30 | #env = WLR_DRM_NO_ATOMIC,1 31 | #env = NVD_BACKEND,direct 32 | 33 | # FOR VM and POSSIBLY NVIDIA 34 | #env = WLR_RENDERER_ALLOW_SOFTWARE,1 35 | 36 | # nvidia firefox (for hardware acceleration on FF)? 37 | # check this post https://github.com/elFarto/nvidia-vaapi-driver#configuration 38 | #env = MOZ_DISABLE_RDD_SANDBOX,1 39 | #env = NVD_BACKEND,direct 40 | #env = EGL_PLATFORM,wayland 41 | -------------------------------------------------------------------------------- /config/hypr/UserConfigs/LaptopDisplay.conf: -------------------------------------------------------------------------------- 1 | # NOTE, THIS FILE IS BEING USED by disabling Laptop display monitor behaviour when closing lid. 2 | # See notes on Laptops.conf 3 | 4 | #monitor = eDP-1, preferred, auto, 1 5 | -------------------------------------------------------------------------------- /config/hypr/UserConfigs/Laptops.conf: -------------------------------------------------------------------------------- 1 | # /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ # 2 | 3 | # See https://wiki.hyprland.org/Configuring/Keywords/ for more variable settings 4 | # These configs are mostly for laptops. This is addemdum to Keybinds.conf 5 | 6 | $mainMod = SUPER 7 | $scriptsDir = $HOME/.config/hypr/scripts 8 | $UserConfigs = $HOME/.config/hypr/UserConfigs 9 | 10 | bind = , xf86KbdBrightnessDown, exec, $scriptsDir/BrightnessKbd.sh --dec #Keyboard brightness Down 11 | bind = , xf86KbdBrightnessUp, exec, $scriptsDir/BrightnessKbd.sh --inc #Keyboard brightness up 12 | bind = , xf86Launch1, exec, rog-control-center # ASUS Armory crate button 13 | bind = , xf86Launch3, exec, asusctl led-mode -n #FN+F4 Switch keyboard RGB profile 14 | bind = , xf86Launch4, exec, asusctl profile -n #FN+F5 change of fan profiles (Quite, Balance, Performance) 15 | bind = , xf86MonBrightnessDown, exec, $scriptsDir/Brightness.sh --dec 16 | bind = , xf86MonBrightnessUp, exec, $scriptsDir/Brightness.sh --inc 17 | bind = , xf86TouchpadToggle, exec, $scriptsDir/TouchPad.sh #disable touchpad 18 | 19 | # Screenshot keybindings for Asus G15 (no PrinSrc button) 20 | bind = $mainMod, F6, exec, $scriptsDir/ScreenShot.sh --now # Fullscreen 21 | bind = $mainMod SHIFT, F6, exec, $scriptsDir/ScreenShot.sh --area 22 | bind = $mainMod CTRL, F6, exec, $scriptsDir/ScreenShot.sh --in5 # Screenshot in 5 secs 23 | bind = $mainMod ALT, F6, exec, $scriptsDir/ScreenShot.sh --in10 # Screenshot in 10 secs 24 | bind = ALT, F6, exec, $scriptsDir/ScreenShot.sh --active # Screenshot active window 25 | 26 | # Below are useful when you are connecting your laptop in external display 27 | # Suggest you edit below for your laptop display 28 | # From WIKI This is to disable laptop monitor when lid is closed. 29 | # consult https://wiki.hyprland.org/hyprland-wiki/pages/Configuring/Binds/#switches 30 | #bindl = , switch:off:Lid Switch,exec,hyprctl keyword monitor "eDP-1, preferred, auto, 1" 31 | #bindl = , switch:on:Lid Switch,exec,hyprctl keyword monitor "eDP-1, disable" 32 | 33 | ############################################################################# 34 | ### WARNING! Using this method has some caveats!! USE THIS PART WITH SOME CAUTION! 35 | # CONS of doing this, is that you need to set up your wallpaper (SUPER W) and choose wallpaper. 36 | # CAVEATS! Sometimes the Main Laptop Monitor DOES NOT have display that it needs to re-connect your external monitor 37 | # One work around is to ensure that before shutting down laptop, MAKE SURE your laptop lid is OPEN!! 38 | # Make sure to comment (put # on the both the bindl = , switch ......) above 39 | # NOTE: Display for laptop are being generated into LaptopDisplay.conf 40 | # This part is to be use if you do not want your main laptop monitor to wake up during say wallpaper change etc 41 | 42 | #bindl = , switch:off:Lid Switch,exec,echo "monitor = eDP-1, preferred, auto, 1" > $UserConfigs/LaptopDisplay.conf 43 | #bindl = , switch:on:Lid Switch,exec,echo "monitor = eDP-1, disable" > $UserConfigs/LaptopDisplay.conf 44 | 45 | # for laptop-lid action (to erase the last entry) 46 | #exec-once = echo "eDP-1, preferred, auto, 1" > $HOME/.config/hypr/UserConfigs/LaptopDisplay.conf 47 | ############################################################################## 48 | -------------------------------------------------------------------------------- /config/hypr/UserConfigs/Monitors.conf: -------------------------------------------------------------------------------- 1 | # /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ # 2 | 3 | # Monitor Configuration 4 | # See Hyprland wiki for more details 5 | # https://wiki.hyprland.org/Configuring/Monitors/ 6 | # Configure your Display resolution, offset, scale and Monitors here, use `hyprctl monitors` to get the info. 7 | 8 | 9 | # Monitors 10 | monitor=,highres,auto,1 11 | 12 | # NOTE: for laptop, kindly check notes in Laptops.conf regarding display 13 | # Created this inorder for the monitor display to not wake up if not intended. 14 | # See here: https://github.com/hyprwm/Hyprland/issues/4090 15 | 16 | #monitor = eDP-1, preferred, auto, 1 17 | #monitor = eDP-1, 2560x1440@165, 0x0, 1 18 | #monitor = HDMI-A-1, 1920x1080@60, 0x0, 1 #own Configuration 19 | #monitor = DP-3, 1920x1080@240, auto, 1 20 | #monitor = DP-1, preferred, auto, 1 21 | #monitor = HDMI-A-1, preferred,auto,1 22 | 23 | # QEMU-KVM or any virtual box 24 | #monitor = Virtual-1, 1920x1080@60,auto,1 25 | 26 | # Hi Refresh Rate 27 | #monitor=,highrr,auto,1 28 | 29 | # High Resolution 30 | #monitor=,highres,auto,1 31 | 32 | # to disable a monitor 33 | #monitor=name,disable 34 | 35 | # Mirror 36 | #monitor=DP-3,1920x1080@60,0x0,1,mirror,DP-2 37 | #monitor=,preferred,auto,1,mirror,eDP-1 38 | 39 | 40 | # Example : 41 | #monitor=eDP-1,2560x1440@165,0x0,1 42 | #workspace=HDMI-A-1,1 43 | #monitor=HDMI-A-1,2560x1440@144,0x0,1,mirror,eDP-1 44 | #workspace=HDMI-A-2,2 45 | 46 | #monitor=eDP-1,transform,0 47 | #monitor=eDP-1,addreserved,10,10,10,49 48 | #workspace=eDP-1,1 49 | 50 | -------------------------------------------------------------------------------- /config/hypr/UserConfigs/Startup_Apps.conf: -------------------------------------------------------------------------------- 1 | # /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ 2 | #Commands & Apps to be executed at launch 3 | 4 | $scriptsDir = $HOME/.config/hypr/scripts 5 | $UserScripts = $HOME/.config/hypr/UserScripts 6 | 7 | $wallDIR=$HOME/Pictures/wallpapers 8 | $lock = $scriptsDir/LockScreen.sh 9 | $SwwwRandom = $UserScripts/WallpaperAutoChange.sh 10 | 11 | # set cursor 12 | exec-once = hyprctl setcursor Bibata-Modern-Ice 24 13 | 14 | # wallpaper stuff / More wallpaper options below 15 | exec-once = swww query || swww init 16 | exec = ags -q && ags & 17 | # exec-once = $SwwwRandom $wallDIR # random wallpaper switcher every 30 minutes 18 | 19 | # Startup 20 | exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP 21 | exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP 22 | exec-once = hyprpm reload -n 23 | 24 | # Polkit (Polkit Gnome / KDE) 25 | exec-once = $scriptsDir/Polkit.sh 26 | 27 | # starup apps 28 | # exec-once = waybar & 29 | exec-once = nm-applet --indicator & 30 | # exec-once = swaync & 31 | #exec-once = blueman-applet & 32 | #exec-once = rog-control-center & 33 | 34 | 35 | #clipboard manager 36 | exec-once = wl-paste --type text --watch cliphist store 37 | exec-once = wl-paste --type image --watch cliphist store 38 | 39 | # Rainbow borders 40 | # exec-once = $UserScripts/RainbowBorders.sh 41 | 42 | # sway-idle with lock only 43 | # exec-once = swayidle -w timeout 900 '$lock' 44 | # sway-idle with lock and sleep 45 | #exec-once = swayidle -w timeout 900 '$lock' timeout 1200 'hyprctl dispatch dpms off' resume 'hyprctl dispatch dpms on' before-sleep '$lock' 46 | # sway idle without lock 47 | #exec-once = swayidle -w timeout 900 'hyprctl dispatch dpms off' resume 'hyprctl dispatch dpms on' 48 | 49 | # Here are list of features available but disabled by default 50 | #exec-once = swww query || swww init && swww img $HOME/Pictures/wallpapers/mecha-nostalgia.png # persistent wallpaper 51 | 52 | #gnome polkit for nixos 53 | #exec-once = $scriptsDir/Polkit-NixOS.sh 54 | 55 | # xdg-desktop-portal-hyprland (should be auto starting. However, you can force to start) 56 | #exec-once = $scriptsDir/PortalHyprland.sh 57 | 58 | exec-once = flatpak run dev.vencord.Vesktop 59 | -------------------------------------------------------------------------------- /config/hypr/UserConfigs/UserKeybinds.conf: -------------------------------------------------------------------------------- 1 | # /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ 2 | # This is where you put your own keybinds. Be Mindful to check as well ~/.config/hypr/configs/Keybinds.conf to avoid conflict 3 | # if you think I should replace the Pre-defined Keybinds in ~/.config/hypr/configs/Keybinds.conf , submit an issue or let me know in DC and present me a valid reason as to why, such as conflicting with global shortcuts, etc etc 4 | 5 | # See https://wiki.hyprland.org/Configuring/Keywords/ for more settings and variables 6 | # See also Laptops.conf for laptops keybinds 7 | 8 | $mainMod = SUPER 9 | $files = nautilus 10 | #$term = alacritty 11 | $term = kitty 12 | $scriptsDir = $HOME/.config/hypr/scripts 13 | $UserScripts = $HOME/.config/hypr/UserScripts 14 | 15 | # ags App launcher 16 | bindr = $mainMod, $mainMod_L, exec, ags -t launcher 17 | bind = $mainMod, D, exec, ags -t launcher 18 | bind = $mainMod, R, exec, ags -q && ags && hyprctl reload 19 | 20 | bind = $mainMod, Return, exec, $term # Launch terminal 21 | bind = $mainMod, T, exec, $files 22 | 23 | 24 | # For passthrough keyboard into a VM 25 | # bind = $mainMod ALT, P, submap, passthru 26 | #submap = passthru 27 | # to unbind 28 | #bind = $mainMod ALT, P, submap, reset 29 | #submap = reset 30 | -------------------------------------------------------------------------------- /config/hypr/configs/Settings.conf: -------------------------------------------------------------------------------- 1 | # /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ # 2 | 3 | # Default Settings. avoid changing this file as during update, this will be replaced 4 | 5 | # refer to Hyprland wiki for more info https://wiki.hyprland.org/Configuring/Variables 6 | 7 | # Initial boot script enable to apply initial wallpapers, theming, new settings etc. 8 | exec-once = $HOME/.config/hypr/initial-boot.sh 9 | -------------------------------------------------------------------------------- /config/hypr/hyprland.conf: -------------------------------------------------------------------------------- 1 | # Sourcing external config files 2 | 3 | ###### Default Configs 4 | $configs = $HOME/.config/hypr/configs 5 | 6 | source=$configs/Settings.conf 7 | source=$configs/Keybinds.conf 8 | 9 | #### User Configs 10 | $UserConfigs = $HOME/.config/hypr/UserConfigs 11 | 12 | source= $UserConfigs/Startup_Apps.conf 13 | source= $UserConfigs/ENVariables.conf 14 | source= $UserConfigs/Monitors.conf 15 | source= $UserConfigs/Laptops.conf 16 | source= $UserConfigs/LaptopDisplay.conf 17 | source= $UserConfigs/WindowRules.conf 18 | source= $UserConfigs/UserKeybinds.conf 19 | source= $UserConfigs/UserSettings.conf -------------------------------------------------------------------------------- /config/hypr/initial-boot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # A bash script designed to run only once dotfiles installed 3 | 4 | # THIS SCRIPT CAN BE DELETED ONCE SUCCESSFULLY BOOTED!! And also, edit ~/.config/hypr/configs/Settings.conf 5 | # not necessary to do since this script is only designed to run only once as long as the marker exists 6 | # However, I do highly suggest not to touch it since again, as long as the marker exist, script wont run 7 | 8 | # Variables 9 | scriptsDir=$HOME/.config/hypr/scripts 10 | wallpaper=$HOME/Pictures/wallpapers/10516833.png 11 | kvantum_theme="Tokyo-Night" 12 | 13 | swww="swww img" 14 | effect="--transition-bezier .43,1.19,1,.4 --transition-fps 30 --transition-type grow --transition-pos 0.925,0.977 --transition-duration 2" 15 | 16 | # Check if a marker file exists. 17 | if [ ! -f ~/.config/hypr/.initial_startup_done ]; then 18 | 19 | # Initialize pywal and wallpaper 20 | if [ -f "$wallpaper" ]; then 21 | wal -i $wallpaper -s -t > /dev/null 22 | swww init && $swww $wallpaper $effect 23 | "$scriptsDir/PywalSwww.sh" > /dev/null 2>&1 & 24 | fi 25 | 26 | # initiate GTK dark mode and apply icon and cursor theme 27 | gsettings set org.gnome.desktop.interface color-scheme prefer-dark > /dev/null 2>&1 & 28 | gsettings set org.gnome.desktop.interface gtk-theme Tokyonight-Dark-BL-LB > /dev/null 2>&1 & 29 | gsettings set org.gnome.desktop.interface icon-theme Tokyonight-Dark > /dev/null 2>&1 & 30 | gsettings set org.gnome.desktop.interface cursor-theme Bibata-Modern-Ice > /dev/null 2>&1 & 31 | gsettings set org.gnome.desktop.interface cursor-size 24 > /dev/null 2>&1 & 32 | 33 | # initiate kvantum theme 34 | kvantummanager --set "$kvantum_theme" > /dev/null 2>&1 & 35 | 36 | # initiate the kb_layout (for some reason) waybar cant launch it 37 | "$scriptsDir/SwitchKeyboardLayout.sh" > /dev/null 2>&1 & 38 | 39 | # Create a marker file to indicate that the script has been executed. 40 | touch ~/.config/hypr/.initial_startup_done 41 | 42 | exit 43 | fi 44 | -------------------------------------------------------------------------------- /config/hypr/scripts/ChangeBlur.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## 3 | ## Script for changing blurs on the fly 4 | 5 | notif="$HOME/.config/swaync/images/bell.png" 6 | 7 | STATE=$(hyprctl -j getoption decoration:blur:passes | jq ".int") 8 | 9 | if [ "${STATE}" == "2" ]; then 10 | hyprctl keyword decoration:blur:size 2 11 | hyprctl keyword decoration:blur:passes 1 12 | notify-send -e -u low -i "$notif" "Less blur" 13 | else 14 | hyprctl keyword decoration:blur:size 5 15 | hyprctl keyword decoration:blur:passes 2 16 | notify-send -e -u low -i "$notif" "Normal blur" 17 | fi 18 | -------------------------------------------------------------------------------- /config/hypr/scripts/ChangeLayout.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## 3 | # for changing Hyprland Layouts (Master or Dwindle) on the fly 4 | 5 | notif="$HOME/.config/swaync/images/bell.png" 6 | 7 | LAYOUT=$(hyprctl -j getoption general:layout | jq '.str' | sed 's/"//g') 8 | 9 | case $LAYOUT in 10 | "master") 11 | hyprctl keyword general:layout dwindle 12 | hyprctl keyword unbind SUPER,J 13 | hyprctl keyword unbind SUPER,K 14 | hyprctl keyword bind SUPER,J,cyclenext 15 | hyprctl keyword bind SUPER,K,cyclenext,prev 16 | hyprctl keyword bind SUPER,O,togglesplit 17 | notify-send -e -u low -i "$notif" "Dwindle Layout" 18 | ;; 19 | "dwindle") 20 | hyprctl keyword general:layout master 21 | hyprctl keyword unbind SUPER,J 22 | hyprctl keyword unbind SUPER,K 23 | hyprctl keyword unbind SUPER,O 24 | hyprctl keyword bind SUPER,J,layoutmsg,cyclenext 25 | hyprctl keyword bind SUPER,K,layoutmsg,cycleprev 26 | notify-send -e -u low -i "$notif" "Master Layout" 27 | ;; 28 | *) ;; 29 | 30 | esac 31 | -------------------------------------------------------------------------------- /config/hypr/scripts/ClipManager.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## 3 | # Clipboard Manager. This script uses cliphist, rofi, and wl-copy. 4 | 5 | # Actions: 6 | # CTRL Del to delete an entry 7 | # ALT Del to wipe clipboard contents 8 | 9 | while true; do 10 | result=$( 11 | rofi -dmenu \ 12 | -kb-custom-1 "Control-Delete" \ 13 | -kb-custom-2 "Alt-Delete" \ 14 | -config ~/.config/rofi/config-clipboard.rasi < <(cliphist list) 15 | ) 16 | 17 | case "$?" in 18 | 1) 19 | exit 20 | ;; 21 | 0) 22 | case "$result" in 23 | "") 24 | continue 25 | ;; 26 | *) 27 | cliphist decode <<<"$result" | wl-copy 28 | exit 29 | ;; 30 | esac 31 | ;; 32 | 10) 33 | cliphist delete <<<"$result" 34 | ;; 35 | 11) 36 | cliphist wipe 37 | ;; 38 | esac 39 | done 40 | 41 | -------------------------------------------------------------------------------- /config/hypr/scripts/GameMode.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## 3 | # Game Mode. Turning off all animations 4 | 5 | notif="$HOME/.config/swaync/images/bell.png" 6 | SCRIPTSDIR="$HOME/.config/hypr/scripts" 7 | 8 | 9 | HYPRGAMEMODE=$(hyprctl getoption animations:enabled | awk 'NR==1{print $2}') 10 | if [ "$HYPRGAMEMODE" = 1 ] ; then 11 | hyprctl --batch "\ 12 | keyword animations:enabled 0;\ 13 | keyword decoration:drop_shadow 0;\ 14 | keyword decoration:blur:passes 0;\ 15 | keyword general:gaps_in 0;\ 16 | keyword general:gaps_out 0;\ 17 | keyword general:border_size 1;\ 18 | keyword decoration:rounding 0" 19 | swww kill 20 | notify-send -e -u low -i "$notif" "gamemode enabled. All animations off" 21 | exit 22 | else 23 | hyprctl reload 24 | ags -q && ags 25 | swww query || swww init 26 | sleep 4 27 | notify-send -e -u low -i "$notif" "gamemode disabled. All animations normal" 28 | exit 29 | fi 30 | hyprctl reload 31 | -------------------------------------------------------------------------------- /config/hypr/scripts/KeyHints.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## 3 | # Keyhints. Idea got from Garuda Hyprland 4 | 5 | # Detect monitor resolution and scale 6 | x_mon=$(hyprctl -j monitors | jq '.[] | select(.focused==true) | .width') 7 | y_mon=$(hyprctl -j monitors | jq '.[] | select(.focused==true) | .height') 8 | hypr_scale=$(hyprctl -j monitors | jq '.[] | select (.focused == true) | .scale' | sed 's/\.//') 9 | 10 | # Calculate width and height based on percentages and monitor resolution 11 | width=$((x_mon * hypr_scale / 100)) 12 | height=$((y_mon * hypr_scale / 100)) 13 | 14 | # Set maximum width and height 15 | max_width=1200 16 | max_height=1000 17 | 18 | # Set percentage of screen size for dynamic adjustment 19 | percentage_width=70 20 | percentage_height=70 21 | 22 | # Calculate dynamic width and height 23 | dynamic_width=$((width * percentage_width / 100)) 24 | dynamic_height=$((height * percentage_height / 100)) 25 | 26 | # Limit width and height to maximum values 27 | dynamic_width=$(($dynamic_width > $max_width ? $max_width : $dynamic_width)) 28 | dynamic_height=$(($dynamic_height > $max_height ? $max_height : $dynamic_height)) 29 | 30 | # Launch yad with calculated width and height 31 | yad --width=$dynamic_width --height=$dynamic_height \ 32 | --center \ 33 | --title="Keybindings" \ 34 | --no-buttons \ 35 | --list \ 36 | --column=Key: \ 37 | --column=Description: \ 38 | --column=Command: \ 39 | --timeout-indicator=bottom \ 40 | "ESC" "close this app" "" "=" "SUPER KEY (Windows Key)" "(SUPER KEY)" \ 41 | " enter" "Terminal" "(alacritty)" \ 42 | " or  D" "App Launcher" "(AGS)" \ 43 | " T" "Open File Manager" "(Nautilus)" \ 44 | " Q" "close active window" "(not kill)" \ 45 | " Shift Q " "closes a specified window" "(window)" \ 46 | " Alt V" "Clipboard Manager" "(cliphist)" \ 47 | " R" "Reload Hyprland" "Reloads AGS and Hyprland" \ 48 | " Print" "screenshot" "(grim)" \ 49 | " Shift Print" "screenshot region" "(grim + slurp)" \ 50 | " Shift S" "screenshot region" "(swappy)" \ 51 | "ALT Print" "Screenshot active window" "active window only" \ 52 | "CTRL ALT P" "power-menu" "(AGS)" \ 53 | "CTRL ALT L" "screen lock" "(Hyprlock)" \ 54 | "CTRL ALT Del" "Hyprland Exit" "(SAVE YOUR WORK!!!)" \ 55 | " F" "Fullscreen" "Toggles to full screen" \ 56 | " ALT L" "Toggle Dwindle | Master Layout" "Hyprland Layout" \ 57 | " Shift F" "Toggle float" "single window" \ 58 | " ALT F" "Toggle all windows to float" "all windows" \ 59 | " SHIFT G" "Gamemode! All animations OFF or ON" "toggle" \ 60 | " Shift B" "Toggle Blur" "normal or less blur" \ 61 | " H" "Launch this app" "" \ 62 | " E" "View or EDIT Keybinds, Settings, Monitor" "" \ 63 | "" "" "" \ 64 | "More tips:" "https://github.com/AXWTV/Hyprland-DotFiles/wiki" ""\ 65 | -------------------------------------------------------------------------------- /config/hypr/scripts/LockScreen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/AXWTV 💫 ---- */ ## 3 | # For Swaylock 4 | 5 | #CONFIG="$HOME/.config/swaylock/config" 6 | 7 | #sleep 0.5s; swaylock --config ${CONFIG} & disown 8 | 9 | # for Hyprlock 10 | # 11 | CONFIG="$HOME/.config/hypr/hyprlock.conf" 12 | 13 | sleep 0.5s; hyprlock --config ${CONFIG} & disown 14 | -------------------------------------------------------------------------------- /config/hypr/scripts/MediaCtrl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## 3 | # Playerctl 4 | 5 | music_icon="$HOME/.config/swaync/icons/music.png" 6 | 7 | # Play the next track 8 | play_next() { 9 | playerctl next 10 | show_music_notification 11 | } 12 | 13 | # Play the previous track 14 | play_previous() { 15 | playerctl previous 16 | show_music_notification 17 | } 18 | 19 | # Toggle play/pause 20 | toggle_play_pause() { 21 | playerctl play-pause 22 | show_music_notification 23 | } 24 | 25 | # Stop playback 26 | stop_playback() { 27 | playerctl stop 28 | notify-send -e -u low -i "$music_icon" "Playback Stopped" 29 | } 30 | 31 | # Display notification with song information 32 | show_music_notification() { 33 | status=$(playerctl status) 34 | if [[ "$status" == "Playing" ]]; then 35 | song_title=$(playerctl metadata title) 36 | song_artist=$(playerctl metadata artist) 37 | notify-send -e -u low -i "$music_icon" "Now Playing:" "$song_title\nby $song_artist" 38 | elif [[ "$status" == "Paused" ]]; then 39 | notify-send -e -u low -i "$music_icon" "Playback Paused" 40 | fi 41 | } 42 | 43 | # Get media control action from command line argument 44 | case "$1" in 45 | "--nxt") 46 | play_next 47 | ;; 48 | "--prv") 49 | play_previous 50 | ;; 51 | "--pause") 52 | toggle_play_pause 53 | ;; 54 | "--stop") 55 | stop_playback 56 | ;; 57 | *) 58 | echo "Usage: $0 [--nxt|--prv|--pause|--stop]" 59 | exit 1 60 | ;; 61 | esac 62 | -------------------------------------------------------------------------------- /config/hypr/scripts/Polkit-NixOS.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## 3 | # For NixOS starting of polkit-gnome. Dec 2023, the settings stated in NixOS wiki does not work so have to manual start it 4 | 5 | # Find all polkit-gnome executables in the Nix store 6 | polkit_gnome_paths=$(find /nix/store -name 'polkit-gnome-authentication-agent-1' -type f 2>/dev/null) 7 | 8 | for polkit_gnome_path in $polkit_gnome_paths; do 9 | # Extract the directory containing the executable 10 | polkit_gnome_dir=$(dirname "$polkit_gnome_path") 11 | 12 | # Check if the executable is valid and exists 13 | if [ -x "$polkit_gnome_dir/polkit-gnome-authentication-agent-1" ]; then 14 | # Start the Polkit-GNOME Authentication Agent 15 | "$polkit_gnome_dir/polkit-gnome-authentication-agent-1" & 16 | exit 0 17 | fi 18 | done 19 | 20 | # If no valid executable is found, report an error 21 | echo "No valid Polkit-GNOME Authentication Agent executable found." -------------------------------------------------------------------------------- /config/hypr/scripts/Polkit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## 3 | # This is for polkits, it will start from top and will stop if the top is executed 4 | 5 | # Polkit possible paths files to check 6 | polkit=( 7 | "/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1" 8 | "/usr/lib/polkit-kde-authentication-agent-1" 9 | "/usr/lib/polkit-gnome-authentication-agent-1" 10 | "/usr/libexec/polkit-gnome-authentication-agent-1" 11 | "/usr/lib/x86_64-linux-gnu/libexec/polkit-kde-authentication-agent-1" 12 | "/usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1" 13 | ) 14 | 15 | executed=false # Flag to track if a file has been executed 16 | 17 | # Loop through the list of files 18 | for file in "${polkit[@]}"; do 19 | if [ -e "$file" ]; then 20 | echo "File $file found, executing command..." 21 | exec "$file" 22 | executed=true 23 | break 24 | fi 25 | done 26 | 27 | # If none of the files were found, you can add a fallback command here 28 | if [ "$executed" == false ]; then 29 | echo "None of the specified files were found. Install a Polkit" 30 | fi 31 | -------------------------------------------------------------------------------- /config/hypr/scripts/PortalHyprland.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## 3 | # For manually starting xdg-desktop-portal 4 | 5 | sleep 1 6 | killall xdg-desktop-portal-hyprland 7 | killall xdg-desktop-portal-wlr 8 | killall xdg-desktop-portal-gnome 9 | killall xdg-desktop-portal 10 | sleep 1 11 | /usr/lib/xdg-desktop-portal-hyprland & 12 | /usr/libexec/xdg-desktop-portal-hyprland & 13 | sleep 2 14 | /usr/lib/xdg-desktop-portal-hyprland & 15 | /usr/libexec/xdg-desktop-portal & 16 | 17 | -------------------------------------------------------------------------------- /config/hypr/scripts/PywalSwww.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## 3 | # Pywal Colors for current wallpaper 4 | 5 | # Define the path to the swww cache directory 6 | cache_dir="$HOME/.cache/swww/" 7 | 8 | # Get a list of monitor outputs 9 | monitor_outputs=($(ls "$cache_dir")) 10 | 11 | # Initialize a flag to determine if the ln command was executed 12 | ln_success=false 13 | 14 | # Loop through monitor outputs 15 | for output in "${monitor_outputs[@]}"; do 16 | # Construct the full path to the cache file 17 | cache_file="$cache_dir$output" 18 | 19 | # Check if the cache file exists for the current monitor output 20 | if [ -f "$cache_file" ]; then 21 | # Get the wallpaper path from the cache file 22 | wallpaper_path=$(cat "$cache_file") 23 | 24 | # Copy the wallpaper to the location Rofi can access 25 | if ln -sf "$wallpaper_path" "$HOME/.config/rofi/.current_wallpaper"; then 26 | ln_success=true # Set the flag to true upon successful execution 27 | fi 28 | 29 | break # Exit the loop after processing the first found monitor output 30 | fi 31 | done 32 | 33 | # Check the flag before executing further commands 34 | if [ "$ln_success" = true ]; then 35 | # execute pywal 36 | # wal -i "$wallpaper_path" 37 | 38 | # execute pywal skipping tty and terminal changes 39 | wal -i "$wallpaper_path" -s -t & 40 | fi 41 | -------------------------------------------------------------------------------- /config/hypr/scripts/Refresh.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## 3 | # Scripts for refreshing waybar, rofi, swaync, pywal colors 4 | 5 | SCRIPTSDIR=$HOME/.config/hypr/scripts 6 | UserScripts=$HOME/.config/hypr/UserScripts 7 | 8 | # Define file_exists function 9 | file_exists() { 10 | if [ -e "$1" ]; then 11 | return 0 # File exists 12 | else 13 | return 1 # File does not exist 14 | fi 15 | } 16 | 17 | # Kill already running processes 18 | _ps=(waybar rofi swaync) 19 | for _prs in "${_ps[@]}"; do 20 | if pidof "${_prs}" >/dev/null; then 21 | pkill "${_prs}" 22 | fi 23 | done 24 | 25 | sleep 0.3 26 | # Relaunch waybar 27 | waybar & 28 | 29 | # relaunch swaync 30 | sleep 0.5 31 | swaync > /dev/null 2>&1 & 32 | 33 | # Relaunching rainbow borders if the script exists 34 | sleep 1 35 | if file_exists "${UserScripts}/RainbowBorders.sh"; then 36 | ${UserScripts}/RainbowBorders.sh & 37 | fi 38 | 39 | # for cava-pywal (note, need to manually restart cava once wallpaper changes) 40 | ln -sf "$HOME/.cache/wal/cava-colors" "$HOME/.config/cava/config" || true 41 | 42 | exit 0 -------------------------------------------------------------------------------- /config/hypr/scripts/SwitchKeyboardLayout.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## 3 | # This is for changing kb_layouts. Set kb_layouts in $settings_file 4 | 5 | layout_f="$HOME/.cache/kb_layout" 6 | settings_file="$HOME/.config/hypr/UserConfigs/UserSettings.conf" 7 | notif="$HOME/.config/swaync/images/bell.png" 8 | 9 | # Check if ~/.cache/kb_layout exists and create it with a default layout from Settings.conf if not found 10 | if [ ! -f "$layout_f" ]; then 11 | default_layout=$(grep 'kb_layout=' "$settings_file" | cut -d '=' -f 2 | cut -d ',' -f 1 2>/dev/null) 12 | if [ -z "$default_layout" ]; then 13 | default_layout="us" # Default to 'us' layout if Settings.conf or 'kb_layout' is not found 14 | fi 15 | echo "$default_layout" > "$layout_f" 16 | fi 17 | 18 | current_layout=$(cat "$layout_f") 19 | 20 | # Read keyboard layout settings from Settings.conf 21 | if [ -f "$settings_file" ]; then 22 | kb_layout_line=$(grep 'kb_layout=' "$settings_file" | cut -d '=' -f 2) 23 | IFS=',' read -ra layout_mapping <<< "$kb_layout_line" 24 | fi 25 | 26 | layout_count=${#layout_mapping[@]} 27 | 28 | # Find the index of the current layout in the mapping 29 | for ((i = 0; i < layout_count; i++)); do 30 | if [ "$current_layout" == "${layout_mapping[i]}" ]; then 31 | current_index=$i 32 | break 33 | fi 34 | done 35 | 36 | # Calculate the index of the next layout 37 | next_index=$(( (current_index + 1) % layout_count )) 38 | new_layout="${layout_mapping[next_index]}" 39 | 40 | # Update the keyboard layout 41 | hyprctl keyword input:kb_layout "$new_layout" 42 | echo "$new_layout" > "$layout_f" 43 | 44 | # Notification for the new keyboard layout 45 | notify-send -u low -i "$notif" "new KB_Layout: $new_layout" -------------------------------------------------------------------------------- /config/hypr/scripts/TouchPad.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## 3 | # For disabling touchpad. 4 | 5 | Touchpad_Device="asue1209:00-04f3:319f-touchpad" 6 | notif="$HOME/.config/swaync/images/bell.png" 7 | 8 | XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-/run/user/$(id -u)} 9 | STATUS_FILE="$XDG_RUNTIME_DIR/touchpad.status" 10 | 11 | toggle_touchpad() { 12 | if [ ! -f "$STATUS_FILE" ] || [ "$(cat "$STATUS_FILE")" = "false" ]; then 13 | echo "true" > "$STATUS_FILE" 14 | action="enabled" 15 | else 16 | echo "false" > "$STATUS_FILE" 17 | action="disabled" 18 | fi 19 | 20 | notify-send -u low -i "$notif" "Touchpad $action" 21 | hyprctl keyword "device:$Touchpad_Device:enabled" "$(cat "$STATUS_FILE")" 22 | } 23 | 24 | toggle_touchpad 25 | -------------------------------------------------------------------------------- /config/hypr/v4.0: -------------------------------------------------------------------------------- 1 | ### https://github.com/AXWTV 2 | -------------------------------------------------------------------------------- /config/kitty/kitty.conf: -------------------------------------------------------------------------------- 1 | include ~/.cache/wal/colors-kitty.conf 2 | 3 | font_family JetbrainsMono Nerd Font 4 | font_size 10 5 | bold_font auto 6 | italic_font auto 7 | bold_italic_font auto 8 | 9 | background_opacity 0.7 10 | 11 | confirm_os_window_close 0 12 | 13 | enable_audio_bell no 14 | 15 | shell /bin/zsh 16 | 17 | selection_foreground #000000 18 | selection_background #F5FBFF 19 | -------------------------------------------------------------------------------- /config/nushell/history.txt: -------------------------------------------------------------------------------- 1 | ls 2 | gt 3 | vim 4 | nvim 5 | tmux 6 | ll 7 | ls 8 | lsd 9 | lsd -l 10 | ps 11 | chsh -l 12 | tmux new-session -A -s AXWTV 13 | exit 14 | exitg 15 | exit 16 | ls 17 | starship preset gruvbox-rainbow -o ~/.config/starship.toml 18 | starship preset pure-preset -o ~/.config/starship.toml 19 | chsh -s /bin/zsh 20 | exit 21 | gt 22 | cd .. 23 | exit 24 | $env | reject config | transpose key val | each {|r| echo $"$env.($r.key) = '($r.val)'"} | str join (char nl) 25 | starship preset pure-preset -o ~/.config/starship.toml 26 | starship preset pure-preset -o ~/starship.toml 27 | gt 28 | ls 29 | cd Hyprland-DotFiles/ 30 | cd .. 31 | cd Hyprland-Installer/ 32 | cd .. 33 | starship preset pure-preset -o ~/.config/starship.toml 34 | starship preset pure-preset -o ~/starship.toml 35 | -------------------------------------------------------------------------------- /config/nvim/.stylua.toml: -------------------------------------------------------------------------------- 1 | column_width = 120 2 | line_endings = "Unix" 3 | indent_type = "Spaces" 4 | indent_width = 2 5 | quote_style = "AutoPreferDouble" 6 | call_parentheses = "None" 7 | -------------------------------------------------------------------------------- /config/nvim/init.lua: -------------------------------------------------------------------------------- 1 | vim.g.base46_cache = vim.fn.stdpath "data" .. "/nvchad/base46/" 2 | vim.g.mapleader = " " 3 | 4 | -- bootstrap lazy and all plugins 5 | local lazypath = vim.fn.stdpath "data" .. "/lazy/lazy.nvim" 6 | 7 | if not vim.uv.fs_stat(lazypath) then 8 | local repo = "https://github.com/folke/lazy.nvim.git" 9 | vim.fn.system { "git", "clone", "--filter=blob:none", repo, "--branch=stable", lazypath } 10 | end 11 | 12 | vim.opt.rtp:prepend(lazypath) 13 | 14 | local lazy_config = require "configs.lazy" 15 | 16 | -- load plugins 17 | require("lazy").setup({ 18 | { 19 | "NvChad/NvChad", 20 | lazy = false, 21 | branch = "v2.5", 22 | import = "nvchad.plugins", 23 | }, 24 | 25 | { import = "plugins" }, 26 | }, lazy_config) 27 | 28 | -- load theme 29 | dofile(vim.g.base46_cache .. "defaults") 30 | dofile(vim.g.base46_cache .. "statusline") 31 | 32 | require "options" 33 | require "nvchad.autocmds" 34 | 35 | vim.schedule(function() 36 | require "mappings" 37 | end) 38 | -------------------------------------------------------------------------------- /config/nvim/lua/chadrc.lua: -------------------------------------------------------------------------------- 1 | -- This file needs to have same structure as nvconfig.lua 2 | -- https://github.com/NvChad/ui/blob/v2.5/lua/nvconfig.lua 3 | -- Please read that file to know all available options :( 4 | 5 | ---@type ChadrcConfig 6 | local options = { 7 | 8 | base46 = { 9 | theme = "tokyodark", -- default theme 10 | hl_add = {}, 11 | hl_override = {}, 12 | integrations = {}, 13 | changed_themes = {}, 14 | transparency = true, 15 | theme_toggle = { "tokyodark", "one_light" }, 16 | }, 17 | 18 | ui = { 19 | cmp = { 20 | icons = true, 21 | lspkind_text = true, 22 | style = "default", -- default/flat_light/flat_dark/atom/atom_colored 23 | }, 24 | 25 | telescope = { style = "borderless" }, -- borderless / bordered 26 | 27 | statusline = { 28 | theme = "minimal", -- default/vscode/vscode_colored/minimal 29 | -- default/round/block/arrow separators work only for default statusline theme 30 | -- round and block will work for minimal theme only 31 | separator_style = "round", 32 | order = nil, 33 | modules = nil, 34 | }, 35 | 36 | -- lazyload it when there are 1+ buffers 37 | tabufline = { 38 | enabled = true, 39 | lazyload = true, 40 | order = { "treeOffset", "buffers", "tabs", "btns" }, 41 | modules = nil, 42 | }, 43 | 44 | nvdash = { 45 | load_on_startup = true, 46 | 47 | header = { 48 | " ▄ ▄ ", 49 | " ▄ ▄▄▄ ▄ ▄▄▄ ▄ ▄ ", 50 | " █ ▄ █▄█ ▄▄▄ █ █▄█ █ █ ", 51 | " ▄▄ █▄█▄▄▄█ █▄█▄█▄▄█▄▄█ █ ", 52 | " ▄ █▄▄█ ▄ ▄▄ ▄█ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ", 53 | " █▄▄▄▄ ▄▄▄ █ ▄ ▄▄▄ ▄ ▄▄▄ ▄ ▄ █ ▄", 54 | "▄ █ █▄█ █▄█ █ █ █▄█ █ █▄█ ▄▄▄ █ █", 55 | "█▄█ ▄ █▄▄█▄▄█ █ ▄▄█ █ ▄ █ █▄█▄█ █", 56 | " █▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█ █▄█▄▄▄█ ", 57 | }, 58 | 59 | buttons = { 60 | { " Find File", "Spc f f", "Telescope find_files" }, 61 | { "󰈚 Recent Files", "Spc f o", "Telescope oldfiles" }, 62 | { "󰈭 Find Word", "Spc f w", "Telescope live_grep" }, 63 | { " Bookmarks", "Spc m a", "Telescope marks" }, 64 | { " Themes", "Spc t h", "Telescope themes" }, 65 | { " Mappings", "Spc c h", "NvCheatsheet" }, 66 | }, 67 | }, 68 | }, 69 | 70 | term = { 71 | winopts = { number = false, relativenumber = false }, 72 | sizes = { sp = 0.3, vsp = 0.2, ["bo sp"] = 0.3, ["bo vsp"] = 0.2 }, 73 | float = { 74 | relative = "editor", 75 | row = 0.3, 76 | col = 0.25, 77 | width = 0.5, 78 | height = 0.4, 79 | border = "single", 80 | }, 81 | }, 82 | 83 | lsp = { signature = true }, 84 | 85 | cheatsheet = { 86 | theme = "grid", -- simple/grid 87 | excluded_groups = { "terminal (t)", "autopairs", "Nvim", "Opens" }, -- can add group name or with mode 88 | }, 89 | 90 | mason = { cmd = true, pkgs = {} }, 91 | } 92 | 93 | local status, chadrc = pcall(require, "chadrc") 94 | return vim.tbl_deep_extend("force", options, status and chadrc or {}) 95 | -------------------------------------------------------------------------------- /config/nvim/lua/configs/conform.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | formatters_by_ft = { 3 | lua = { "stylua" }, 4 | -- css = { "prettier" }, 5 | -- html = { "prettier" }, 6 | }, 7 | 8 | -- format_on_save = { 9 | -- -- These options will be passed to conform.format() 10 | -- timeout_ms = 500, 11 | -- lsp_fallback = true, 12 | -- }, 13 | } 14 | 15 | return options 16 | -------------------------------------------------------------------------------- /config/nvim/lua/configs/lazy.lua: -------------------------------------------------------------------------------- 1 | return { 2 | defaults = { lazy = true }, 3 | install = { colorscheme = { "nvchad" } }, 4 | 5 | ui = { 6 | icons = { 7 | ft = "", 8 | lazy = "󰂠 ", 9 | loaded = "", 10 | not_loaded = "", 11 | }, 12 | }, 13 | 14 | performance = { 15 | rtp = { 16 | disabled_plugins = { 17 | "2html_plugin", 18 | "tohtml", 19 | "getscript", 20 | "getscriptPlugin", 21 | "gzip", 22 | "logipat", 23 | "netrw", 24 | "netrwPlugin", 25 | "netrwSettings", 26 | "netrwFileHandlers", 27 | "matchit", 28 | "tar", 29 | "tarPlugin", 30 | "rrhelper", 31 | "spellfile_plugin", 32 | "vimball", 33 | "vimballPlugin", 34 | "zip", 35 | "zipPlugin", 36 | "tutor", 37 | "rplugin", 38 | "syntax", 39 | "synmenu", 40 | "optwin", 41 | "compiler", 42 | "bugreport", 43 | "ftplugin", 44 | }, 45 | }, 46 | }, 47 | } 48 | -------------------------------------------------------------------------------- /config/nvim/lua/configs/lspconfig.lua: -------------------------------------------------------------------------------- 1 | -- load defaults i.e lua_lsp 2 | require("nvchad.configs.lspconfig").defaults() 3 | 4 | local lspconfig = require "lspconfig" 5 | 6 | -- EXAMPLE 7 | local servers = { "html", "cssls" } 8 | local nvlsp = require "nvchad.configs.lspconfig" 9 | 10 | -- lsps with default config 11 | for _, lsp in ipairs(servers) do 12 | lspconfig[lsp].setup { 13 | on_attach = nvlsp.on_attach, 14 | on_init = nvlsp.on_init, 15 | capabilities = nvlsp.capabilities, 16 | } 17 | end 18 | 19 | -- configuring single server, example: typescript 20 | -- lspconfig.tsserver.setup { 21 | -- on_attach = nvlsp.on_attach, 22 | -- on_init = nvlsp.on_init, 23 | -- capabilities = nvlsp.capabilities, 24 | -- } 25 | -------------------------------------------------------------------------------- /config/nvim/lua/mappings.lua: -------------------------------------------------------------------------------- 1 | require "nvchad.mappings" 2 | 3 | -- add yours here 4 | 5 | local map = vim.keymap.set 6 | 7 | map("n", ";", ":", { desc = "CMD enter command mode" }) 8 | map("i", "jk", "") 9 | 10 | -- map({ "n", "i", "v" }, "", " w ") 11 | -------------------------------------------------------------------------------- /config/nvim/lua/options.lua: -------------------------------------------------------------------------------- 1 | require "nvchad.options" 2 | 3 | -- add yours here! 4 | 5 | -- local o = vim.o 6 | -- o.cursorlineopt ='both' -- to enable cursorline! 7 | -------------------------------------------------------------------------------- /config/nvim/lua/plugins/init.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "stevearc/conform.nvim", 4 | -- event = 'BufWritePre', -- uncomment for format on save 5 | opts = require "configs.conform", 6 | }, 7 | 8 | -- These are some examples, uncomment them if you want to see them work! 9 | { 10 | "neovim/nvim-lspconfig", 11 | config = function() 12 | require "configs.lspconfig" 13 | end, 14 | }, 15 | 16 | -- { 17 | -- "nvim-treesitter/nvim-treesitter", 18 | -- opts = { 19 | -- ensure_installed = { 20 | -- "vim", "lua", "vimdoc", 21 | -- "html", "css" 22 | -- }, 23 | -- }, 24 | -- }, 25 | } 26 | -------------------------------------------------------------------------------- /config/qt5ct/colors/Catppuccin-Mocha.conf: -------------------------------------------------------------------------------- 1 | [ColorScheme] 2 | active_colors=#ffcdd6f4, #ff1e1e2e, #ffa6adc8, #ff9399b2, #ff45475a, #ff6c7086, #ffcdd6f4, #ffcdd6f4, #ffcdd6f4, #ff1e1e2e, #ff181825, #ff7f849c, #ff89b4fa, #ff1e1e2e, #ff89b4fa, #fff38ba8, #ff1e1e2e, #ffcdd6f4, #ff11111b, #ffcdd6f4, #807f849c 3 | disabled_colors=#ffa6adc8, #ff1e1e2e, #ffa6adc8, #ff9399b2, #ff45475a, #ff6c7086, #ffa6adc8, #ffa6adc8, #ffa6adc8, #ff1e1e2e, #ff11111b, #ff7f849c, #ff89b4fa, #ff45475a, #ff89b4fa, #fff38ba8, #ff1e1e2e, #ffcdd6f4, #ff11111b, #ffcdd6f4, #807f849c 4 | inactive_colors=#ffcdd6f4, #ff1e1e2e, #ffa6adc8, #ff9399b2, #ff45475a, #ff6c7086, #ffcdd6f4, #ffcdd6f4, #ffcdd6f4, #ff1e1e2e, #ff181825, #ff7f849c, #ff89b4fa, #ffa6adc8, #ff89b4fa, #fff38ba8, #ff1e1e2e, #ffcdd6f4, #ff11111b, #ffcdd6f4, #807f849c 5 | -------------------------------------------------------------------------------- /config/qt5ct/colors/Tokyo-Day.conf: -------------------------------------------------------------------------------- 1 | [ColorScheme] 2 | active_colors=#ff4c4f69, #ffe6e9ef, #ff6c6f85, #ff7c7f93, #ffbcc0cc, #ff9ca0b0, #ff4c4f69, #ff4c4f69, #ff4c4f69, #ffeff1f5, #ffe6e9ef, #ff8c8fa1, #ff1e66f5, #ffeff1f5, #ff7287fd, #ffe64553, #ffeff1f5, #ff4c4f69, #ffdce0e8, #ff4c4f69, #808c8fa1 3 | disabled_colors=#ff6c6f85, #ffe6e9ef, #ff6c6f85, #ff7c7f93, #ffbcc0cc, #ff9ca0b0, #ff6c6f85, #ff6c6f85, #ff6c6f85, #ffeff1f5, #ffe6e9ef, #ff8c8fa1, #ff9ca0b0, #ff5c5f77, #ff7287fd, #ffe64553, #ffeff1f5, #ff4c4f69, #ffdce0e8, #ff4c4f69, #808c8fa1 4 | inactive_colors=#ff4c4f69, #ffe6e9ef, #ff6c6f85, #ff7c7f93, #ffbcc0cc, #ff9ca0b0, #ff4c4f69, #ff4c4f69, #ff4c4f69, #ffeff1f5, #ffe6e9ef, #ff8c8fa1, #ffccd0da, #ff6c6f85, #ff7287fd, #ffe64553, #ffeff1f5, #ff4c4f69, #ffdce0e8, #ff4c4f69, #808c8fa1 5 | -------------------------------------------------------------------------------- /config/qt5ct/colors/Tokyo-Night.conf: -------------------------------------------------------------------------------- 1 | [ColorScheme] 2 | active_colors=#2ac3def4, #bb9af72e, #565f89c8, #bb9af7b2, #ff45475a, #bb9af786, #2ac3def4, #2ac3def4, #2ac3def4, ##bb9af72e, #ff181825, #eb6f929c, #ff89b4fa, ##bb9af72e, #ff89b4fa, #9ccfd8a8, ##bb9af72e, #2ac3def4, #ff11111b, #2ac3def4, #bb9af79c 3 | disabled_colors=#565f89c8, #bb9af72e, #565f89c8, #bb9af7b2, #ff45475a, #bb9af786, #565f89c8, #565f89c8, #565f89c8, ##bb9af72e, #ff11111b, #eb6f929c, #ff89b4fa, #ff45475a, #ff89b4fa, #9ccfd8a8, ##bb9af72e, #2ac3def4, #ff11111b, #2ac3def4, #bb9af79c 4 | inactive_colors=#2ac3def4, #bb9af72e, #565f89c8, #bb9af7b2, #ff45475a, #bb9af786, #2ac3def4, #2ac3def4, #2ac3def4, ##bb9af72e, #ff181825, #eb6f929c, #ff89b4fa, #565f89c8, #ff89b4fa, #9ccfd8a8, ##bb9af72e, #2ac3def4, #ff11111b, #2ac3def4, #bb9af79c 5 | -------------------------------------------------------------------------------- /config/qt5ct/qt5ct.conf: -------------------------------------------------------------------------------- 1 | [Appearance] 2 | color_scheme_path=$HOME/.config/qt5ct/colors/Tokyo-Night.conf 3 | custom_palette=true 4 | icon_theme=Tokyonight-Dark 5 | standard_dialogs=default 6 | style=kvantum 7 | 8 | [Fonts] 9 | fixed="Fira Code Medium,12,-1,5,57,0,0,0,0,0,Regular" 10 | general="Fira Code Medium,14,-1,5,57,0,0,0,0,0,Regular" 11 | 12 | [Interface] 13 | activate_item_on_single_click=1 14 | buttonbox_layout=0 15 | cursor_flash_time=1000 16 | dialog_buttons_have_icons=1 17 | double_click_interval=400 18 | gui_effects=General, AnimateMenu, AnimateCombo, AnimateTooltip, AnimateToolBox 19 | keyboard_scheme=2 20 | menus_have_icons=true 21 | show_shortcuts_in_context_menus=true 22 | stylesheets=@Invalid() 23 | toolbutton_style=4 24 | underline_shortcut=1 25 | wheel_scroll_lines=3 26 | 27 | [SettingsWindow] 28 | geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\x39\0\0\x1\xc8\0\0\x5\a\0\0\x5\x2\0\0\0\0\0\0\0\x14\0\0\x6\xe3\0\0\x5u\0\0\0\0\x2\0\0\0\n\0\0\0\0\x39\0\0\x1\xc8\0\0\x5\a\0\0\x5\x2) 29 | 30 | [Troubleshooting] 31 | force_raster_widgets=1 32 | ignored_applications=@Invalid() 33 | -------------------------------------------------------------------------------- /config/qt6ct/colors/Tokyo-Day.conf: -------------------------------------------------------------------------------- 1 | [ColorScheme] 2 | active_colors=#ff4c4f69, #ffe6e9ef, #ff6c6f85, #ff7c7f93, #ffbcc0cc, #ff9ca0b0, #ff4c4f69, #ff4c4f69, #ff4c4f69, #ffeff1f5, #ffe6e9ef, #ff8c8fa1, #ff1e66f5, #ffeff1f5, #ff7287fd, #ffe64553, #ffeff1f5, #ff4c4f69, #ffdce0e8, #ff4c4f69, #808c8fa1 3 | disabled_colors=#ff6c6f85, #ffe6e9ef, #ff6c6f85, #ff7c7f93, #ffbcc0cc, #ff9ca0b0, #ff6c6f85, #ff6c6f85, #ff6c6f85, #ffeff1f5, #ffe6e9ef, #ff8c8fa1, #ff9ca0b0, #ff5c5f77, #ff7287fd, #ffe64553, #ffeff1f5, #ff4c4f69, #ffdce0e8, #ff4c4f69, #808c8fa1 4 | inactive_colors=#ff4c4f69, #ffe6e9ef, #ff6c6f85, #ff7c7f93, #ffbcc0cc, #ff9ca0b0, #ff4c4f69, #ff4c4f69, #ff4c4f69, #ffeff1f5, #ffe6e9ef, #ff8c8fa1, #ffccd0da, #ff6c6f85, #ff7287fd, #ffe64553, #ffeff1f5, #ff4c4f69, #ffdce0e8, #ff4c4f69, #808c8fa1 5 | -------------------------------------------------------------------------------- /config/qt6ct/colors/Tokyo-Night.conf: -------------------------------------------------------------------------------- 1 | [ColorScheme] 2 | active_colors=#2ac3def4, #bb9af72e, #565f89c8, #bb9af7b2, #ff45475a, #bb9af786, #2ac3def4, #2ac3def4, #2ac3def4, ##bb9af72e, #ff181825, #eb6f929c, #ff89b4fa, ##bb9af72e, #ff89b4fa, #9ccfd8a8, ##bb9af72e, #2ac3def4, #ff11111b, #2ac3def4, #bb9af79c 3 | disabled_colors=#565f89c8, #bb9af72e, #565f89c8, #bb9af7b2, #ff45475a, #bb9af786, #565f89c8, #565f89c8, #565f89c8, ##bb9af72e, #ff11111b, #eb6f929c, #ff89b4fa, #ff45475a, #ff89b4fa, #9ccfd8a8, ##bb9af72e, #2ac3def4, #ff11111b, #2ac3def4, #bb9af79c 4 | inactive_colors=#2ac3def4, #bb9af72e, #565f89c8, #bb9af7b2, #ff45475a, #bb9af786, #2ac3def4, #2ac3def4, #2ac3def4, ##bb9af72e, #ff181825, #eb6f929c, #ff89b4fa, #565f89c8, #ff89b4fa, #9ccfd8a8, ##bb9af72e, #2ac3def4, #ff11111b, #2ac3def4, #bb9af79c 5 | -------------------------------------------------------------------------------- /config/qt6ct/qt6ct.conf: -------------------------------------------------------------------------------- 1 | [Appearance] 2 | color_scheme_path=$HOME/.config/qt6ct/colors/Tokyo-Night.conf 3 | custom_palette=true 4 | icon_theme=TokyoNight-Tokyonight-Dark 5 | standard_dialogs=default 6 | style=kvantum 7 | 8 | [Fonts] 9 | fixed="Fira Code Medium,12,-1,5,57,0,0,0,0,0,Regular" 10 | general="Fira Code Medium,14,-1,5,57,0,0,0,0,0,Regular" 11 | 12 | [Interface] 13 | activate_item_on_single_click=1 14 | buttonbox_layout=0 15 | cursor_flash_time=1000 16 | dialog_buttons_have_icons=1 17 | double_click_interval=400 18 | gui_effects=General, AnimateMenu, AnimateCombo, AnimateTooltip, AnimateToolBox 19 | keyboard_scheme=2 20 | menus_have_icons=true 21 | show_shortcuts_in_context_menus=true 22 | stylesheets=@Invalid() 23 | toolbutton_style=4 24 | underline_shortcut=1 25 | wheel_scroll_lines=3 26 | 27 | [SettingsWindow] 28 | geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\x39\0\0\x1\xc8\0\0\x5\a\0\0\x5\x2\0\0\0\0\0\0\0\x14\0\0\x6\xe3\0\0\x5u\0\0\0\0\x2\0\0\0\n\0\0\0\0\x39\0\0\x1\xc8\0\0\x5\a\0\0\x5\x2) 29 | 30 | [Troubleshooting] 31 | force_raster_widgets=1 32 | ignored_applications=@Invalid() 33 | 34 | -------------------------------------------------------------------------------- /config/swappy/config: -------------------------------------------------------------------------------- 1 | [Default] 2 | save_dir=$HOME/Pictures/Screenshots 3 | save_filename_format=swappy-%Y%m%d-%H%M%S.png 4 | show_pannel=false 5 | line_size=5 6 | text-size=20 7 | paint_mode=brush 8 | early_exit=false 9 | fill_shape=false -------------------------------------------------------------------------------- /config/tmux/README.md: -------------------------------------------------------------------------------- 1 | # Run: 2 | 3 | ```bash 4 | git clone https://github.com/tmux-plugins/tpm.git 5 | ``` 6 | Too install plugins press Prefix(C-Space)+I and Prefix+R to reload config 7 | -------------------------------------------------------------------------------- /config/wal/templates/color-alacritty.toml: -------------------------------------------------------------------------------- 1 | [colors.bright] 2 | black = "{color0}" 3 | blue = "{color4}" 4 | cyan = "{color7}" 5 | green = "{color2}" 6 | magenta = "{color4}" 7 | red = "{color1}" 8 | white = "{color7}" 9 | yellow = "{color3}" 10 | 11 | [colors.normal] 12 | black = "{color0}" 13 | blue = "{color4}" 14 | cyan = "{color6}" 15 | green = "{color10}" 16 | magenta = "{color5}" 17 | red = "{color1}" 18 | white = "{color7}" 19 | yellow = "{color3}" 20 | 21 | [colors.primary] 22 | background = "{color0}" 23 | foreground = "{color7}" 24 | -------------------------------------------------------------------------------- /config/wal/templates/colors-hyprland: -------------------------------------------------------------------------------- 1 | $foregroundCol = 0xff{foreground.strip} 2 | $backgroundCol = 0xff{background.strip} 3 | $color0 = 0xff{color0.strip} 4 | $color1 = 0xff{color1.strip} 5 | $color2 = 0xff{color2.strip} 6 | $color3 = 0xff{color3.strip} 7 | $color4 = 0xff{color4.strip} 8 | $color5 = 0xff{color5.strip} 9 | $color6 = 0xff{color6.strip} 10 | $color7 = 0xff{color7.strip} 11 | $color8 = 0xff{color8.strip} 12 | $color9 = 0xff{color9.strip} 13 | $color10 = 0xff{color10.strip} 14 | $color11 = 0xff{color11.strip} 15 | $color12 = 0xff{color12.strip} 16 | $color13 = 0xff{color13.strip} 17 | $color14 = 0xff{color14.strip} 18 | $color15 = 0xff{color15.strip} 19 | --------------------------------------------------------------------------------