├── .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 | [](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 | 
7 |
8 | 
9 |
10 | 
11 |
12 | 
13 |
14 |
15 |
16 |
17 | 
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 |
5 |
--------------------------------------------------------------------------------
/config/ags/assets/chat-bubbles-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/config/ags/assets/controller-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/config/ags/assets/controls-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/config/ags/assets/dark-mode-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/config/ags/assets/hourglass-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/config/ags/assets/light-mode-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/config/ags/assets/mixer-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/config/ags/assets/processor-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
18 |
--------------------------------------------------------------------------------
/config/ags/assets/terminal-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/config/ags/assets/toolbars-symbolic.svg:
--------------------------------------------------------------------------------
1 |
2 |
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 |
--------------------------------------------------------------------------------