Updated everything
This commit is contained in:
17
.vscode/tasks.json
vendored
17
.vscode/tasks.json
vendored
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Build Hyprland Configuration",
|
||||
"type": "shell",
|
||||
"command": "nix",
|
||||
"args": [
|
||||
"build",
|
||||
".#homeConfigurations.panotaka@Bellerophon.activationPackage"
|
||||
],
|
||||
"group": "build",
|
||||
"isBackground": false,
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
43
docs/lxqt-niri-setup.md
Normal file
43
docs/lxqt-niri-setup.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Example: Enabling LXQt with Niri Window Manager
|
||||
|
||||
To use LXQt with Niri as the window manager in your NixOS configuration, add the following to your host configuration:
|
||||
|
||||
```nix
|
||||
{
|
||||
imports = lib.flatten [
|
||||
# ... other imports ...
|
||||
"hosts/common/optional/lxqt-niri.nix"
|
||||
"hosts/common/optional/gdm.nix" # or sddm.nix for SDDM display manager
|
||||
# ... other imports ...
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
## What this provides
|
||||
|
||||
- **LXQt Desktop Environment**: Full LXQt suite including panel, file manager, settings tools, and applications
|
||||
- **Niri Window Manager**: Modern tiling Wayland compositor with smooth animations
|
||||
- **Qt Theming**: Proper Qt theming integration with LXQt themes and Kvantum support
|
||||
- **System Integration**: Audio (PipeWire), network management, power management, and hardware support
|
||||
- **XDG Portals**: Screen sharing and file picker integration for Wayland applications
|
||||
|
||||
## Session Selection
|
||||
|
||||
After adding this configuration and rebuilding your system, you'll see "LXQt (Niri)" as an option in your display manager's session selection menu.
|
||||
|
||||
## Additional Notes
|
||||
|
||||
- The configuration enables X11 server support for compatibility with X11-only applications
|
||||
- Network management is handled through NetworkManager with Qt frontend
|
||||
- Audio is configured with PipeWire for low-latency audio
|
||||
- The setup includes proper polkit integration for system authentication dialogs
|
||||
- Bluetooth support is enabled by default
|
||||
|
||||
## Customization
|
||||
|
||||
You can further customize the LXQt-Niri experience by:
|
||||
|
||||
- Adding additional LXQt applications to your user packages
|
||||
- Configuring Niri-specific settings through its configuration files
|
||||
- Using LXQt's appearance settings to customize themes and styling
|
||||
- Adding additional Qt applications that integrate well with the LXQt environment
|
||||
253
flake.lock
generated
253
flake.lock
generated
@@ -8,11 +8,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1755729720,
|
||||
"narHash": "sha256-F6NKjTnVe5we9N7HAux1LEibshcTOndmm18TePGWQ68=",
|
||||
"lastModified": 1757330146,
|
||||
"narHash": "sha256-ujlZerjj0ouA63nftpoHF/tA+xE5gDJZVBuuZP6YS+Q=",
|
||||
"owner": "aylur",
|
||||
"repo": "ags",
|
||||
"rev": "c674fe0e4130cec4f16e620c1fe30183cdb055f4",
|
||||
"rev": "5347d21c2289df157e91e297daa37572e0d277b5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -29,11 +29,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1752404970,
|
||||
"narHash": "sha256-XULTToDUkIshNXEO+YP2mAHdQv8bxWDvKjbamBfOC8E=",
|
||||
"lastModified": 1756474652,
|
||||
"narHash": "sha256-iiBU6itpEqE0spXeNJ3uJTfioSyKYjt5bNepykpDXTE=",
|
||||
"owner": "aylur",
|
||||
"repo": "astal",
|
||||
"rev": "2c5eb54f39e1710c6e2c80915a240978beb3269a",
|
||||
"rev": "20bd8318e4136fbd3d4eb2d64dbabc3acbc915dd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -47,11 +47,11 @@
|
||||
"fromYaml": "fromYaml"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1746562888,
|
||||
"narHash": "sha256-YgNJQyB5dQiwavdDFBMNKk1wyS77AtdgDk/VtU6wEaI=",
|
||||
"lastModified": 1755819240,
|
||||
"narHash": "sha256-qcMhnL7aGAuFuutH4rq9fvAhCpJWVHLcHVZLtPctPlo=",
|
||||
"owner": "SenchoPens",
|
||||
"repo": "base16.nix",
|
||||
"rev": "806a1777a5db2a1ef9d5d6f493ef2381047f2b89",
|
||||
"rev": "75ed5e5e3fce37df22e49125181fa37899c3ccd6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -141,20 +141,67 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"caelestia-cli": {
|
||||
"inputs": {
|
||||
"caelestia-shell": [
|
||||
"caelestia-shell"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"caelestia-shell",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1757772762,
|
||||
"narHash": "sha256-7m4hqYSgRe68lkzHFLb1GN5gQac4X4akKfKgFvhj/34=",
|
||||
"owner": "caelestia-dots",
|
||||
"repo": "cli",
|
||||
"rev": "62e7911864ce6ec8a0b371735cf640d81821100e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "caelestia-dots",
|
||||
"repo": "cli",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"caelestia-shell": {
|
||||
"inputs": {
|
||||
"caelestia-cli": "caelestia-cli",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"quickshell": "quickshell"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1758031737,
|
||||
"narHash": "sha256-D9e9R64xox8swabXvu0DEf8goazQGypjuLe6u7ejZ/k=",
|
||||
"owner": "caelestia-dots",
|
||||
"repo": "shell",
|
||||
"rev": "542495c74faff1285fa7371d2e5cbb2e5294ef9d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "caelestia-dots",
|
||||
"repo": "shell",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"devenv": {
|
||||
"inputs": {
|
||||
"cachix": "cachix",
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-parts": "flake-parts",
|
||||
"git-hooks": "git-hooks",
|
||||
"nix": "nix",
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1755784454,
|
||||
"narHash": "sha256-5LJOcUS2LoSg7qrNCPdOlBHA9YL3cMJVAqXu26DJNjw=",
|
||||
"lastModified": 1757928168,
|
||||
"narHash": "sha256-smFckXZeYHoS6330QBZf0K7JrmN+1hsHmIesKqTzU6U=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "6edd3ff0206feedfd50a9e3295e0d9302131eaed",
|
||||
"rev": "d9019631e0e965b78f94a63246863fa7d8315d17",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -170,11 +217,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1755519972,
|
||||
"narHash": "sha256-bU4nqi3IpsUZJeyS8Jk85ytlX61i4b0KCxXX9YcOgVc=",
|
||||
"lastModified": 1757508292,
|
||||
"narHash": "sha256-7lVWL5bC6xBIMWWDal41LlGAG+9u2zUorqo3QCUL4p4=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "4073ff2f481f9ef3501678ff479ed81402caae6d",
|
||||
"rev": "146f45bee02b8bd88812cfce6ffc0f933788875a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -186,11 +233,11 @@
|
||||
"firefox-gnome-theme": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1748383148,
|
||||
"narHash": "sha256-pGvD/RGuuPf/4oogsfeRaeMm6ipUIznI2QSILKjKzeA=",
|
||||
"lastModified": 1756083905,
|
||||
"narHash": "sha256-UqYGTBgI5ypGh0Kf6zZjom/vABg7HQocB4gmxzl12uo=",
|
||||
"owner": "rafaelmardojai",
|
||||
"repo": "firefox-gnome-theme",
|
||||
"rev": "4eb2714fbed2b80e234312611a947d6cb7d70caf",
|
||||
"rev": "b655eaf16d4cbec9c3472f62eee285d4b419a808",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -235,16 +282,15 @@
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"devenv",
|
||||
"nix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1733312601,
|
||||
"narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=",
|
||||
"lastModified": 1756770412,
|
||||
"narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9",
|
||||
"rev": "4524271976b625a4a605beefd893f270620fd751",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -261,11 +307,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1751413152,
|
||||
"narHash": "sha256-Tyw1RjYEsp5scoigs1384gIg6e0GoBVjms4aXFfRssQ=",
|
||||
"lastModified": 1756770412,
|
||||
"narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "77826244401ea9de6e3bac47c2db46005e1f30b5",
|
||||
"rev": "4524271976b625a4a605beefd893f270620fd751",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -378,11 +424,11 @@
|
||||
},
|
||||
"hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1755330281,
|
||||
"narHash": "sha256-aJHFJWP9AuI8jUGzI77LYcSlkA9wJnOIg4ZqftwNGXA=",
|
||||
"lastModified": 1757943327,
|
||||
"narHash": "sha256-w6cDExPBqbq7fTLo4dZ1ozDGeq3yV6dSN4n/sAaS6OM=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "3dac8a872557e0ca8c083cdcfc2f218d18e113b0",
|
||||
"rev": "67a709cfe5d0643dafd798b0b613ed579de8be05",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -398,11 +444,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1755755322,
|
||||
"narHash": "sha256-spCxkNihCk3uT3LUrUwzdEAjLA/E0EtEgF3KVI05nlM=",
|
||||
"lastModified": 1757997814,
|
||||
"narHash": "sha256-F+1aoG+3NH4jDDEmhnDUReISyq6kQBBuktTUqCUWSiw=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "282b4c98de97da6667cb03de4f427371734bc39c",
|
||||
"rev": "5820376beb804de9acf07debaaff1ac84728b708",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -444,11 +490,11 @@
|
||||
"xwayland-satellite-unstable": "xwayland-satellite-unstable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1755424351,
|
||||
"narHash": "sha256-xcorYLNdtLpb0wH5CPlUcpmYQUxeK95j1X855xQw+DY=",
|
||||
"lastModified": 1758006511,
|
||||
"narHash": "sha256-YmZX6Wydog4Q9p7dRZDFOFkUfCtQfoXRobmJdg3F1dg=",
|
||||
"owner": "sodiboo",
|
||||
"repo": "niri-flake",
|
||||
"rev": "9aa137af01f05386e5bb5050e983750017007a66",
|
||||
"rev": "0be585b11314ac02804b4fe03196116c4f747d6d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -460,16 +506,16 @@
|
||||
"niri-stable": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1748151941,
|
||||
"narHash": "sha256-z4viQZLgC2bIJ3VrzQnR+q2F3gAOEQpU1H5xHtX/2fs=",
|
||||
"lastModified": 1756556321,
|
||||
"narHash": "sha256-RLD89dfjN0RVO86C/Mot0T7aduCygPGaYbog566F0Qo=",
|
||||
"owner": "YaLTeR",
|
||||
"repo": "niri",
|
||||
"rev": "8ba57fcf25d2fc9565131684a839d58703f1dae7",
|
||||
"rev": "01be0e65f4eb91a9cd624ac0b76aaeab765c7294",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "YaLTeR",
|
||||
"ref": "v25.05.1",
|
||||
"ref": "v25.08",
|
||||
"repo": "niri",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -477,11 +523,11 @@
|
||||
"niri-unstable": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1755419373,
|
||||
"narHash": "sha256-EFH3zbpyLYjEboNV2Lmkxf9joEuFCmeYX+MMLRPStpg=",
|
||||
"lastModified": 1758000903,
|
||||
"narHash": "sha256-FyfB40rl2mbRGIvF2/6Iwv9xHDxOmhaE1MhlV6Efsg4=",
|
||||
"owner": "YaLTeR",
|
||||
"repo": "niri",
|
||||
"rev": "a6febb86aa5af0df7bf2792ca027ef95a503d599",
|
||||
"rev": "c30e5c91851d77d48ff2120f0e710501b19d61b4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -496,7 +542,10 @@
|
||||
"devenv",
|
||||
"flake-compat"
|
||||
],
|
||||
"flake-parts": "flake-parts",
|
||||
"flake-parts": [
|
||||
"devenv",
|
||||
"flake-parts"
|
||||
],
|
||||
"git-hooks-nix": [
|
||||
"devenv",
|
||||
"git-hooks"
|
||||
@@ -534,11 +583,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1755751773,
|
||||
"narHash": "sha256-d1H34kko9J5fWrxCVgfa1TkIwdkGt/eDSVopAWenw24=",
|
||||
"lastModified": 1757430124,
|
||||
"narHash": "sha256-MhDltfXesGH8VkGv3hmJ1QEKl1ChTIj9wmGAFfWj/Wk=",
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "3a0a38a1e7ac2c4b4150ea37a491fdffdc9c92e1",
|
||||
"rev": "830b3f0b50045cf0bcfd4dab65fad05bf882e196",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -555,11 +604,11 @@
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1755741555,
|
||||
"narHash": "sha256-95N5X0MHiGkCSudjPqA/Grvnhlz+XEzjnnLruG37iog=",
|
||||
"lastModified": 1757987447,
|
||||
"narHash": "sha256-VbCSJEbiNtt8VTGkhCbSLwIs45013DHCXw2s8O27Xxs=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix4vscode",
|
||||
"rev": "69b1b5ad001042ce730ca5c2ecc0f693ccadc94b",
|
||||
"rev": "ac15473ac105ddb22395639470ad338e3c4fc7c9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -570,11 +619,11 @@
|
||||
},
|
||||
"nixos-hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1755330281,
|
||||
"narHash": "sha256-aJHFJWP9AuI8jUGzI77LYcSlkA9wJnOIg4ZqftwNGXA=",
|
||||
"lastModified": 1757943327,
|
||||
"narHash": "sha256-w6cDExPBqbq7fTLo4dZ1ozDGeq3yV6dSN4n/sAaS6OM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "3dac8a872557e0ca8c083cdcfc2f218d18e113b0",
|
||||
"rev": "67a709cfe5d0643dafd798b0b613ed579de8be05",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -617,11 +666,11 @@
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1755274400,
|
||||
"narHash": "sha256-rTInmnp/xYrfcMZyFMH3kc8oko5zYfxsowaLv1LVobY=",
|
||||
"lastModified": 1757810152,
|
||||
"narHash": "sha256-Vp9K5ol6h0J90jG7Rm4RWZsCB3x7v5VPx588TQ1dkfs=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ad7196ae55c295f53a7d1ec39e4a06d922f3b899",
|
||||
"rev": "9a094440e02a699be5c57453a092a8baf569bdad",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -633,11 +682,11 @@
|
||||
},
|
||||
"nixpkgs-stable_2": {
|
||||
"locked": {
|
||||
"lastModified": 1755704039,
|
||||
"narHash": "sha256-gKlP0LbyJ3qX0KObfIWcp5nbuHSb5EHwIvU6UcNBg2A=",
|
||||
"lastModified": 1757810152,
|
||||
"narHash": "sha256-Vp9K5ol6h0J90jG7Rm4RWZsCB3x7v5VPx588TQ1dkfs=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9cb344e96d5b6918e94e1bca2d9f3ea1e9615545",
|
||||
"rev": "9a094440e02a699be5c57453a092a8baf569bdad",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -649,11 +698,11 @@
|
||||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1755615617,
|
||||
"narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=",
|
||||
"lastModified": 1757745802,
|
||||
"narHash": "sha256-hLEO2TPj55KcUFUU1vgtHE9UEIOjRcH/4QbmfHNF820=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "20075955deac2583bb12f07151c2df830ef346b4",
|
||||
"rev": "c23193b943c6c689d70ee98ce3128239ed9e32d1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -665,11 +714,11 @@
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1755615617,
|
||||
"narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=",
|
||||
"lastModified": 1757745802,
|
||||
"narHash": "sha256-hLEO2TPj55KcUFUU1vgtHE9UEIOjRcH/4QbmfHNF820=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "20075955deac2583bb12f07151c2df830ef346b4",
|
||||
"rev": "c23193b943c6c689d70ee98ce3128239ed9e32d1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -691,11 +740,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1751906969,
|
||||
"narHash": "sha256-BSQAOdPnzdpOuCdAGSJmefSDlqmStFNScEnrWzSqKPw=",
|
||||
"lastModified": 1756961635,
|
||||
"narHash": "sha256-hETvQcILTg5kChjYNns1fD5ELdsYB/VVgVmBtqKQj9A=",
|
||||
"owner": "nix-community",
|
||||
"repo": "NUR",
|
||||
"rev": "ddb679f4131e819efe3bbc6457ba19d7ad116f25",
|
||||
"rev": "6ca27b2654ac55e3f6e0ca434c1b4589ae22b370",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -713,11 +762,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1755446520,
|
||||
"narHash": "sha256-I0Ok1OGDwc1jPd8cs2VvAYZsHriUVFGIUqW+7uSsOUM=",
|
||||
"lastModified": 1757974173,
|
||||
"narHash": "sha256-4DpXmct/2rcLgScT1CXOLr0TUeIlrBB1rnFqCOf5MUw=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "4b04db83821b819bbbe32ed0a025b31e7971f22e",
|
||||
"rev": "302af509428169db34f268324162712d10559f74",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -726,9 +775,31 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"quickshell": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"caelestia-shell",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1756981260,
|
||||
"narHash": "sha256-GhuD9QVimjynHI0OOyZsqJsnlXr2orowh9H+HYz4YMs=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "6eb12551baf924f8fdecdd04113863a754259c34",
|
||||
"revCount": 672,
|
||||
"type": "git",
|
||||
"url": "https://git.outfoxxed.me/outfoxxed/quickshell"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://git.outfoxxed.me/outfoxxed/quickshell"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"ags": "ags",
|
||||
"caelestia-shell": "caelestia-shell",
|
||||
"devenv": "devenv",
|
||||
"disko": "disko",
|
||||
"hardware": "hardware",
|
||||
@@ -767,11 +838,11 @@
|
||||
"tinted-zed": "tinted-zed"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1755708361,
|
||||
"narHash": "sha256-RmqBx2EamhIk0WVhQSNb8iehaVhilO7D0YAnMoFPqJQ=",
|
||||
"lastModified": 1757956156,
|
||||
"narHash": "sha256-f0W7qbsCqpi6swQ5w8H+0YrAbNwsHgCFDkNRMTJjqrE=",
|
||||
"owner": "danth",
|
||||
"repo": "stylix",
|
||||
"rev": "2355da455d7188228aaf20ac16ea9386e5aa6f0c",
|
||||
"rev": "0ce0103b498bb22f899ed8862d8d7f9503ed9cdb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -847,11 +918,11 @@
|
||||
"tinted-schemes": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1750770351,
|
||||
"narHash": "sha256-LI+BnRoFNRa2ffbe3dcuIRYAUcGklBx0+EcFxlHj0SY=",
|
||||
"lastModified": 1754779259,
|
||||
"narHash": "sha256-8KG2lXGaXLUE0F/JVwLQe7kOVm21IDfNEo0gfga5P4M=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "schemes",
|
||||
"rev": "5a775c6ffd6e6125947b393872cde95867d85a2a",
|
||||
"rev": "097d751b9e3c8b97ce158e7d141e5a292545b502",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -863,11 +934,11 @@
|
||||
"tinted-tmux": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1751159871,
|
||||
"narHash": "sha256-UOHBN1fgHIEzvPmdNMHaDvdRMgLmEJh2hNmDrp3d3LE=",
|
||||
"lastModified": 1754788770,
|
||||
"narHash": "sha256-LAu5nBr7pM/jD9jwFc6/kyFY4h7Us4bZz7dvVvehuwo=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-tmux",
|
||||
"rev": "bded5e24407cec9d01bd47a317d15b9223a1546c",
|
||||
"rev": "fb2175accef8935f6955503ec9dd3c973eec385c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -879,11 +950,11 @@
|
||||
"tinted-zed": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1751158968,
|
||||
"narHash": "sha256-ksOyv7D3SRRtebpXxgpG4TK8gZSKFc4TIZpR+C98jX8=",
|
||||
"lastModified": 1755613540,
|
||||
"narHash": "sha256-zBFrrTxHLDMDX/OYxkCwGGbAhPXLi8FrnLhYLsSOKeY=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "base16-zed",
|
||||
"rev": "86a470d94204f7652b906ab0d378e4231a5b3384",
|
||||
"rev": "937bada16cd3200bdbd3a2f5776fc3b686d5cba0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -895,16 +966,16 @@
|
||||
"xwayland-satellite-stable": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1748488455,
|
||||
"narHash": "sha256-IiLr1alzKFIy5tGGpDlabQbe6LV1c9ABvkH6T5WmyRI=",
|
||||
"lastModified": 1755491097,
|
||||
"narHash": "sha256-m+9tUfsmBeF2Gn4HWa6vSITZ4Gz1eA1F5Kh62B0N4oE=",
|
||||
"owner": "Supreeeme",
|
||||
"repo": "xwayland-satellite",
|
||||
"rev": "3ba30b149f9eb2bbf42cf4758d2158ca8cceef73",
|
||||
"rev": "388d291e82ffbc73be18169d39470f340707edaa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Supreeeme",
|
||||
"ref": "v0.6",
|
||||
"ref": "v0.7",
|
||||
"repo": "xwayland-satellite",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -912,11 +983,11 @@
|
||||
"xwayland-satellite-unstable": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1755219541,
|
||||
"narHash": "sha256-yKV6xHaPbEbh5RPxAJnb9yTs1wypr7do86hFFGQm1w8=",
|
||||
"lastModified": 1757179758,
|
||||
"narHash": "sha256-TIvyWzRt1miQj6Cf5Wy8Qz43XIZX7c4vTVwRLAT5S4Y=",
|
||||
"owner": "Supreeeme",
|
||||
"repo": "xwayland-satellite",
|
||||
"rev": "5a184d435927c3423f0ad189ea2b490578450fb7",
|
||||
"rev": "970728d0d9d1eada342bb8860af214b601139e58",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -933,11 +1004,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1755745641,
|
||||
"narHash": "sha256-dk5XmelXuuIPr7twSyVlxcORlRKr7ch68wXd1Bz+T4c=",
|
||||
"lastModified": 1757999874,
|
||||
"narHash": "sha256-kgV3ms4hR86tIxaNAYJI8NNgkmEygN+JwkXCPAx2P2U=",
|
||||
"owner": "0xc000022070",
|
||||
"repo": "zen-browser-flake",
|
||||
"rev": "e00337af97e646e0ecb94097983f33bda767fb41",
|
||||
"rev": "7dcbd22ca3943e4cfb3122f96cf515f028b3236a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -182,6 +182,11 @@
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
caelestia-shell = {
|
||||
url = "github:caelestia-dots/shell";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
#
|
||||
# ========= Personal Repositories =========
|
||||
#
|
||||
|
||||
@@ -1,7 +1,41 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
{pkgs, ...}: {
|
||||
fonts.fontconfig.enable = true;
|
||||
home.packages = [
|
||||
pkgs.noto-fonts
|
||||
home.packages = with pkgs; [
|
||||
noto-fonts
|
||||
noto-fonts-cjk-sans
|
||||
noto-fonts-emoji
|
||||
noto-fonts-extra
|
||||
liberation_ttf
|
||||
dejavu_fonts
|
||||
fira-code
|
||||
fira-mono
|
||||
jetbrains-mono
|
||||
source-code-pro
|
||||
hack-font
|
||||
roboto
|
||||
roboto-mono
|
||||
font-awesome
|
||||
material-design-icons
|
||||
inter
|
||||
ibm-plex
|
||||
sarasa-gothic
|
||||
unifont
|
||||
dina-font
|
||||
# proggyfonts - removed due to collision with dina-font fonts.dir
|
||||
terminus_font
|
||||
mplus-outline-fonts.osdnRelease
|
||||
open-sans
|
||||
# Droid fonts are now in android-fonts-droid
|
||||
# droid-sans
|
||||
# droid-serif
|
||||
# droid-sans-mono
|
||||
cantarell-fonts
|
||||
recursive
|
||||
# google-fonts - removed due to collision with jetbrains-mono
|
||||
# Microsoft fonts
|
||||
corefonts
|
||||
vistafonts
|
||||
# webcore-fonts - removed package
|
||||
cascadia-code
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = with pkgs; [
|
||||
oterm
|
||||
# oterm removed
|
||||
];
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
./btop.nix
|
||||
./carapace.nix
|
||||
./common.nix
|
||||
./devenv.nix
|
||||
./direnv.nix
|
||||
./eza.nix
|
||||
./fish.nix
|
||||
|
||||
3
home/panotaka/common/core/shell/devenv.nix
Normal file
3
home/panotaka/common/core/shell/devenv.nix
Normal file
@@ -0,0 +1,3 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = [pkgs.devenv];
|
||||
}
|
||||
@@ -3,14 +3,17 @@
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
|
||||
# Global SSH settings
|
||||
addKeysToAgent = "yes";
|
||||
controlMaster = "auto";
|
||||
controlPath = "${config.home.homeDirectory}/.ssh/sockets/S.%r@%h:%p";
|
||||
controlPersist = "20m";
|
||||
# Avoids infinite hang if control socket connection interrupted. ex: vpn goes down/up
|
||||
serverAliveCountMax = 3;
|
||||
serverAliveInterval = 5; # 3 * 5s
|
||||
hashKnownHosts = true;
|
||||
addKeysToAgent = "yes";
|
||||
|
||||
# Set default values for all hosts
|
||||
matchBlocks."*" = {};
|
||||
};
|
||||
home.file = {
|
||||
".ssh/config.d/.keep".text = "# Managed by Home Manager";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{pkgs, ...}: {
|
||||
programs.vscode = {
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
"GitHub.copilot"
|
||||
"GitHub.copilot-chat"
|
||||
];
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
enableUpdateCheck = false; # Let Home Manager manage VSCode versions
|
||||
enableExtensionUpdateCheck = false; # Let nix4vscode manage extensions
|
||||
mutableExtensionsDir = false;
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
# --- General ---
|
||||
"britesnow.vscode-toggle-quotes"
|
||||
"mrmlnc.vscode-duplicate"
|
||||
@@ -35,7 +35,7 @@
|
||||
"ms-python.python"
|
||||
"jock.svg"
|
||||
"redhat.vscode-yaml"
|
||||
"arrterian.nix-env-selector"
|
||||
"mkhl.direnv"
|
||||
];
|
||||
userSettings = {
|
||||
# --- Privacy & Telemetry ---
|
||||
@@ -59,6 +59,7 @@
|
||||
"window.titleBarStyle" = "native";
|
||||
"workbench.navigationControl.enabled" = false;
|
||||
"workbench.layoutControl.enabled" = false;
|
||||
|
||||
# --- Extension-specific telemetry opt-outs ---
|
||||
"code-runner.enableAppInsights" = false;
|
||||
"docker-explorer.enableTelemetry" = false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{pkgs, ...}: {
|
||||
programs.vscode = {
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
# CSV language support
|
||||
"mechatroner.rainbow-csv"
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{pkgs, ...}: {
|
||||
programs.vscode = {
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
# Godot language support
|
||||
"geequlim.godot-tools"
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{pkgs, ...}: {
|
||||
programs.vscode = {
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
# Go language support
|
||||
"golang.go"
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{pkgs, ...}: {
|
||||
programs.vscode = {
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
# General
|
||||
"christian-kohler.npm-intellisense"
|
||||
"dbaeumer.vscode-eslint"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{pkgs, ...}: {
|
||||
programs.vscode = {
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
# General
|
||||
"james-yu.latex-workshop"
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{pkgs, ...}: {
|
||||
programs.vscode = {
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
# General
|
||||
"bpruitt-goddard.mermaid-markdown-syntax-highlighting"
|
||||
"davidanson.vscode-markdownlint"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{pkgs, ...}: {
|
||||
programs.vscode = {
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
# Nix language support
|
||||
"jnoortheen.nix-ide"
|
||||
"kamadorueda.alejandra"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{pkgs, ...}: {
|
||||
programs.vscode = {
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
# Python language support
|
||||
"ms-python.python"
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{pkgs, ...}: {
|
||||
programs.vscode = {
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
# Rust language support
|
||||
"barbosshack.crates-io"
|
||||
"tamasfe.even-better-toml"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{pkgs, ...}: {
|
||||
programs.vscode = {
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
# SVG language support
|
||||
"jock.svg"
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{pkgs, ...}: {
|
||||
programs.vscode = {
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
# YAML language support
|
||||
"redhat.vscode-yaml"
|
||||
];
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}: {
|
||||
# GNOME desktop packages
|
||||
@@ -12,6 +13,8 @@
|
||||
# It's usually part of mutter/gnome-shell, we'll use gdbus calls instead
|
||||
inotify-tools # for watching USB changes
|
||||
iio-sensor-proxy # for rotation detection (includes monitor-sensor)
|
||||
xdotool # for monitor focus detection
|
||||
papers
|
||||
|
||||
# GNOME Extensions
|
||||
gnomeExtensions.dash-to-dock
|
||||
@@ -25,6 +28,7 @@
|
||||
gnomeExtensions.launch-new-instance
|
||||
gnomeExtensions.paperwm
|
||||
gnomeExtensions.just-perfection
|
||||
gnomeExtensions.touchpad-gesture-customization
|
||||
];
|
||||
|
||||
# GNOME desktop settings via dconf
|
||||
@@ -52,6 +56,7 @@
|
||||
"launch-new-instance@gnome-shell-extensions.gcampax.github.com"
|
||||
"paperwm@paperwm.github.com"
|
||||
"just-perfection@just-perfection"
|
||||
"touchpad-gesture-customization@rexhsu"
|
||||
];
|
||||
};
|
||||
|
||||
@@ -72,6 +77,21 @@
|
||||
experimental-features = ["scale-monitor-framebuffer" "variable-refresh-rate"];
|
||||
};
|
||||
|
||||
# Settings for Just Perfection extension (hide panel, disable overview/hot-corner)
|
||||
"org/gnome/shell/extensions/just-perfection" = {
|
||||
# --- Visibility ---
|
||||
panel-visibility = false; # Hides the entire top bar (panel)
|
||||
# panel-in-session-visibility = false; # Alternative if the above doesn't work
|
||||
|
||||
# --- Behavior ---
|
||||
activities-overview = false; # Disables the overview
|
||||
super-key-action = "disabled"; # Prevents Super key from opening overview
|
||||
hot-corner = false; # Disables the top-left hot corner
|
||||
|
||||
# --- Icons (if you decide to keep the panel) ---
|
||||
# activities-button = false; # Hides the "Activities" button
|
||||
};
|
||||
|
||||
# PaperWM extension settings placeholder
|
||||
"org/gnome/shell/extensions/paperwm" = {
|
||||
# Add any PaperWM-specific dconf keys here if needed
|
||||
@@ -87,4 +107,7 @@
|
||||
close = ["<Super>q"];
|
||||
};
|
||||
};
|
||||
|
||||
# Note: Monitor workspace management is now handled by the custom GNOME extension
|
||||
# instead of a systemd service with a shell script
|
||||
}
|
||||
|
||||
@@ -0,0 +1,462 @@
|
||||
{
|
||||
inputs,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
# Import caelestia-shell home manager module
|
||||
imports = [
|
||||
inputs.caelestia-shell.homeManagerModules.default
|
||||
];
|
||||
|
||||
# Add packages required for Caelestia Shell functionality
|
||||
home.packages = with pkgs; [
|
||||
# Required for network functionality
|
||||
networkmanager
|
||||
# For brightness control
|
||||
brightnessctl
|
||||
# For audio visualization
|
||||
cava
|
||||
# For calculations in launcher
|
||||
libqalculate
|
||||
# For screenshot functionality
|
||||
swappy
|
||||
# For clipboard
|
||||
wl-clipboard
|
||||
# For authentication dialogs (WiFi passwords, etc.)
|
||||
kdePackages.polkit-kde-agent-1
|
||||
# For storing WiFi passwords securely
|
||||
gnome-keyring
|
||||
libsecret
|
||||
];
|
||||
|
||||
# Set up wallpapers directory and sync with Stylix
|
||||
home.file."Pictures/Wallpapers/stylix-wallpaper" = {
|
||||
source = config.stylix.image;
|
||||
enable = config.stylix.image != null;
|
||||
};
|
||||
|
||||
# Caelestia Shell configuration based on https://github.com/caelestia-dots/shell
|
||||
# Integrated with Stylix theming system
|
||||
programs.caelestia = {
|
||||
enable = true;
|
||||
systemd = {
|
||||
enable = true; # if you prefer starting from your compositor
|
||||
target = "graphical-session.target";
|
||||
environment = [];
|
||||
};
|
||||
settings = let
|
||||
# Access Stylix fonts
|
||||
fonts = config.stylix.fonts;
|
||||
in {
|
||||
# ===== APPEARANCE SETTINGS =====
|
||||
appearance = {
|
||||
# Font configuration using Stylix fonts
|
||||
font = {
|
||||
family = {
|
||||
material = "Material Symbols Rounded";
|
||||
mono = fonts.monospace.name;
|
||||
sans = fonts.sansSerif.name;
|
||||
};
|
||||
size = {
|
||||
scale = 1; # Keep default scaling, adjust if needed
|
||||
};
|
||||
};
|
||||
|
||||
# Transparency settings
|
||||
transparency = {
|
||||
enabled = true;
|
||||
base = 0.90; # Adjust based on preference
|
||||
layers = 0.3;
|
||||
};
|
||||
|
||||
# Spacing and layout
|
||||
padding.scale = 1;
|
||||
rounding.scale = 1;
|
||||
spacing.scale = 1;
|
||||
|
||||
# Animation settings
|
||||
anim.durations.scale = 1;
|
||||
};
|
||||
|
||||
# ===== BAR CONFIGURATION =====
|
||||
bar = {
|
||||
persistent = true;
|
||||
showOnHover = false;
|
||||
|
||||
# Ensure bar entries are explicitly defined
|
||||
entries = [
|
||||
{
|
||||
id = "logo";
|
||||
enabled = true;
|
||||
}
|
||||
{
|
||||
id = "workspaces";
|
||||
enabled = true;
|
||||
}
|
||||
{
|
||||
id = "spacer";
|
||||
enabled = true;
|
||||
}
|
||||
{
|
||||
id = "activeWindow";
|
||||
enabled = true;
|
||||
}
|
||||
{
|
||||
id = "spacer";
|
||||
enabled = true;
|
||||
}
|
||||
{
|
||||
id = "tray";
|
||||
enabled = true;
|
||||
}
|
||||
{
|
||||
id = "clock";
|
||||
enabled = true;
|
||||
}
|
||||
{
|
||||
id = "statusIcons";
|
||||
enabled = true;
|
||||
}
|
||||
{
|
||||
id = "power";
|
||||
enabled = true;
|
||||
}
|
||||
{
|
||||
id = "idleInhibitor";
|
||||
enabled = false;
|
||||
}
|
||||
];
|
||||
|
||||
# Status indicators
|
||||
status = {
|
||||
showAudio = true;
|
||||
showBattery = true;
|
||||
showBluetooth = true;
|
||||
showKbLayout = false;
|
||||
showMicrophone = false;
|
||||
showNetwork = true;
|
||||
showLockStatus = true;
|
||||
};
|
||||
|
||||
# Clock settings
|
||||
clock = {
|
||||
showIcon = true;
|
||||
};
|
||||
|
||||
# Workspace configuration
|
||||
workspaces = {
|
||||
activeIndicator = true;
|
||||
activeLabel = "";
|
||||
activeTrail = false;
|
||||
label = " ";
|
||||
occupiedBg = true;
|
||||
occupiedLabel = "";
|
||||
perMonitorWorkspaces = true;
|
||||
showWindows = true;
|
||||
shown = 5;
|
||||
};
|
||||
|
||||
# Tray configuration
|
||||
tray = {
|
||||
background = false;
|
||||
iconSubs = [];
|
||||
recolour = true; # Recolor tray icons to match theme
|
||||
};
|
||||
|
||||
# Scroll actions
|
||||
scrollActions = {
|
||||
brightness = true;
|
||||
workspaces = true;
|
||||
volume = true;
|
||||
};
|
||||
|
||||
dragThreshold = 20;
|
||||
};
|
||||
|
||||
# ===== DASHBOARD =====
|
||||
dashboard = {
|
||||
enabled = true;
|
||||
dragThreshold = 50;
|
||||
mediaUpdateInterval = 500;
|
||||
showOnHover = true;
|
||||
};
|
||||
|
||||
# ===== LAUNCHER =====
|
||||
launcher = {
|
||||
actionPrefix = ">";
|
||||
specialPrefix = "@";
|
||||
dragThreshold = 50;
|
||||
vimKeybinds = false;
|
||||
enableDangerousActions = true;
|
||||
maxShown = 8;
|
||||
maxWallpapers = 9;
|
||||
showOnHover = false;
|
||||
hiddenApps = [];
|
||||
|
||||
# Enable more powerful fuzzy search for better UX
|
||||
useFuzzy = {
|
||||
apps = true;
|
||||
actions = true;
|
||||
schemes = false;
|
||||
variants = false;
|
||||
wallpapers = false;
|
||||
};
|
||||
|
||||
# Add useful launcher actions
|
||||
actions = [
|
||||
{
|
||||
name = "Calculator";
|
||||
icon = "calculate";
|
||||
description = "Do simple math equations (powered by Qalc)";
|
||||
command = ["autocomplete" "calc"];
|
||||
enabled = true;
|
||||
dangerous = false;
|
||||
}
|
||||
{
|
||||
name = "Scheme";
|
||||
icon = "palette";
|
||||
description = "Change the current colour scheme";
|
||||
command = ["autocomplete" "scheme"];
|
||||
enabled = true;
|
||||
dangerous = false;
|
||||
}
|
||||
{
|
||||
name = "Wallpaper";
|
||||
icon = "image";
|
||||
description = "Change the current wallpaper";
|
||||
command = ["autocomplete" "wallpaper"];
|
||||
enabled = true;
|
||||
dangerous = false;
|
||||
}
|
||||
{
|
||||
name = "Variant";
|
||||
icon = "colors";
|
||||
description = "Change the current scheme variant";
|
||||
command = ["autocomplete" "variant"];
|
||||
enabled = true;
|
||||
dangerous = false;
|
||||
}
|
||||
{
|
||||
name = "Random";
|
||||
icon = "casino";
|
||||
description = "Switch to a random wallpaper";
|
||||
command = ["caelestia" "wallpaper" "-r"];
|
||||
enabled = true;
|
||||
dangerous = false;
|
||||
}
|
||||
{
|
||||
name = "Light";
|
||||
icon = "light_mode";
|
||||
description = "Change the scheme to light mode";
|
||||
command = ["setMode" "light"];
|
||||
enabled = true;
|
||||
dangerous = false;
|
||||
}
|
||||
{
|
||||
name = "Dark";
|
||||
icon = "dark_mode";
|
||||
description = "Change the scheme to dark mode";
|
||||
command = ["setMode" "dark"];
|
||||
enabled = true;
|
||||
dangerous = false;
|
||||
}
|
||||
{
|
||||
name = "Shutdown";
|
||||
icon = "power_settings_new";
|
||||
description = "Shutdown the system";
|
||||
command = ["systemctl" "poweroff"];
|
||||
enabled = true;
|
||||
dangerous = true;
|
||||
}
|
||||
{
|
||||
name = "Reboot";
|
||||
icon = "cached";
|
||||
description = "Reboot the system";
|
||||
command = ["systemctl" "reboot"];
|
||||
enabled = true;
|
||||
dangerous = true;
|
||||
}
|
||||
{
|
||||
name = "Logout";
|
||||
icon = "exit_to_app";
|
||||
description = "Log out of the current session";
|
||||
command = ["loginctl" "terminate-user" ""];
|
||||
enabled = true;
|
||||
dangerous = true;
|
||||
}
|
||||
{
|
||||
name = "Lock";
|
||||
icon = "lock";
|
||||
description = "Lock the current session";
|
||||
command = ["loginctl" "lock-session"];
|
||||
enabled = true;
|
||||
dangerous = false;
|
||||
}
|
||||
{
|
||||
name = "Sleep";
|
||||
icon = "bedtime";
|
||||
description = "Suspend then hibernate";
|
||||
command = ["systemctl" "suspend-then-hibernate"];
|
||||
enabled = true;
|
||||
dangerous = false;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
# ===== NOTIFICATIONS =====
|
||||
notifs = {
|
||||
actionOnClick = false;
|
||||
clearThreshold = 0.3;
|
||||
defaultExpireTimeout = 5000;
|
||||
expandThreshold = 20;
|
||||
expire = false;
|
||||
};
|
||||
|
||||
# ===== OSD (On-Screen Display) =====
|
||||
osd = {
|
||||
enabled = true;
|
||||
enableBrightness = true;
|
||||
enableMicrophone = false;
|
||||
hideDelay = 2000;
|
||||
};
|
||||
|
||||
# ===== PATHS =====
|
||||
paths = {
|
||||
mediaGif = "root:/assets/bongocat.gif";
|
||||
sessionGif = "root:/assets/kurukuru.gif";
|
||||
wallpaperDir = "~/Pictures/Wallpapers";
|
||||
};
|
||||
|
||||
# ===== SERVICES =====
|
||||
services = {
|
||||
audioIncrement = 0.1;
|
||||
defaultPlayer = "Spotify";
|
||||
gpuType = ""; # Auto-detect
|
||||
playerAliases = [
|
||||
{
|
||||
from = "com.github.th-ch.youtube_music";
|
||||
to = "YT Music";
|
||||
}
|
||||
];
|
||||
weatherLocation = ""; # Set your location for weather
|
||||
useFahrenheit = false;
|
||||
useTwelveHourClock = false;
|
||||
smartScheme = true; # Enable dynamic color schemes based on wallpaper
|
||||
visualiserBars = 45;
|
||||
};
|
||||
|
||||
# ===== LOCK SCREEN =====
|
||||
lock = {
|
||||
recolourLogo = true; # Recolor logo to match theme
|
||||
};
|
||||
|
||||
# ===== BORDER =====
|
||||
border = {
|
||||
rounding = 20;
|
||||
thickness = 8;
|
||||
};
|
||||
|
||||
# ===== BACKGROUND =====
|
||||
background = {
|
||||
enabled = true;
|
||||
desktopClock = {
|
||||
enabled = false;
|
||||
};
|
||||
visualiser = {
|
||||
enabled = true;
|
||||
autoHide = true;
|
||||
rounding = 1;
|
||||
spacing = 1;
|
||||
};
|
||||
};
|
||||
|
||||
# ===== SESSION =====
|
||||
session = {
|
||||
dragThreshold = 30;
|
||||
vimKeybinds = false;
|
||||
commands = {
|
||||
logout = ["loginctl" "terminate-user" ""];
|
||||
shutdown = ["systemctl" "poweroff"];
|
||||
hibernate = ["systemctl" "hibernate"];
|
||||
reboot = ["systemctl" "reboot"];
|
||||
};
|
||||
};
|
||||
|
||||
# ===== GENERAL =====
|
||||
general = {
|
||||
apps = {
|
||||
terminal = ["ghostty"]; # Using your terminal preference
|
||||
audio = ["pavucontrol"];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
cli = {
|
||||
enable = true; # Also add caelestia-cli to path
|
||||
settings = {
|
||||
theme.enableGtk = false; # Let Stylix handle GTK theming
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Add launcher keybind for caelestia
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
bind = [
|
||||
# Launch caelestia launcher with just Super key
|
||||
"SUPER,space,global,caelestia:launcher"
|
||||
];
|
||||
};
|
||||
|
||||
# Set the Stylix wallpaper in Caelestia on startup
|
||||
systemd.user.services.caelestia-set-wallpaper = {
|
||||
Unit = {
|
||||
Description = "Set Stylix wallpaper in Caelestia Shell";
|
||||
After = ["caelestia.service"];
|
||||
Wants = ["caelestia.service"];
|
||||
};
|
||||
Service = {
|
||||
Type = "oneshot";
|
||||
ExecStart = let
|
||||
setWallpaperScript = pkgs.writeShellScript "set-caelestia-wallpaper" ''
|
||||
# Wait a moment for Caelestia to be ready
|
||||
sleep 2
|
||||
|
||||
# Check if Stylix wallpaper exists and set it via shell IPC
|
||||
if [ -f "$HOME/Pictures/Wallpapers/stylix-wallpaper" ]; then
|
||||
${inputs.caelestia-shell.packages.${pkgs.system}.with-cli}/bin/caelestia shell wallpaper set "$HOME/Pictures/Wallpapers/stylix-wallpaper" || true
|
||||
fi
|
||||
'';
|
||||
in "${setWallpaperScript}";
|
||||
RemainAfterExit = false;
|
||||
};
|
||||
Install = {
|
||||
WantedBy = ["graphical-session.target"];
|
||||
};
|
||||
};
|
||||
|
||||
# Authentication agent for NetworkManager and other system operations
|
||||
systemd.user.services.polkit-kde-authentication-agent-1 = {
|
||||
Unit = {
|
||||
Description = "polkit-kde-authentication-agent-1";
|
||||
After = ["graphical-session-pre.target"];
|
||||
PartOf = ["graphical-session.target"];
|
||||
};
|
||||
Service = {
|
||||
Type = "simple";
|
||||
ExecStart = "${pkgs.kdePackages.polkit-kde-agent-1}/libexec/polkit-kde-authentication-agent-1";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 1;
|
||||
TimeoutStopSec = 10;
|
||||
};
|
||||
Install = {
|
||||
WantedBy = ["graphical-session.target"];
|
||||
};
|
||||
};
|
||||
|
||||
# GNOME Keyring daemon for secure password storage
|
||||
services.gnome-keyring = {
|
||||
enable = true;
|
||||
components = ["pkcs11" "secrets" "ssh"];
|
||||
};
|
||||
}
|
||||
@@ -1,20 +1,14 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
{pkgs, ...}: {
|
||||
imports = [
|
||||
./caelestia-shell.nix
|
||||
./hyprlock.nix
|
||||
./hypridle.nix
|
||||
./wofi.nix
|
||||
./waybar.nix
|
||||
./keyring.nix
|
||||
];
|
||||
|
||||
# Add essential packages
|
||||
home.packages = with pkgs; [
|
||||
networkmanagerapplet # NetworkManager system tray applet
|
||||
home.packages = [
|
||||
# Essential packages will be provided by caelestia-shell
|
||||
];
|
||||
|
||||
# Configure Hyprland session management
|
||||
@@ -58,8 +52,6 @@
|
||||
exec-once = [
|
||||
# Start polkit authentication agent for secure authentication
|
||||
"${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1"
|
||||
# Start NetworkManager applet for network management
|
||||
"nm-applet --indicator"
|
||||
];
|
||||
|
||||
# Layer rules for proper panel/bar integration
|
||||
@@ -72,7 +64,7 @@
|
||||
# Keybinds
|
||||
bind = [
|
||||
# Launch terminal (kitty)
|
||||
"$mod,RETURN,exec,kitty"
|
||||
"$mod,T,exec,kitty"
|
||||
# Launch browser (zen)
|
||||
"$mod,B,exec,zen"
|
||||
# Close window
|
||||
@@ -80,8 +72,6 @@
|
||||
# Logout
|
||||
"$mod SHIFT,E,exit"
|
||||
|
||||
# Network utility (NetworkManager applet)
|
||||
"$mod,N,exec,nm-applet"
|
||||
# Secrets manager (Seahorse - GNOME keyring GUI)
|
||||
"$mod,K,exec,seahorse"
|
||||
|
||||
@@ -158,13 +148,4 @@
|
||||
SDL_VIDEODRIVER = "wayland";
|
||||
_JAVA_AWT_WM_NONREPARENTING = "1";
|
||||
};
|
||||
|
||||
# Shell aliases for NetworkManager integration
|
||||
home.shellAliases = {
|
||||
# NetworkManager aliases for easier network management
|
||||
nmcli-wifi-list = "nmcli dev wifi list";
|
||||
nmcli-connect = "nmcli dev wifi connect";
|
||||
nmcli-status = "nmcli general status";
|
||||
nmcli-connections = "nmcli connection show";
|
||||
};
|
||||
}
|
||||
|
||||
10
home/panotaka/common/optional/desktops/kde/default.nix
Normal file
10
home/panotaka/common/optional/desktops/kde/default.nix
Normal file
@@ -0,0 +1,10 @@
|
||||
{pkgs, ...}: {
|
||||
home.packages = with pkgs; [
|
||||
kdePackages.kdeconnect-kde
|
||||
kdePackages.konsole
|
||||
kdePackages.dolphin
|
||||
kdePackages.okular
|
||||
kdePackages.gwenview
|
||||
kdePackages.spectacle
|
||||
];
|
||||
}
|
||||
667
home/panotaka/common/optional/desktops/kde/zenbook-screen.nix
Normal file
667
home/panotaka/common/optional/desktops/kde/zenbook-screen.nix
Normal file
@@ -0,0 +1,667 @@
|
||||
{pkgs, ...}: let
|
||||
# Configuration constants for ZenBook Duo
|
||||
duoConfig = {
|
||||
# For 3K model (adjust as needed)
|
||||
prefered_resolution = "2880x1800@120.000";
|
||||
ui_scale = 1.5;
|
||||
y_offset = 1200; # height of resolution / ui_scale (1800/1.5 = 1200)
|
||||
backlight = "card1-eDP-2-backlight";
|
||||
|
||||
# USB ID for ZenBook Duo keyboard dock detection
|
||||
dock_usb_id = "0b05:1b2c";
|
||||
|
||||
# Display device identifiers
|
||||
primary_display = "eDP-1";
|
||||
secondary_display = "eDP-2";
|
||||
|
||||
# Touchscreen/tablet device IDs
|
||||
primary_touch_id = "04f3:425b";
|
||||
secondary_touch_id = "04f3:425a";
|
||||
|
||||
# For 1080p model (uncomment if needed)
|
||||
# prefered_resolution = "1920x1200@60.003";
|
||||
# ui_scale = 1;
|
||||
# y_offset = 1200;
|
||||
};
|
||||
|
||||
# Core display management script adapted for KDE
|
||||
duoScript = pkgs.writeShellScript "duo" ''
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Import configuration
|
||||
PREFERRED_RESOLUTION="${duoConfig.prefered_resolution}"
|
||||
UI_SCALE="${toString duoConfig.ui_scale}"
|
||||
Y_OFFSET="${toString duoConfig.y_offset}"
|
||||
BACKLIGHT="${duoConfig.backlight}"
|
||||
DOCK_USB_ID="${duoConfig.dock_usb_id}"
|
||||
PRIMARY_DISPLAY="${duoConfig.primary_display}"
|
||||
SECONDARY_DISPLAY="${duoConfig.secondary_display}"
|
||||
PRIMARY_TOUCH_ID="${duoConfig.primary_touch_id}"
|
||||
SECONDARY_TOUCH_ID="${duoConfig.secondary_touch_id}"
|
||||
|
||||
# Logging function
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
|
||||
}
|
||||
|
||||
# Error handling
|
||||
handle_error() {
|
||||
log "ERROR: $1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Utility functions
|
||||
suenv() {
|
||||
sudo /usr/bin/env "$@"
|
||||
}
|
||||
|
||||
retry_command() {
|
||||
local retries=$1
|
||||
shift
|
||||
local count=0
|
||||
until "$@"; do
|
||||
count=$((count + 1))
|
||||
if [ $count -ge $retries ]; then
|
||||
return 1
|
||||
fi
|
||||
log "Command failed, retrying ($count/$retries)..."
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
# ===== DETECTION LOGIC =====
|
||||
|
||||
# Check if external displays are connected
|
||||
has_external_displays() {
|
||||
local external_count
|
||||
external_count=$(${pkgs.kdePackages.kscreen}/bin/kscreen-doctor -o | \
|
||||
grep -v "eDP-[12]" | grep "enabled" | wc -l)
|
||||
[ "$external_count" -gt 0 ]
|
||||
}
|
||||
|
||||
# Get list of active external displays
|
||||
get_active_external_displays() {
|
||||
${pkgs.kdePackages.kscreen}/bin/kscreen-doctor -o | \
|
||||
grep -vE 'eDP-[12]' | \
|
||||
grep "enabled" | \
|
||||
cut -d: -f1
|
||||
}
|
||||
|
||||
# Check if dock is connected (determines single vs dual screen mode)
|
||||
is_dock_connected() {
|
||||
${pkgs.usbutils}/bin/lsusb 2>/dev/null | grep -q "$DOCK_USB_ID"
|
||||
}
|
||||
|
||||
# Get current internal display status
|
||||
get_internal_display_status() {
|
||||
local primary_on secondary_on
|
||||
primary_on=$(${pkgs.kdePackages.kscreen}/bin/kscreen-doctor -o | grep "$PRIMARY_DISPLAY" | grep -q "enabled" && echo "1" || echo "0")
|
||||
secondary_on=$(${pkgs.kdePackages.kscreen}/bin/kscreen-doctor -o | grep "$SECONDARY_DISPLAY" | grep -q "enabled" && echo "1" || echo "0")
|
||||
|
||||
case "$primary_on$secondary_on" in
|
||||
"00") echo "none" ;;
|
||||
"10") echo "top" ;;
|
||||
"01") echo "bottom" ;;
|
||||
"11") echo "both" ;;
|
||||
*) echo "unknown" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get device orientation from accelerometer
|
||||
get_orientation() {
|
||||
# This would typically come from iio-sensor-proxy
|
||||
# For now, return normal as default
|
||||
echo "normal"
|
||||
}
|
||||
|
||||
# Determine optimal display configuration based on current state
|
||||
determine_optimal_config() {
|
||||
local has_external dock_connected orientation current_status
|
||||
|
||||
has_external=$(has_external_displays && echo "true" || echo "false")
|
||||
dock_connected=$(is_dock_connected && echo "true" || echo "false")
|
||||
orientation=$(get_orientation)
|
||||
current_status=$(get_internal_display_status)
|
||||
|
||||
log "State: external=$has_external, dock=$dock_connected, orientation=$orientation, current=$current_status"
|
||||
|
||||
# Determine internal display configuration based on orientation and dock status
|
||||
# External displays don't affect internal display arrangement
|
||||
case "$orientation" in
|
||||
"normal")
|
||||
if [ "$dock_connected" = "true" ]; then
|
||||
echo "top-only"
|
||||
else
|
||||
echo "both-stacked"
|
||||
fi
|
||||
;;
|
||||
"left-up")
|
||||
echo "both-left"
|
||||
;;
|
||||
"right-up")
|
||||
echo "both-right"
|
||||
;;
|
||||
"bottom-up")
|
||||
echo "bottom-only"
|
||||
;;
|
||||
*)
|
||||
echo "both-stacked" # Safe default
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ===== MONITOR CONFIGURATION LOGIC =====
|
||||
|
||||
# Apply display configuration with error handling
|
||||
apply_display_config() {
|
||||
local config_name="$1"
|
||||
log "Applying KDE display configuration: $config_name"
|
||||
|
||||
case "$config_name" in
|
||||
"top-only")
|
||||
retry_command 3 ${pkgs.kdePackages.kscreen}/bin/kscreen-doctor \
|
||||
output."$PRIMARY_DISPLAY".enable \
|
||||
output."$SECONDARY_DISPLAY".disable
|
||||
;;
|
||||
"bottom-only")
|
||||
retry_command 3 ${pkgs.kdePackages.kscreen}/bin/kscreen-doctor \
|
||||
output."$SECONDARY_DISPLAY".enable \
|
||||
output."$PRIMARY_DISPLAY".disable
|
||||
;;
|
||||
"both-stacked")
|
||||
retry_command 3 ${pkgs.kdePackages.kscreen}/bin/kscreen-doctor \
|
||||
output."$PRIMARY_DISPLAY".enable \
|
||||
output."$SECONDARY_DISPLAY".enable \
|
||||
output."$PRIMARY_DISPLAY".position.0,0 \
|
||||
output."$SECONDARY_DISPLAY".position.0,"$Y_OFFSET"
|
||||
;;
|
||||
"both-left")
|
||||
retry_command 3 ${pkgs.kdePackages.kscreen}/bin/kscreen-doctor \
|
||||
output."$SECONDARY_DISPLAY".enable \
|
||||
output."$PRIMARY_DISPLAY".enable \
|
||||
output."$SECONDARY_DISPLAY".position.0,0 \
|
||||
output."$SECONDARY_DISPLAY".rotation.left \
|
||||
output."$PRIMARY_DISPLAY".position."$Y_OFFSET",0 \
|
||||
output."$PRIMARY_DISPLAY".rotation.left
|
||||
;;
|
||||
"both-right")
|
||||
retry_command 3 ${pkgs.kdePackages.kscreen}/bin/kscreen-doctor \
|
||||
output."$PRIMARY_DISPLAY".enable \
|
||||
output."$SECONDARY_DISPLAY".enable \
|
||||
output."$PRIMARY_DISPLAY".position.0,0 \
|
||||
output."$PRIMARY_DISPLAY".rotation.right \
|
||||
output."$SECONDARY_DISPLAY".position."$Y_OFFSET",0 \
|
||||
output."$SECONDARY_DISPLAY".rotation.right
|
||||
;;
|
||||
*)
|
||||
handle_error "Unknown display configuration: $config_name"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Update tablet/touchscreen mappings after successful display config
|
||||
update_tablet_mappings "$config_name"
|
||||
}
|
||||
|
||||
# Update tablet and touchscreen mappings based on display config
|
||||
update_tablet_mappings() {
|
||||
local config="$1"
|
||||
log "Updating tablet mappings for configuration: $config"
|
||||
|
||||
# Map touchscreens to displays using xinput (works with both X11 and Wayland)
|
||||
for device in $(${pkgs.xorg.xinput}/bin/xinput list --name-only | grep -i touch || true); do
|
||||
if echo "$device" | grep -q "$PRIMARY_TOUCH_ID"; then
|
||||
${pkgs.xorg.xinput}/bin/xinput map-to-output "$device" "$PRIMARY_DISPLAY" 2>/dev/null || true
|
||||
elif echo "$device" | grep -q "$SECONDARY_TOUCH_ID"; then
|
||||
${pkgs.xorg.xinput}/bin/xinput map-to-output "$device" "$SECONDARY_DISPLAY" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# ===== EVENT HANDLING & WATCHERS =====
|
||||
|
||||
# Handle display change events
|
||||
handle_display_change() {
|
||||
log "Display change detected"
|
||||
sleep 1 # Allow hardware to stabilize
|
||||
|
||||
local optimal_config
|
||||
optimal_config=$(determine_optimal_config)
|
||||
apply_display_config "$optimal_config"
|
||||
}
|
||||
|
||||
# Handle orientation change events
|
||||
handle_orientation_change() {
|
||||
local new_orientation="$1"
|
||||
log "Orientation changed to: $new_orientation"
|
||||
|
||||
# Always reconfigure internal displays when orientation changes
|
||||
# External displays don't affect the need to maintain proper internal layout
|
||||
local optimal_config
|
||||
optimal_config=$(determine_optimal_config)
|
||||
apply_display_config "$optimal_config"
|
||||
}
|
||||
|
||||
# Watch for USB device changes (dock connect/disconnect)
|
||||
watch_usb_changes() {
|
||||
log "Starting USB device watcher"
|
||||
while ${pkgs.inotify-tools}/bin/inotifywait -e attrib /dev/bus/usb/*/ 2>/dev/null; do
|
||||
handle_display_change
|
||||
done
|
||||
}
|
||||
|
||||
# Watch for orientation changes
|
||||
watch_orientation_changes() {
|
||||
log "Starting orientation watcher"
|
||||
${pkgs.iio-sensor-proxy}/bin/monitor-sensor --accel 2>/dev/null | \
|
||||
${pkgs.coreutils}/bin/stdbuf -oL grep "orientation" | \
|
||||
${pkgs.coreutils}/bin/stdbuf -oL cut -d: -f2 | \
|
||||
${pkgs.coreutils}/bin/stdbuf -oL sed 's/[ )]//g' | \
|
||||
while read -r orientation; do
|
||||
handle_orientation_change "$orientation"
|
||||
done
|
||||
}
|
||||
|
||||
# ===== BACKLIGHT MANAGEMENT =====
|
||||
|
||||
# Sync backlight between displays
|
||||
sync_backlight() {
|
||||
if [ -r "/sys/class/backlight/intel_backlight/brightness" ] && [ -w "/sys/class/backlight/$BACKLIGHT/brightness" ]; then
|
||||
cat "/sys/class/backlight/intel_backlight/brightness" | \
|
||||
suenv tee "/sys/class/backlight/$BACKLIGHT/brightness" >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
# Watch backlight changes
|
||||
watch_backlight() {
|
||||
log "Starting backlight watcher"
|
||||
sync_backlight # Initial sync
|
||||
while ${pkgs.inotify-tools}/bin/inotifywait -e modify "/sys/class/backlight/intel_backlight/brightness" 2>/dev/null; do
|
||||
sync_backlight
|
||||
done
|
||||
}
|
||||
|
||||
# ===== MAIN COMMAND INTERFACE =====
|
||||
|
||||
case "''${1:-}" in
|
||||
# Automatic configuration
|
||||
"auto"|"configure")
|
||||
optimal_config=$(determine_optimal_config)
|
||||
apply_display_config "$optimal_config"
|
||||
;;
|
||||
|
||||
# Manual display configurations
|
||||
"top")
|
||||
apply_display_config "top-only"
|
||||
;;
|
||||
"bottom")
|
||||
apply_display_config "bottom-only"
|
||||
;;
|
||||
"both"|"normal")
|
||||
apply_display_config "both-stacked"
|
||||
;;
|
||||
"left-up")
|
||||
apply_display_config "both-left"
|
||||
;;
|
||||
"right-up")
|
||||
apply_display_config "both-right"
|
||||
;;
|
||||
|
||||
# Toggle between configurations
|
||||
"toggle")
|
||||
current_status=$(get_internal_display_status)
|
||||
case "$current_status" in
|
||||
"both") apply_display_config "top-only" ;;
|
||||
"top"|"bottom") apply_display_config "both-stacked" ;;
|
||||
*) apply_display_config "both-stacked" ;;
|
||||
esac
|
||||
;;
|
||||
|
||||
# Status reporting
|
||||
"status")
|
||||
echo "Internal: $(get_internal_display_status)"
|
||||
if has_external_displays; then
|
||||
echo "External: $(get_active_external_displays | tr '\n' '+')"
|
||||
fi
|
||||
echo "Dock: $(is_dock_connected && echo "connected" || echo "disconnected")"
|
||||
;;
|
||||
|
||||
# Event watchers
|
||||
"watch-displays")
|
||||
watch_usb_changes
|
||||
;;
|
||||
"watch-orientation")
|
||||
watch_orientation_changes
|
||||
;;
|
||||
"watch-backlight")
|
||||
watch_backlight
|
||||
;;
|
||||
|
||||
# Utility functions
|
||||
"sync-backlight")
|
||||
sync_backlight
|
||||
;;
|
||||
"set-tablet-mapping")
|
||||
update_tablet_mappings "both-stacked"
|
||||
;;
|
||||
"bat-limit")
|
||||
echo "''${2:-80}" | suenv tee /sys/class/power_supply/BAT0/charge_control_end_threshold
|
||||
;;
|
||||
"set-kb-backlight")
|
||||
suenv ${zenbook-kb-backlight}/bin/zenbook-kb-backlight "''${2:-1}"
|
||||
;;
|
||||
|
||||
# Deprecated aliases for backward compatibility
|
||||
"set-displays")
|
||||
log "DEPRECATED: Use 'auto' instead of 'set-displays'"
|
||||
"$0" auto
|
||||
;;
|
||||
"bottom-up")
|
||||
log "DEPRECATED: Use specific orientation commands"
|
||||
apply_display_config "bottom-only"
|
||||
;;
|
||||
"status-internal")
|
||||
get_internal_display_status
|
||||
;;
|
||||
|
||||
# Help
|
||||
"help"|"-h"|"--help"|"")
|
||||
cat << EOF
|
||||
ZenBook Duo Display Management Tool (KDE)
|
||||
|
||||
USAGE: duo <command> [options]
|
||||
|
||||
AUTOMATIC CONFIGURATION:
|
||||
auto, configure Automatically configure displays based on current state
|
||||
|
||||
MANUAL CONFIGURATION:
|
||||
top Enable only top display
|
||||
bottom Enable only bottom display
|
||||
both, normal Enable both displays in stacked configuration
|
||||
left-up Both displays rotated left
|
||||
right-up Both displays rotated right
|
||||
toggle Toggle between single and dual display modes
|
||||
|
||||
STATUS & MONITORING:
|
||||
status Show current display and device status
|
||||
watch-displays Monitor for display/dock changes
|
||||
watch-orientation Monitor for orientation changes
|
||||
watch-backlight Monitor and sync backlight changes
|
||||
|
||||
UTILITIES:
|
||||
sync-backlight Manually sync backlight between displays
|
||||
set-tablet-mapping Update tablet/touchscreen mappings
|
||||
bat-limit [0-100] Set battery charge limit (default: 80)
|
||||
set-kb-backlight [0-3] Set keyboard backlight level
|
||||
|
||||
help Show this help message
|
||||
EOF
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown command: $1"
|
||||
echo "Use 'duo help' for usage information"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
'';
|
||||
|
||||
# Keyboard backlight control script (same as GNOME version)
|
||||
zenbook-kb-backlight = pkgs.python3Packages.buildPythonApplication {
|
||||
pname = "zenbook-kb-backlight";
|
||||
version = "1.0.0";
|
||||
format = "other";
|
||||
|
||||
src = pkgs.writeText "zenbook-kb-backlight.py" ''
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import usb.core
|
||||
import usb.util
|
||||
import sys
|
||||
import time
|
||||
|
||||
# USB vendor and product IDs for ZenBook Duo 2024
|
||||
VENDOR_ID = 0x0b05 # ASUS
|
||||
PRODUCT_ID = 0x19b6 # ZenBook Duo specific
|
||||
|
||||
def find_keyboard_device():
|
||||
"""Find the ZenBook Duo keyboard device"""
|
||||
devices = usb.core.find(find_all=True, idVendor=VENDOR_ID)
|
||||
for device in devices:
|
||||
if device.idProduct == PRODUCT_ID:
|
||||
return device
|
||||
return None
|
||||
|
||||
def set_backlight(brightness):
|
||||
"""Set keyboard backlight brightness (0-3)"""
|
||||
device = find_keyboard_device()
|
||||
if not device:
|
||||
print("ZenBook Duo keyboard device not found")
|
||||
return False
|
||||
|
||||
try:
|
||||
# Detach kernel driver if it's attached
|
||||
if device.is_kernel_driver_active(0):
|
||||
device.detach_kernel_driver(0)
|
||||
|
||||
# Set configuration
|
||||
device.set_configuration()
|
||||
|
||||
# Send backlight control command
|
||||
device.ctrl_transfer(
|
||||
bmRequestType=0x21, # USB_TYPE_CLASS | USB_RECIP_INTERFACE
|
||||
bRequest=0x09, # HID SET_REPORT
|
||||
wValue=0x0301, # Report type and ID
|
||||
wIndex=0, # Interface
|
||||
data_or_wLength=[0x5d, 0xba, brightness, 0x00, 0x00, 0x00, 0x00, 0x00]
|
||||
)
|
||||
return True
|
||||
|
||||
except usb.core.USBError as e:
|
||||
print(f"USB Error: {e}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: zenbook-kb-backlight <brightness>")
|
||||
print("Brightness levels: 0 (off), 1 (low), 2 (medium), 3 (high)")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
brightness = int(sys.argv[1])
|
||||
if brightness < 0 or brightness > 3:
|
||||
raise ValueError("Brightness must be between 0 and 3")
|
||||
|
||||
if set_backlight(brightness):
|
||||
print(f"Keyboard backlight set to level {brightness}")
|
||||
else:
|
||||
print("Failed to set keyboard backlight")
|
||||
sys.exit(1)
|
||||
|
||||
except ValueError as e:
|
||||
print(f"Invalid brightness value: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
'';
|
||||
|
||||
propagatedBuildInputs = with pkgs.python3Packages; [pyusb];
|
||||
|
||||
dontUnpack = true;
|
||||
dontConfigure = true;
|
||||
dontBuild = true;
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out/bin
|
||||
cp $src $out/bin/zenbook-kb-backlight
|
||||
chmod +x $out/bin/zenbook-kb-backlight
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "ZenBook keyboard backlight control utility";
|
||||
license = pkgs.lib.licenses.mit;
|
||||
};
|
||||
};
|
||||
|
||||
# Combined package with both scripts
|
||||
zenbook-duo-tools = pkgs.stdenv.mkDerivation {
|
||||
pname = "zenbook-duo-tools";
|
||||
version = "1.0.0";
|
||||
|
||||
dontUnpack = true;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp ${duoScript} $out/bin/duo
|
||||
cp ${zenbook-kb-backlight}/bin/zenbook-kb-backlight $out/bin/zenbook-kb-backlight
|
||||
chmod +x $out/bin/*
|
||||
'';
|
||||
};
|
||||
in {
|
||||
# Install the ZenBook Duo tools
|
||||
home.packages = with pkgs; [
|
||||
zenbook-duo-tools
|
||||
kdePackages.kscreen # KDE's display management tool
|
||||
kdePackages.powerdevil # Power management
|
||||
inotify-tools
|
||||
usbutils
|
||||
iio-sensor-proxy
|
||||
xorg.xinput # For touchscreen mapping
|
||||
];
|
||||
|
||||
# Systemd user services for automatic display management
|
||||
systemd.user.services = {
|
||||
zenbook-display-startup = {
|
||||
Unit = {
|
||||
Description = "ZenBook Duo Display Setup on Startup";
|
||||
After = ["graphical-session.target"];
|
||||
PartOf = ["graphical-session.target"];
|
||||
};
|
||||
Service = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${zenbook-duo-tools}/bin/duo auto";
|
||||
RemainAfterExit = true;
|
||||
# Add some delay to ensure graphics are ready
|
||||
ExecStartPre = "${pkgs.coreutils}/bin/sleep 2";
|
||||
};
|
||||
Install.WantedBy = ["graphical-session.target"];
|
||||
};
|
||||
|
||||
zenbook-display-watcher = {
|
||||
Unit = {
|
||||
Description = "ZenBook Duo Display Watcher";
|
||||
After = ["graphical-session.target" "zenbook-display-startup.service"];
|
||||
PartOf = ["graphical-session.target"];
|
||||
Requires = ["zenbook-display-startup.service"];
|
||||
};
|
||||
Service = {
|
||||
Type = "simple";
|
||||
ExecStart = "${zenbook-duo-tools}/bin/duo watch-displays";
|
||||
Restart = "always";
|
||||
RestartSec = "10";
|
||||
# Prevent rapid restarts
|
||||
StartLimitInterval = "60";
|
||||
StartLimitBurst = "3";
|
||||
};
|
||||
Install.WantedBy = ["graphical-session.target"];
|
||||
};
|
||||
|
||||
zenbook-orientation-watcher = {
|
||||
Unit = {
|
||||
Description = "ZenBook Duo Orientation Watcher";
|
||||
After = ["graphical-session.target" "zenbook-display-startup.service"];
|
||||
PartOf = ["graphical-session.target"];
|
||||
Requires = ["zenbook-display-startup.service"];
|
||||
};
|
||||
Service = {
|
||||
Type = "simple";
|
||||
ExecStart = "${zenbook-duo-tools}/bin/duo watch-orientation";
|
||||
Restart = "always";
|
||||
RestartSec = "10";
|
||||
StartLimitInterval = "60";
|
||||
StartLimitBurst = "3";
|
||||
};
|
||||
Install.WantedBy = ["graphical-session.target"];
|
||||
};
|
||||
|
||||
zenbook-backlight-sync = {
|
||||
Unit = {
|
||||
Description = "ZenBook Duo Backlight Sync";
|
||||
After = ["graphical-session.target"];
|
||||
PartOf = ["graphical-session.target"];
|
||||
};
|
||||
Service = {
|
||||
Type = "simple";
|
||||
ExecStart = "${zenbook-duo-tools}/bin/duo watch-backlight";
|
||||
Restart = "always";
|
||||
RestartSec = "5";
|
||||
# This is less critical, allow more restarts
|
||||
StartLimitInterval = "300";
|
||||
StartLimitBurst = "10";
|
||||
};
|
||||
Install.WantedBy = ["graphical-session.target"];
|
||||
};
|
||||
};
|
||||
|
||||
# Shell aliases for convenience (generic across all shells)
|
||||
home.shellAliases = {
|
||||
# Main commands
|
||||
duo = "${zenbook-duo-tools}/bin/duo";
|
||||
duo-auto = "${zenbook-duo-tools}/bin/duo auto";
|
||||
duo-status = "${zenbook-duo-tools}/bin/duo status";
|
||||
duo-help = "${zenbook-duo-tools}/bin/duo help";
|
||||
|
||||
# Display configurations
|
||||
duo-toggle = "${zenbook-duo-tools}/bin/duo toggle";
|
||||
duo-both = "${zenbook-duo-tools}/bin/duo both";
|
||||
duo-top = "${zenbook-duo-tools}/bin/duo top";
|
||||
duo-bottom = "${zenbook-duo-tools}/bin/duo bottom";
|
||||
|
||||
# Utilities
|
||||
duo-sync-backlight = "${zenbook-duo-tools}/bin/duo sync-backlight";
|
||||
zenbook-kb = "${zenbook-duo-tools}/bin/zenbook-kb-backlight";
|
||||
|
||||
# Backward compatibility
|
||||
duo-normal = "${zenbook-duo-tools}/bin/duo both"; # Alias for legacy 'normal' command
|
||||
};
|
||||
|
||||
# KDE-specific configuration via kwriteconfig6
|
||||
home.activation.kdeZenbookConfig = {
|
||||
after = ["writeBoundary"];
|
||||
before = [];
|
||||
data = ''
|
||||
# Configure display scaling for high-DPI Zenbook screens
|
||||
${pkgs.kdePackages.kconfig}/bin/kwriteconfig6 --file kscreenrc --group "Display" --key "ScaleFactor" "${toString duoConfig.ui_scale}"
|
||||
|
||||
# Enable fractional scaling in KWin (Wayland)
|
||||
${pkgs.kdePackages.kconfig}/bin/kwriteconfig6 --file kwinrc --group "Wayland" --key "EnableHiDPI" "true"
|
||||
${pkgs.kdePackages.kconfig}/bin/kwriteconfig6 --file kwinrc --group "Wayland" --key "UseOutputScaling" "true"
|
||||
|
||||
# Enable fractional scaling in KWin (X11)
|
||||
${pkgs.kdePackages.kconfig}/bin/kwriteconfig6 --file kwinrc --group "Xwayland" --key "Scale" "${toString duoConfig.ui_scale}"
|
||||
|
||||
# Enable Variable Refresh Rate (VRR) support
|
||||
${pkgs.kdePackages.kconfig}/bin/kwriteconfig6 --file kwinrc --group "Wayland" --key "AllowVariableRefreshRate" "true"
|
||||
${pkgs.kdePackages.kconfig}/bin/kwriteconfig6 --file kwinrc --group "Compositing" --key "AllowTearing" "true"
|
||||
|
||||
# Configure tablet mode detection
|
||||
${pkgs.kdePackages.kconfig}/bin/kwriteconfig6 --file kwinrc --group "TabletMode" --key "Available" "true"
|
||||
|
||||
# Enable advanced display features
|
||||
${pkgs.kdePackages.kconfig}/bin/kwriteconfig6 --file kwinrc --group "Effect-overview" --key "BorderActivate" "9"
|
||||
|
||||
# Set up custom keyboard shortcut for display configuration
|
||||
${pkgs.kdePackages.kconfig}/bin/kwriteconfig6 --file kglobalshortcutsrc --group "Custom Shortcuts" --key "ZenBook Display Toggle" "Meta+Z,none,${zenbook-duo-tools}/bin/duo auto"
|
||||
|
||||
# Configure KScreen for proper scaling and refresh rates
|
||||
${pkgs.kdePackages.kconfig}/bin/kwriteconfig6 --file kscreenrc --group "General" --key "ScalePolicy" "PerOutputScaling"
|
||||
${pkgs.kdePackages.kconfig}/bin/kwriteconfig6 --file kscreenrc --group "General" --key "EnableVRR" "true"
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
# AGS Bar Configuration for Niri
|
||||
|
||||
This AGS configuration provides a comprehensive status bar for the Niri Wayland compositor with the following features:
|
||||
|
||||
## Features
|
||||
|
||||
### 🕒 Clock Widget
|
||||
- Displays current time and date
|
||||
- Updates every second
|
||||
- Format: `HH:MM Mon DD`
|
||||
|
||||
### 🔊 Volume Control
|
||||
- Shows current volume level and mute status
|
||||
- **Left click**: Toggle mute
|
||||
- Visual feedback with icons:
|
||||
- 🔇 Muted
|
||||
- 🔈 Low volume (0-33%)
|
||||
- 🔉 Medium volume (34-66%)
|
||||
- 🔊 High volume (67-100%)
|
||||
|
||||
### 🔋 Battery Indicator
|
||||
- Shows battery percentage
|
||||
- Charging status indicator
|
||||
- Icons:
|
||||
- 🔌 Charging
|
||||
- 🔋 Battery levels
|
||||
- 🪫 Low battery
|
||||
|
||||
### 🔵 Bluetooth Widget
|
||||
- Shows Bluetooth power status
|
||||
- **Left click**: Toggle Bluetooth on/off
|
||||
- **Right click**: Auto-connect to paired devices
|
||||
- Shows number of connected devices
|
||||
- Icons:
|
||||
- 🔵 Bluetooth enabled
|
||||
- ⚫ Bluetooth disabled
|
||||
- 📱 Connected devices counter
|
||||
|
||||
### 🌐 Network Widget
|
||||
- Shows network connection status
|
||||
- **Left click**: Toggle WiFi / show connection info
|
||||
- Auto-connects to known networks
|
||||
- Icons:
|
||||
- 🌐 Wired connection
|
||||
- 📶 WiFi strength indicator
|
||||
- ❌ No connection
|
||||
- Displays current WiFi SSID when connected
|
||||
|
||||
## Multi-Monitor Support
|
||||
|
||||
The bar automatically appears on all connected monitors using AGS's reactive monitor binding system. When monitors are added or removed, the bar will automatically adjust.
|
||||
|
||||
## Styling
|
||||
|
||||
The bar uses a modern dark theme with:
|
||||
- Semi-transparent background
|
||||
- Catppuccin-inspired color scheme
|
||||
- Hover effects and smooth transitions
|
||||
- Color-coded widget borders:
|
||||
- 🟢 Volume (Green)
|
||||
- 🟡 Battery (Yellow)
|
||||
- 🔵 Bluetooth (Blue)
|
||||
- 🔴 Network (Pink)
|
||||
|
||||
## Files
|
||||
|
||||
- `app.tsx` - Main application entry point
|
||||
- `Bar.tsx` - Bar component with all widgets
|
||||
- `style.css` - Styling and theme
|
||||
- `package.json` - Project configuration
|
||||
- `tsconfig.json` - TypeScript configuration
|
||||
|
||||
## Usage
|
||||
|
||||
The bar starts automatically with Niri via the `spawn-at-startup` configuration in the main Niri config. To manually restart:
|
||||
|
||||
```bash
|
||||
pkill ags && ags run
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
To customize the bar:
|
||||
|
||||
1. **Add new widgets**: Create functions in `Bar.tsx` and add them to the left/center/right sections
|
||||
2. **Modify styling**: Edit `style.css` to change colors, spacing, and animations
|
||||
3. **Change layout**: Modify the `centerbox` structure in the main Bar component
|
||||
4. **Add keybindings**: Use Niri's keybinding system to interact with AGS widgets
|
||||
|
||||
## Dependencies
|
||||
|
||||
All required Astal libraries are automatically provided via the Nix configuration:
|
||||
- `astal.battery` - Battery information
|
||||
- `astal.bluetooth` - Bluetooth control
|
||||
- `astal.network` - Network management
|
||||
- `astal.wireplumber` - Audio control
|
||||
|
||||
## Notes
|
||||
|
||||
- The configuration uses modern AGS v2 syntax with JSX
|
||||
- TypeScript errors in the editor are expected (AGS handles compilation)
|
||||
- Network auto-connection relies on NetworkManager's saved connections
|
||||
- Bluetooth auto-connection attempts to connect to paired devices
|
||||
@@ -1,226 +0,0 @@
|
||||
import { Astal, Gtk, Gdk } from "ags/gtk4"
|
||||
import { bind, Variable } from "ags"
|
||||
import Wp from "gi://AstalWp"
|
||||
import Battery from "gi://AstalBattery"
|
||||
import Bluetooth from "gi://AstalBluetooth"
|
||||
import Network from "gi://AstalNetwork"
|
||||
import App from "ags/gtk4/app"
|
||||
|
||||
type BarProps = {
|
||||
gdkmonitor: Gdk.Monitor
|
||||
}
|
||||
|
||||
function Clock() {
|
||||
const time = Variable("").poll(1000, 'date "+%H:%M %b %e"')
|
||||
|
||||
return (
|
||||
<label
|
||||
className="clock"
|
||||
label={bind(time)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function VolumeWidget() {
|
||||
const speaker = Wp.get_default()?.audio.defaultSpeaker!
|
||||
|
||||
function getVolumeIcon(volume: number, muted: boolean) {
|
||||
if (muted) return "🔇"
|
||||
if (volume > 66) return "🔊"
|
||||
if (volume > 33) return "🔉"
|
||||
if (volume > 0) return "🔈"
|
||||
return "🔇"
|
||||
}
|
||||
|
||||
return (
|
||||
<box className="volume" spacing={8}>
|
||||
<label
|
||||
label={bind(speaker, "volume").as(v =>
|
||||
getVolumeIcon(Math.floor(v * 100), speaker.mute)
|
||||
)}
|
||||
/>
|
||||
<label
|
||||
label={bind(speaker, "volume").as(v => `${Math.floor(v * 100)}%`)}
|
||||
/>
|
||||
<eventbox
|
||||
onButtonPressEvent={(self, event) => {
|
||||
if (event.button === 1) { // Left click
|
||||
speaker.mute = !speaker.mute
|
||||
}
|
||||
}}
|
||||
>
|
||||
<label label="🎵" />
|
||||
</eventbox>
|
||||
</box>
|
||||
)
|
||||
}
|
||||
|
||||
function BatteryWidget() {
|
||||
const bat = Battery.get_default()
|
||||
|
||||
function getBatteryIcon(percentage: number, charging: boolean) {
|
||||
if (charging) return "🔌"
|
||||
if (percentage > 80) return "🔋"
|
||||
if (percentage > 60) return "🔋"
|
||||
if (percentage > 40) return "🔋"
|
||||
if (percentage > 20) return "🪫"
|
||||
return "🪫"
|
||||
}
|
||||
|
||||
return (
|
||||
<box className="battery" spacing={8}>
|
||||
<label
|
||||
label={bind(bat, "percentage").as(p =>
|
||||
getBatteryIcon(p, bat.charging)
|
||||
)}
|
||||
/>
|
||||
<label
|
||||
label={bind(bat, "percentage").as(p => `${Math.floor(p)}%`)}
|
||||
/>
|
||||
</box>
|
||||
)
|
||||
}
|
||||
|
||||
function BluetoothWidget() {
|
||||
const bluetooth = Bluetooth.get_default()
|
||||
|
||||
return (
|
||||
<box className="bluetooth" spacing={8}>
|
||||
<label
|
||||
label={bind(bluetooth, "isPowered").as(powered =>
|
||||
powered ? "🔵" : "⚫"
|
||||
)}
|
||||
/>
|
||||
<eventbox
|
||||
onButtonPressEvent={async (self, event) => {
|
||||
if (event.button === 1) { // Left click to toggle
|
||||
bluetooth.isPowered = !bluetooth.isPowered
|
||||
} else if (event.button === 3) { // Right click to connect to known devices
|
||||
const devices = bluetooth.devices.filter(d => d.paired && !d.connected)
|
||||
if (devices.length > 0) {
|
||||
try {
|
||||
await devices[0].connectDevice()
|
||||
} catch (error) {
|
||||
// Failed to connect to Bluetooth device
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<label
|
||||
label={bind(bluetooth, "devices").as(devices => {
|
||||
const connected = devices.filter(d => d.connected).length
|
||||
return connected > 0 ? `📱${connected}` : "📱"
|
||||
})}
|
||||
/>
|
||||
</eventbox>
|
||||
</box>
|
||||
)
|
||||
}
|
||||
|
||||
function NetworkWidget() {
|
||||
const network = Network.get_default()
|
||||
|
||||
function getNetworkIcon(wifi: any, wired: any) {
|
||||
if (wired?.state === Network.DeviceState.ACTIVATED) {
|
||||
return "🌐"
|
||||
}
|
||||
if (wifi?.state === Network.DeviceState.ACTIVATED) {
|
||||
const strength = wifi.activeAccessPoint?.strength || 0
|
||||
if (strength > 80) return "📶"
|
||||
if (strength > 60) return "📶"
|
||||
if (strength > 40) return "📶"
|
||||
if (strength > 20) return "📶"
|
||||
return "📶"
|
||||
}
|
||||
return "❌"
|
||||
}
|
||||
|
||||
return (
|
||||
<box className="network" spacing={8}>
|
||||
<label
|
||||
label={bind(network, "wifi").as(() =>
|
||||
getNetworkIcon(network.wifi, network.wired)
|
||||
)}
|
||||
/>
|
||||
<eventbox
|
||||
onButtonPressEvent={async (self, event) => {
|
||||
if (event.button === 1 && network.wifi) { // Left click
|
||||
if (network.wifi.state === Network.DeviceState.ACTIVATED) {
|
||||
// Already connected, show current connection
|
||||
const ap = network.wifi.activeAccessPoint
|
||||
if (ap) {
|
||||
// Connected to network
|
||||
}
|
||||
} else {
|
||||
// Try to connect to a known network
|
||||
network.wifi.enabled = true
|
||||
const accessPoints = network.wifi.accessPoints
|
||||
const knownAPs = accessPoints.filter(ap => ap.ssid && ap.ssid.length > 0)
|
||||
|
||||
if (knownAPs.length > 0) {
|
||||
try {
|
||||
// This would typically require network manager secrets
|
||||
// For auto-connection, NetworkManager should handle this
|
||||
await network.wifi.connectToAccessPoint(knownAPs[0])
|
||||
} catch (error) {
|
||||
// Failed to connect to WiFi
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<label
|
||||
label={bind(network, "wifi").as(() => {
|
||||
if (network.wifi?.activeAccessPoint?.ssid) {
|
||||
return network.wifi.activeAccessPoint.ssid
|
||||
}
|
||||
return "WiFi"
|
||||
})}
|
||||
/>
|
||||
</eventbox>
|
||||
</box>
|
||||
)
|
||||
}
|
||||
|
||||
function WorkspaceWidget() {
|
||||
// Simple workspace widget showing current workspace
|
||||
// Note: Niri doesn't have built-in workspace API, so this is a placeholder
|
||||
return (
|
||||
<box className="workspaces" spacing={8}>
|
||||
<label label=" Workspaces" />
|
||||
</box>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Bar({ gdkmonitor }: BarProps) {
|
||||
const { TOP, LEFT, RIGHT } = Astal.WindowAnchor
|
||||
|
||||
return (
|
||||
<window
|
||||
className="bar"
|
||||
gdkmonitor={gdkmonitor}
|
||||
exclusivity={Astal.Exclusivity.EXCLUSIVE}
|
||||
anchor={TOP | LEFT | RIGHT}
|
||||
application={App}
|
||||
>
|
||||
<centerbox className="bar-content">
|
||||
<box className="left" spacing={16} halign={Gtk.Align.START}>
|
||||
<Clock />
|
||||
</box>
|
||||
|
||||
<box className="center" spacing={16} halign={Gtk.Align.CENTER}>
|
||||
<WorkspaceWidget />
|
||||
</box>
|
||||
|
||||
<box className="right" spacing={16} halign={Gtk.Align.END}>
|
||||
<NetworkWidget />
|
||||
<BluetoothWidget />
|
||||
<VolumeWidget />
|
||||
<BatteryWidget />
|
||||
</box>
|
||||
</centerbox>
|
||||
</window>
|
||||
)
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import Gtk from "gi://Gtk"
|
||||
import Bar from "./Bar"
|
||||
import { For, createBinding } from "ags"
|
||||
import app from "ags/gtk4/app"
|
||||
|
||||
function main() {
|
||||
const monitors = createBinding(app, "monitors")
|
||||
|
||||
return (
|
||||
<For each={monitors} cleanup={(win) => (win as Gtk.Window).destroy()}>
|
||||
{(monitor) => <Bar gdkmonitor={monitor} />}
|
||||
</For>
|
||||
)
|
||||
}
|
||||
|
||||
app.start({
|
||||
main,
|
||||
css: "./style.css"
|
||||
})
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "ags-config",
|
||||
"version": "1.0.0",
|
||||
"description": "AGS configuration for niri desktop",
|
||||
"type": "module",
|
||||
"main": "app.tsx",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"ags": "*"
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/* Bar styling for Niri */
|
||||
.bar {
|
||||
background-color: rgba(30, 30, 46, 0.9);
|
||||
color: #cdd6f4;
|
||||
border-bottom: 2px solid #89b4fa;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.bar-content {
|
||||
padding: 8px 16px;
|
||||
}
|
||||
|
||||
.left, .center, .right {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.clock {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
color: #89b4fa;
|
||||
}
|
||||
|
||||
.volume, .battery, .bluetooth, .network, .workspaces {
|
||||
padding: 4px 8px;
|
||||
border-radius: 8px;
|
||||
background-color: rgba(69, 71, 90, 0.8);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.volume:hover, .battery:hover, .bluetooth:hover, .network:hover, .workspaces:hover {
|
||||
background-color: rgba(89, 91, 110, 0.9);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.volume label, .battery label, .bluetooth label, .network label, .workspaces label {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Widget specific colors */
|
||||
.volume {
|
||||
border-left: 3px solid #a6e3a1;
|
||||
}
|
||||
|
||||
.battery {
|
||||
border-left: 3px solid #f9e2af;
|
||||
}
|
||||
|
||||
.bluetooth {
|
||||
border-left: 3px solid #89b4fa;
|
||||
}
|
||||
|
||||
.network {
|
||||
border-left: 3px solid #f38ba8;
|
||||
}
|
||||
|
||||
.workspaces {
|
||||
border-left: 3px solid #cba6f7;
|
||||
}
|
||||
|
||||
/* Responsive design */
|
||||
@media (max-width: 1200px) {
|
||||
.bar-content {
|
||||
padding: 6px 12px;
|
||||
}
|
||||
|
||||
.volume, .battery, .bluetooth, .network, .workspaces {
|
||||
padding: 3px 6px;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ES2022",
|
||||
"lib": ["ES2022"],
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"declaration": false,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"noEmit": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"**/*.js"
|
||||
]
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
{
|
||||
inputs,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
# Add the AGS home manager module
|
||||
imports = [inputs.ags.homeManagerModules.default];
|
||||
|
||||
programs.ags = {
|
||||
enable = true;
|
||||
|
||||
# Symlink to ~/.config/ags
|
||||
configDir = ./config;
|
||||
|
||||
# Additional packages and executables to add to GJS runtime
|
||||
extraPackages = with pkgs; [
|
||||
gtk3
|
||||
glib
|
||||
# Add Astal packages for enhanced functionality
|
||||
astal.astal4
|
||||
astal.io
|
||||
astal.apps
|
||||
astal.battery
|
||||
astal.bluetooth
|
||||
astal.network
|
||||
astal.tray
|
||||
astal.wireplumber
|
||||
];
|
||||
};
|
||||
|
||||
# Note: ags package is provided automatically by programs.ags.enable = true
|
||||
# No need to add it to home.packages separately
|
||||
}
|
||||
@@ -1,12 +1,7 @@
|
||||
{pkgs, ...}: {
|
||||
imports = [
|
||||
# ./waybar.nix # Disabled in favor of AGS
|
||||
./wofi.nix
|
||||
./swaylock.nix
|
||||
./swayidle.nix
|
||||
./keyring.nix
|
||||
./mako.nix
|
||||
./ags
|
||||
./custom-shell.nix # Our custom shell components
|
||||
];
|
||||
|
||||
# Add network utility packages
|
||||
@@ -169,7 +164,7 @@
|
||||
# Window resizing
|
||||
"Mod+R".action.switch-preset-column-width = {};
|
||||
"Mod+Shift+R".action.reset-window-height = {};
|
||||
"Mod+F".action.set-window-width = "100%";
|
||||
"Mod+F".action.maximize-column = {};
|
||||
|
||||
# Screenshots
|
||||
"Print".action.spawn = ["grim"];
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{pkgs, ...}: {
|
||||
# Additional keyring packages for user interaction
|
||||
home.packages = with pkgs; [
|
||||
seahorse # GUI for managing keyrings and passwords
|
||||
kdePackages.kwalletmanager # KDE wallet manager GUI (Qt 6)
|
||||
kdePackages.kwallet # KDE wallet library (Qt 6)
|
||||
libsecret # Secret service API library
|
||||
];
|
||||
|
||||
@@ -9,19 +10,17 @@
|
||||
home.sessionVariables = {
|
||||
# SSH agent socket for SSH key management
|
||||
SSH_AUTH_SOCK = "$XDG_RUNTIME_DIR/keyring/ssh";
|
||||
# Control socket for GNOME Keyring daemon
|
||||
GNOME_KEYRING_CONTROL = "$XDG_RUNTIME_DIR/keyring";
|
||||
# Enable secret service D-Bus API
|
||||
SECRET_SERVICE_API = "1";
|
||||
# Ensure proper D-Bus session bus integration
|
||||
DBUS_SESSION_BUS_ADDRESS = "unix:path=$XDG_RUNTIME_DIR/bus";
|
||||
# Enable password store integration
|
||||
PASSWORD_STORE_ENABLE_EXTENSIONS = "true";
|
||||
# Set keyring backend for applications that support it
|
||||
KEYRING_BACKEND = "gnome-keyring";
|
||||
# Set keyring backend for KDE wallet
|
||||
KEYRING_BACKEND = "kwallet";
|
||||
# Ensure XDG runtime directory is available
|
||||
XDG_RUNTIME_DIR = "/run/user/1000";
|
||||
# Enable keyring unlock via PAM
|
||||
GNOME_KEYRING_UNLOCK_PASSWORD = "1";
|
||||
# KWallet integration
|
||||
KWALLET_ENABLED = "1";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
{pkgs, ...}: {
|
||||
services.mako = {
|
||||
enable = true;
|
||||
settings = {
|
||||
# Basic appearance
|
||||
border-radius = 8;
|
||||
border-size = 2;
|
||||
width = 400;
|
||||
height = 100;
|
||||
padding = "10";
|
||||
margin = "5";
|
||||
default-timeout = 5000;
|
||||
group-by = "app-name";
|
||||
sort = "+time";
|
||||
layer = "overlay";
|
||||
anchor = "top-right";
|
||||
|
||||
# Action configuration
|
||||
actions = true;
|
||||
|
||||
# Icon configuration
|
||||
icon-path = "${pkgs.adwaita-icon-theme}/share/icons/Adwaita";
|
||||
max-icon-size = 48;
|
||||
|
||||
# History configuration
|
||||
max-history = 10;
|
||||
|
||||
# Markup configuration
|
||||
markup = true;
|
||||
format = "<b>%s</b>\\n%b";
|
||||
};
|
||||
};
|
||||
|
||||
home.packages = with pkgs; [
|
||||
mako
|
||||
libnotify # for notify-send command
|
||||
];
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
{pkgs, ...}: {
|
||||
services.swayidle = {
|
||||
enable = true;
|
||||
events = [
|
||||
{
|
||||
event = "before-sleep";
|
||||
command = "${pkgs.swaylock}/bin/swaylock -f";
|
||||
}
|
||||
{
|
||||
event = "lock";
|
||||
command = "${pkgs.swaylock}/bin/swaylock -f";
|
||||
}
|
||||
];
|
||||
timeouts = [
|
||||
{
|
||||
timeout = 150;
|
||||
command = "${pkgs.brightnessctl}/bin/brightnessctl -s set 10";
|
||||
resumeCommand = "${pkgs.brightnessctl}/bin/brightnessctl -r";
|
||||
}
|
||||
{
|
||||
timeout = 300;
|
||||
command = "${pkgs.systemd}/bin/loginctl lock-session";
|
||||
}
|
||||
{
|
||||
timeout = 330;
|
||||
command = "${pkgs.niri}/bin/niri msg action power-off-monitors";
|
||||
resumeCommand = "${pkgs.niri}/bin/niri msg action power-on-monitors";
|
||||
}
|
||||
{
|
||||
timeout = 1800;
|
||||
command = "${pkgs.systemd}/bin/systemctl suspend";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
home.packages = with pkgs; [
|
||||
swayidle
|
||||
];
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{pkgs, ...}: {
|
||||
programs.swaylock = {
|
||||
enable = true;
|
||||
settings = {
|
||||
font-size = 24;
|
||||
indicator-idle-visible = false;
|
||||
indicator-radius = 100;
|
||||
show-failed-attempts = true;
|
||||
};
|
||||
};
|
||||
|
||||
home.packages = with pkgs; [
|
||||
swaylock
|
||||
];
|
||||
}
|
||||
@@ -1,282 +0,0 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
# Configure Stylix to target Waybar
|
||||
stylix.targets.waybar.enable = true;
|
||||
|
||||
programs.waybar = {
|
||||
enable = true;
|
||||
settings = {
|
||||
mainBar = {
|
||||
layer = "top";
|
||||
position = "top";
|
||||
height = 30;
|
||||
|
||||
modules-left = ["niri/workspaces" "niri/mode" "niri/window"];
|
||||
modules-center = ["clock"];
|
||||
modules-right = ["network" "bluetooth" "pulseaudio" "battery" "tray" "custom/notification"];
|
||||
|
||||
"niri/workspaces" = {
|
||||
disable-scroll = true;
|
||||
all-outputs = true;
|
||||
format = "{icon}";
|
||||
format-icons = {
|
||||
"1" = "1";
|
||||
"2" = "2";
|
||||
"3" = "3";
|
||||
"4" = "4";
|
||||
"5" = "5";
|
||||
"6" = "6";
|
||||
"7" = "7";
|
||||
"8" = "8";
|
||||
"9" = "9";
|
||||
"10" = "10";
|
||||
};
|
||||
};
|
||||
|
||||
"niri/mode" = {
|
||||
format = "<span style=\"italic\">{}</span>";
|
||||
};
|
||||
|
||||
"niri/window" = {
|
||||
format = "{}";
|
||||
max-length = 50;
|
||||
separate-outputs = true;
|
||||
};
|
||||
|
||||
"clock" = {
|
||||
tooltip-format = "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>";
|
||||
format-alt = "{:%Y-%m-%d}";
|
||||
format = "{:%H:%M}";
|
||||
};
|
||||
|
||||
"network" = {
|
||||
format-wifi = " {essid} ({signalStrength}%)";
|
||||
format-ethernet = " {ipaddr}/{cidr}";
|
||||
tooltip-format = " {ifname} via {gwaddr}";
|
||||
format-linked = " {ifname} (No IP)";
|
||||
format-disconnected = "⚠ Disconnected";
|
||||
format-alt = "{ifname}: {ipaddr}/{cidr}";
|
||||
};
|
||||
|
||||
"bluetooth" = {
|
||||
format = " {status}";
|
||||
format-disabled = "";
|
||||
format-connected = " {device_alias}";
|
||||
format-connected-battery = " {device_alias} {device_battery_percentage}%";
|
||||
tooltip-format = "{controller_alias}\t{controller_address}\n\n{num_connections} connected";
|
||||
tooltip-format-connected = "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}";
|
||||
tooltip-format-enumerate-connected = "{device_alias}\t{device_address}";
|
||||
tooltip-format-enumerate-connected-battery = "{device_alias}\t{device_address}\t{device_battery_percentage}%";
|
||||
};
|
||||
|
||||
"pulseaudio" = {
|
||||
scroll-step = 5;
|
||||
format = "{icon} {volume}%";
|
||||
format-bluetooth = "{icon} {volume}% ";
|
||||
format-bluetooth-muted = " {icon}";
|
||||
format-muted = " {format_source}";
|
||||
format-source = "{volume}% ";
|
||||
format-source-muted = "";
|
||||
format-icons = {
|
||||
headphone = "";
|
||||
hands-free = "";
|
||||
headset = "";
|
||||
phone = "";
|
||||
portable = "";
|
||||
car = "";
|
||||
default = ["" "" ""];
|
||||
};
|
||||
on-click = "pavucontrol";
|
||||
};
|
||||
|
||||
"battery" = {
|
||||
states = {
|
||||
good = 95;
|
||||
warning = 30;
|
||||
critical = 15;
|
||||
};
|
||||
format = "{icon} {capacity}%";
|
||||
format-charging = " {capacity}%";
|
||||
format-plugged = " {capacity}%";
|
||||
format-alt = "{icon} {time}";
|
||||
format-icons = ["" "" "" "" ""];
|
||||
};
|
||||
|
||||
"tray" = {
|
||||
icon-size = 21;
|
||||
spacing = 10;
|
||||
};
|
||||
|
||||
"custom/notification" = {
|
||||
tooltip = false;
|
||||
format = "{icon}";
|
||||
format-icons = {
|
||||
notification = "<span foreground='red'><sup></sup></span>";
|
||||
none = "";
|
||||
dnd-notification = "<span foreground='red'><sup></sup></span>";
|
||||
dnd-none = "";
|
||||
inhibited-notification = "<span foreground='red'><sup></sup></span>";
|
||||
inhibited-none = "";
|
||||
dnd-inhibited-notification = "<span foreground='red'><sup></sup></span>";
|
||||
dnd-inhibited-none = "";
|
||||
};
|
||||
return-type = "json";
|
||||
exec-if = "which swaync-client";
|
||||
exec = "swaync-client -swb";
|
||||
on-click = "swaync-client -t -sw";
|
||||
on-click-right = "swaync-client -d -sw";
|
||||
escape = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Define the stylesheet using Adwaita-inspired design with Stylix variables
|
||||
style = ''
|
||||
* {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
min-height: 0;
|
||||
font-family: "Cantarell", sans-serif;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
window#waybar {
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.1) 0%, rgba(0,0,0,0.1) 100%);
|
||||
background-color: #${config.lib.stylix.colors.base00};
|
||||
color: #${config.lib.stylix.colors.base05};
|
||||
border-bottom: 1px solid rgba(0,0,0,0.1);
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
transition-property: background-color;
|
||||
transition-duration: 200ms;
|
||||
}
|
||||
|
||||
#workspaces {
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
#workspaces button {
|
||||
padding: 4px 12px;
|
||||
margin: 6px 2px;
|
||||
color: #${config.lib.stylix.colors.base04};
|
||||
background-color: transparent;
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
transition: all 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
min-width: 24px;
|
||||
}
|
||||
|
||||
#workspaces button.active,
|
||||
#workspaces button.focused {
|
||||
background: linear-gradient(135deg, #${config.lib.stylix.colors.base0D} 0%, #${config.lib.stylix.colors.base0E} 100%);
|
||||
color: #${config.lib.stylix.colors.base00};
|
||||
border: 1px solid #${config.lib.stylix.colors.base0D};
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.2);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
#workspaces button:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
border: 1px solid rgba(255,255,255,0.2);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
#clock,
|
||||
#network,
|
||||
#bluetooth,
|
||||
#pulseaudio,
|
||||
#battery,
|
||||
#tray,
|
||||
#custom-notification {
|
||||
padding: 6px 12px;
|
||||
margin: 6px 2px;
|
||||
background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%);
|
||||
background-color: #${config.lib.stylix.colors.base01};
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1), inset 0 1px 0 rgba(255,255,255,0.1);
|
||||
transition: all 200ms ease;
|
||||
}
|
||||
|
||||
#clock:hover,
|
||||
#network:hover,
|
||||
#bluetooth:hover,
|
||||
#pulseaudio:hover,
|
||||
#battery:hover,
|
||||
#tray:hover,
|
||||
#custom-notification:hover {
|
||||
background-color: #${config.lib.stylix.colors.base02};
|
||||
border: 1px solid rgba(255,255,255,0.2);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.15), inset 0 1px 0 rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
#mode {
|
||||
background: linear-gradient(135deg, #${config.lib.stylix.colors.base08} 0%, #${config.lib.stylix.colors.base09} 100%);
|
||||
color: #${config.lib.stylix.colors.base00};
|
||||
padding: 6px 12px;
|
||||
margin: 6px 2px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #${config.lib.stylix.colors.base08};
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.3);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#window {
|
||||
color: #${config.lib.stylix.colors.base05};
|
||||
padding: 6px 12px;
|
||||
margin: 6px 4px;
|
||||
font-weight: 400;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
#battery.warning {
|
||||
color: #${config.lib.stylix.colors.base09};
|
||||
background: linear-gradient(135deg, rgba(255,193,7,0.1) 0%, rgba(255,193,7,0.05) 100%);
|
||||
border: 1px solid rgba(255,193,7,0.3);
|
||||
}
|
||||
|
||||
#battery.critical {
|
||||
color: #${config.lib.stylix.colors.base08};
|
||||
background: linear-gradient(135deg, rgba(220,53,69,0.1) 0%, rgba(220,53,69,0.05) 100%);
|
||||
border: 1px solid rgba(220,53,69,0.3);
|
||||
animation: blink 1s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
to {
|
||||
background-color: rgba(220,53,69,0.2);
|
||||
}
|
||||
}
|
||||
|
||||
#network.disconnected {
|
||||
color: #${config.lib.stylix.colors.base08};
|
||||
background: linear-gradient(135deg, rgba(220,53,69,0.1) 0%, rgba(220,53,69,0.05) 100%);
|
||||
border: 1px solid rgba(220,53,69,0.3);
|
||||
}
|
||||
|
||||
#pulseaudio.muted {
|
||||
color: #${config.lib.stylix.colors.base03};
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
#tray > .passive {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
#tray > .needs-attention {
|
||||
background-color: #${config.lib.stylix.colors.base08};
|
||||
border: 1px solid #${config.lib.stylix.colors.base08};
|
||||
animation: blink 1s ease-in-out infinite alternate;
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
home.packages = with pkgs; [
|
||||
waybar
|
||||
];
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
{pkgs, ...}: {
|
||||
programs.wofi = {
|
||||
enable = true;
|
||||
settings = {
|
||||
width = 600;
|
||||
height = 400;
|
||||
location = "center";
|
||||
show = "drun";
|
||||
prompt = "Search...";
|
||||
filter_rate = 100;
|
||||
allow_markup = true;
|
||||
no_actions = true;
|
||||
halign = "fill";
|
||||
orientation = "vertical";
|
||||
content_halign = "fill";
|
||||
insensitive = true;
|
||||
allow_images = true;
|
||||
image_size = 40;
|
||||
gtk_dark = true;
|
||||
dynamic_lines = false;
|
||||
matching = "contains";
|
||||
hide_scroll = true;
|
||||
print_command = true;
|
||||
layer = "overlay";
|
||||
sort_order = "default";
|
||||
term = "kitty";
|
||||
exec_search = false;
|
||||
};
|
||||
};
|
||||
|
||||
# Keybind: Mod+Return launches wofi only if not already running
|
||||
programs.niri.settings.binds."Mod+Return".action.spawn = ["sh" "-c" "pgrep -x wofi || wofi --show drun"];
|
||||
|
||||
home.packages = with pkgs; [
|
||||
wofi
|
||||
];
|
||||
}
|
||||
@@ -1,7 +1,14 @@
|
||||
{pkgs, ...}: {
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
services.desktopManager.plasma6.enable = true;
|
||||
environment.sessionVariables.GTK_USE_PORTAL = "1";
|
||||
environment.sessionVariables.NIXOS_OZONE_WL = "1";
|
||||
environment.sessionVariables.KWIN_DRM_PREFER_COLOR_DEPTH = "24";
|
||||
environment.systemPackages = with pkgs.kdePackages; [plasma-thunderbolt sddm-kcm];
|
||||
|
||||
# Fix Qt platform theme configuration for KDE - force override stylix
|
||||
qt.platformTheme = lib.mkForce "kde";
|
||||
}
|
||||
|
||||
90
hosts/common/optional/lxqt-greeter.nix
Normal file
90
hosts/common/optional/lxqt-greeter.nix
Normal file
@@ -0,0 +1,90 @@
|
||||
# LXQt Default Greeter (SDDM with LXQt theme)
|
||||
#
|
||||
# This module configures SDDM as the display manager with LXQt theming
|
||||
# to provide a consistent greeter experience for LXQt desktop environments.
|
||||
#
|
||||
# Features:
|
||||
# - SDDM display manager with Wayland support
|
||||
# - LXQt theme integration for the greeter
|
||||
# - Proper session detection for LXQt-based environments
|
||||
# - Qt theming consistency between greeter and desktop
|
||||
#
|
||||
# Usage:
|
||||
# Add this to your host configuration instead of gdm.nix:
|
||||
# imports = lib.flatten [
|
||||
# # ... other imports ...
|
||||
# "hosts/common/optional/lxqt-greeter.nix"
|
||||
# ];
|
||||
#
|
||||
{pkgs, ...}: {
|
||||
# Enable SDDM as the display manager
|
||||
services.displayManager = {
|
||||
sddm = {
|
||||
enable = true;
|
||||
wayland = {
|
||||
enable = true;
|
||||
compositor = "kwin"; # Use KWin for the greeter compositor
|
||||
};
|
||||
# Use LXQt theme for SDDM
|
||||
theme = "breeze"; # Breeze theme works well with LXQt
|
||||
};
|
||||
};
|
||||
|
||||
# Install SDDM themes and LXQt integration packages
|
||||
environment.systemPackages = with pkgs; [
|
||||
# SDDM themes that work well with LXQt
|
||||
kdePackages.sddm-kcm # SDDM configuration module
|
||||
|
||||
# Additional SDDM themes (optional)
|
||||
where-is-my-sddm-theme
|
||||
];
|
||||
|
||||
# Ensure proper font rendering for the greeter
|
||||
fonts = {
|
||||
packages = with pkgs; [
|
||||
noto-fonts
|
||||
noto-fonts-cjk-sans
|
||||
noto-fonts-emoji
|
||||
liberation_ttf
|
||||
fira-code
|
||||
fira-code-symbols
|
||||
];
|
||||
|
||||
fontconfig = {
|
||||
defaultFonts = {
|
||||
serif = ["Noto Serif"];
|
||||
sansSerif = ["Noto Sans"];
|
||||
monospace = ["Fira Code"];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# SDDM configuration
|
||||
environment.etc."sddm.conf".text = ''
|
||||
[Autologin]
|
||||
Relogin=false
|
||||
Session=
|
||||
User=
|
||||
|
||||
[General]
|
||||
HaltCommand=/run/current-system/systemd/bin/systemctl poweroff
|
||||
RebootCommand=/run/current-system/systemd/bin/systemctl reboot
|
||||
|
||||
[Theme]
|
||||
Current=breeze
|
||||
CursorTheme=breeze_cursors
|
||||
Font=Noto Sans,10,-1,0,50,0,0,0,0,0
|
||||
|
||||
[Users]
|
||||
MaximumUid=60513
|
||||
MinimumUid=1000
|
||||
|
||||
[Wayland]
|
||||
EnableHiDPI=true
|
||||
SessionDir=/run/current-system/sw/share/wayland-sessions
|
||||
|
||||
[X11]
|
||||
EnableHiDPI=true
|
||||
SessionDir=/run/current-system/sw/share/xsessions
|
||||
'';
|
||||
}
|
||||
162
hosts/common/optional/lxqt-niri.nix
Normal file
162
hosts/common/optional/lxqt-niri.nix
Normal file
@@ -0,0 +1,162 @@
|
||||
# LXQt Desktop Environment with Niri Window Manager
|
||||
#
|
||||
# This module provides LXQt desktop environment components running with
|
||||
# Niri as the Wayland compositor instead of the default window manager.
|
||||
#
|
||||
# Features:
|
||||
# - LXQt panel, settings, file manager, and utilities
|
||||
# - Niri as the tiling Wayland compositor
|
||||
# - Proper Qt theming with LXQt themes and Kvantum
|
||||
# - XDG portals for screen sharing and file dialogs
|
||||
# - Audio, network, and power management integration
|
||||
#
|
||||
# Usage:
|
||||
# Add this to your host configuration:
|
||||
# imports = lib.flatten [
|
||||
# # ... other imports ...
|
||||
# "hosts/common/optional/lxqt-niri.nix"
|
||||
# "hosts/common/optional/gdm.nix" # or sddm.nix for display manager
|
||||
# ];
|
||||
#
|
||||
# The session will appear as "LXQt (Niri)" in the session list.
|
||||
#
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
inputs.niri.nixosModules.niri
|
||||
];
|
||||
|
||||
# Enable Niri as the window manager
|
||||
programs.niri.enable = true;
|
||||
|
||||
# Enable LXQt desktop environment components
|
||||
# Note: We don't enable services.xserver.desktopManager.lxqt.enable = true
|
||||
# because it would conflict with our custom display manager configuration
|
||||
services.xserver = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
# Install additional LXQt components and utilities
|
||||
environment.systemPackages = with pkgs; [
|
||||
# Core LXQt components that work well with other window managers
|
||||
lxqt.lxqt-panel
|
||||
lxqt.lxqt-session
|
||||
lxqt.lxqt-config
|
||||
lxqt.lxqt-themes
|
||||
lxqt.lxqt-notificationd
|
||||
lxqt.lxqt-powermanagement
|
||||
lxqt.lxqt-policykit
|
||||
lxqt.lxqt-archiver
|
||||
lxqt.qterminal
|
||||
lxqt.pcmanfm-qt
|
||||
lxqt.lximage-qt
|
||||
lxqt.qps
|
||||
|
||||
# Theme engines and styling
|
||||
libsForQt5.qtstyleplugins
|
||||
libsForQt5.qt5ct
|
||||
|
||||
# System tools that integrate well with LXQt
|
||||
lxqt.pavucontrol-qt
|
||||
qpwgraph
|
||||
|
||||
# Network management
|
||||
libsForQt5.networkmanager-qt
|
||||
|
||||
# Custom session script
|
||||
(writeScriptBin "niri-session" ''
|
||||
#!/bin/sh
|
||||
|
||||
# Set up environment
|
||||
export XDG_CURRENT_DESKTOP=LXQt
|
||||
export XDG_SESSION_DESKTOP=lxqt-niri
|
||||
export DESKTOP_SESSION=lxqt-niri
|
||||
|
||||
# Start LXQt session components in background
|
||||
${lxqt.lxqt-session}/bin/lxqt-session &
|
||||
|
||||
# Start Niri as the main session
|
||||
exec ${niri}/bin/niri
|
||||
'')
|
||||
];
|
||||
|
||||
# Configure XDG portals for better integration
|
||||
xdg.portal = {
|
||||
enable = true;
|
||||
extraPortals = with pkgs; [
|
||||
xdg-desktop-portal-gtk
|
||||
xdg-desktop-portal-wlr
|
||||
];
|
||||
config = {
|
||||
common = {
|
||||
default = ["gtk"];
|
||||
"org.freedesktop.impl.portal.Screenshot" = ["wlr"];
|
||||
"org.freedesktop.impl.portal.Screencast" = ["wlr"];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Use LXQt's polkit agent
|
||||
security.polkit.enable = true;
|
||||
systemd.user.services.lxqt-policykit-agent = {
|
||||
description = "LXQt PolicyKit Agent";
|
||||
wantedBy = ["graphical-session.target"];
|
||||
wants = ["graphical-session.target"];
|
||||
after = ["graphical-session.target"];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${pkgs.lxqt.lxqt-policykit}/bin/lxqt-policykit-agent";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 1;
|
||||
TimeoutStopSec = 10;
|
||||
};
|
||||
};
|
||||
|
||||
# Configure Qt theming (basic settings)
|
||||
# Note: More specific Qt theming may be handled by system-wide theming modules
|
||||
|
||||
# Configure Qt theming to use LXQt
|
||||
qt = {
|
||||
platformTheme = lib.mkForce "lxqt";
|
||||
};
|
||||
|
||||
# Environment variables for proper integration
|
||||
environment.sessionVariables = {
|
||||
NIXOS_OZONE_WL = "1";
|
||||
QT_QPA_PLATFORM = "wayland;xcb";
|
||||
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
|
||||
QT_AUTO_SCREEN_SCALE_FACTOR = "1";
|
||||
QT_QPA_PLATFORMTHEME = lib.mkForce "lxqt";
|
||||
QT_STYLE_OVERRIDE = "kvantum";
|
||||
DESKTOP_SESSION = "lxqt-niri";
|
||||
XDG_CURRENT_DESKTOP = "LXQt";
|
||||
XDG_SESSION_DESKTOP = "lxqt-niri";
|
||||
};
|
||||
|
||||
# Enable necessary services for LXQt functionality
|
||||
services = {
|
||||
# Power management
|
||||
upower.enable = true;
|
||||
};
|
||||
|
||||
# Create a custom session file for LXQt + Niri
|
||||
environment.etc."xdg/lxqt/session.conf".text = ''
|
||||
[General]
|
||||
__userfile__=true
|
||||
window_manager=niri
|
||||
'';
|
||||
|
||||
# Create desktop entry for the session
|
||||
environment.etc."wayland-sessions/lxqt-niri.desktop".text = ''
|
||||
[Desktop Entry]
|
||||
Name=LXQt (Niri)
|
||||
Comment=LXQt Desktop with Niri Window Manager
|
||||
Exec=niri-session
|
||||
Type=Application
|
||||
Keywords=niri;lxqt;wayland;
|
||||
'';
|
||||
}
|
||||
@@ -9,12 +9,31 @@
|
||||
|
||||
programs.niri.enable = true;
|
||||
|
||||
# XDG Desktop Portal for niri
|
||||
# Use KDE portal instead of GNOME for better KDE integration
|
||||
xdg.portal = {
|
||||
enable = true;
|
||||
extraPortals = with pkgs; [
|
||||
xdg-desktop-portal-gnome
|
||||
kdePackages.xdg-desktop-portal-kde
|
||||
];
|
||||
config.common.default = "kde";
|
||||
};
|
||||
|
||||
# Use KDE polkit for authentication instead of GNOME
|
||||
security.polkit.enable = true;
|
||||
systemd = {
|
||||
user.services.polkit-kde-authentication-agent-1 = {
|
||||
description = "polkit-kde-authentication-agent-1";
|
||||
wantedBy = ["graphical-session.target"];
|
||||
wants = ["graphical-session.target"];
|
||||
after = ["graphical-session.target"];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${pkgs.kdePackages.polkit-kde-agent-1}/libexec/polkit-kde-authentication-agent-1";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 1;
|
||||
TimeoutStopSec = 10;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
environment.sessionVariables.NIXOS_OZONE_WL = "1";
|
||||
|
||||
17
hosts/common/optional/services/printing.nix
Normal file
17
hosts/common/optional/services/printing.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
# Enable printing support
|
||||
{pkgs, ...}: {
|
||||
# Autodiscovery of network printers
|
||||
services.avahi = {
|
||||
enable = true;
|
||||
nssmdns4 = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
services.printing = {
|
||||
enable = true;
|
||||
drivers = with pkgs; [
|
||||
cups-filters
|
||||
cups-browsed
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
home-manager.sharedModules = [
|
||||
{
|
||||
stylix.autoEnable = true;
|
||||
stylix.targets.vscode.enable = false;
|
||||
stylix.targets.vscode.enable = true;
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@@ -26,20 +26,22 @@ in {
|
||||
};
|
||||
|
||||
sansSerif = {
|
||||
package = pkgs.noto-fonts;
|
||||
name = "Noto Sans";
|
||||
package = pkgs.inter;
|
||||
name = "Inter";
|
||||
};
|
||||
|
||||
monospace = {
|
||||
package = pkgs.nerd-fonts.fira-code;
|
||||
name = "Fira Code Nerd Font";
|
||||
package = pkgs.nerd-fonts.jetbrains-mono;
|
||||
name = "JetBrainsMono Nerd Font Mono";
|
||||
};
|
||||
|
||||
emoji = {
|
||||
package = pkgs.noto-fonts-emoji;
|
||||
name = "Noto Color Emoji";
|
||||
};
|
||||
|
||||
sizes = {
|
||||
applications = 10;
|
||||
applications = 10; # whole-number size
|
||||
desktop = 10;
|
||||
popups = 10;
|
||||
terminal = 10;
|
||||
@@ -49,12 +51,12 @@ in {
|
||||
home-manager.sharedModules = [
|
||||
{
|
||||
programs.vscode = {
|
||||
extensions = pkgs.nix4vscode.forVscode [
|
||||
extensions = pkgs.nix4vscode.forVscodeVersion pkgs.vscode.version [
|
||||
"huytd.tokyo-city"
|
||||
"vscode-icons-team.vscode-icons"
|
||||
];
|
||||
userSettings = {
|
||||
"workbench.colorTheme" = "Tokyo City Darker";
|
||||
#"workbench.colorTheme" = "Tokyo City Darker";
|
||||
"workbench.iconTheme" = "vscode-icons";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -20,13 +20,14 @@
|
||||
|
||||
# This is your main performance tuning knob. 'performance' tells the CPU
|
||||
# to aggressively ramp up to high clock speeds when it detects a load.
|
||||
# 'balance_power' is a good choice for extending battery life.
|
||||
CPU_ENERGY_PERF_POLICY_ON_AC = "performance";
|
||||
# 'balance_performance' provides good performance while being more thermal-aware.
|
||||
CPU_ENERGY_PERF_POLICY_ON_AC = "balance_performance";
|
||||
CPU_ENERGY_PERF_POLICY_ON_BAT = "balance_power";
|
||||
|
||||
# Allow the CPU to use its full performance range when plugged in.
|
||||
# Allow the CPU to use its performance range when plugged in, but cap it
|
||||
# slightly to reduce heat generation while maintaining good responsiveness.
|
||||
CPU_MIN_PERF_ON_AC = 0;
|
||||
CPU_MAX_PERF_ON_AC = 100;
|
||||
CPU_MAX_PERF_ON_AC = 85; # Reduced from 100% to help with thermal management
|
||||
CPU_MIN_PERF_ON_BAT = 0;
|
||||
CPU_MAX_PERF_ON_BAT = 60; # Slightly higher than before for better battery responsiveness.
|
||||
|
||||
@@ -42,9 +43,9 @@
|
||||
|
||||
# --- Intel Arc GPU & System Settings ---
|
||||
|
||||
# Set the platform profile. 'balanced' is a much safer bet than 'performance'
|
||||
# to avoid overwhelming the chassis's cooling solution.
|
||||
PLATFORM_PROFILE_ON_AC = "balanced";
|
||||
# Set the platform profile. 'low-power' is more conservative than 'balanced'
|
||||
# to help with thermal management while still providing reasonable performance.
|
||||
PLATFORM_PROFILE_ON_AC = "low-power";
|
||||
PLATFORM_PROFILE_ON_BAT = "low-power";
|
||||
|
||||
# Use 'powersupersave' for PCIe ASPM. This allows the components,
|
||||
|
||||
@@ -69,10 +69,10 @@
|
||||
# The following are for example sake only and are not necessarily required.
|
||||
#"hosts/common/optional/services/openssh.nix" # allow remote SSH access
|
||||
"hosts/common/optional/services/bluetooth.nix"
|
||||
"hosts/common/optional/services/printing.nix"
|
||||
"hosts/common/optional/thunderbolt.nix"
|
||||
"hosts/common/optional/services/ollama.nix"
|
||||
"hosts/common/optional/services/docker.nix"
|
||||
"hosts/common/optional/services/tailscale.nix"
|
||||
"hosts/common/optional/audio.nix" # pipewire and cli controls
|
||||
"hosts/common/optional/gnome.nix"
|
||||
"hosts/common/optional/gdm.nix"
|
||||
|
||||
@@ -7,10 +7,19 @@
|
||||
...
|
||||
}: let
|
||||
# Adds my custom packages
|
||||
additions = final: prev: (prev.lib.packagesFromDirectoryRecursive {
|
||||
additions = final: prev:
|
||||
(prev.lib.packagesFromDirectoryRecursive {
|
||||
callPackage = prev.lib.callPackageWith final;
|
||||
directory = ../pkgs/common;
|
||||
});
|
||||
})
|
||||
// {
|
||||
# Custom GNOME extensions
|
||||
gnomeExtensions =
|
||||
prev.gnomeExtensions
|
||||
// {
|
||||
monitor-workspace-manager = final.monitor-workspace-manager;
|
||||
};
|
||||
};
|
||||
|
||||
linuxModifications = final: prev: prev.lib.mkIf final.stdenv.isLinux {};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user