Compare commits
6 Commits
82a84e00cc
...
3b2ccc8417
| Author | SHA1 | Date | |
|---|---|---|---|
| 3b2ccc8417 | |||
| d9966d8f38 | |||
| eb58a62168 | |||
| c74f623232 | |||
| 8224513e07 | |||
| 87a2314170 |
65
.github/copilot-instructions.md
vendored
65
.github/copilot-instructions.md
vendored
@@ -1,43 +1,48 @@
|
|||||||
# Copilot Instructions for EmergentMind's Nix-Config
|
# Copilot Instructions for EmergentMind's Nix-Config
|
||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
- This is a modular, flake-based NixOS configuration system, designed for multi-host, multi-user, and reproducible setups.
|
- This is a modular, flake-based NixOS configuration system for managing multiple hosts, users, and environments (NixOS, Darwin, Home Manager).
|
||||||
- Major directories:
|
- The repo is structured for maximum composability: core logic is split into `hosts/`, `home/`, `modules/`, and `overlays/` with heavy use of imports and attribute sets.
|
||||||
- `hosts/`: Per-host NixOS configs (e.g., `hosts/nixos/Bellerophon/`).
|
- Secrets are managed via a private `nix-secrets` repo and sops-nix, integrated as a flake input (see docs/secretsmgmt.md).
|
||||||
- `home/`: Per-user Home Manager configs.
|
|
||||||
- `modules/`: Reusable NixOS and Home Manager modules, auto-imported via `lib.custom.scanPaths`.
|
|
||||||
- `overlays/`, `pkgs/`: Custom packages and overlays.
|
|
||||||
- `nixos-installer/`: Standalone flake for bootstrapping new hosts, with its own README and workflows.
|
|
||||||
- `docs/`: Project documentation, including secrets management.
|
|
||||||
- `scripts/`: Helper scripts for bootstrap, rebuild, sops, etc.
|
|
||||||
|
|
||||||
## Key Patterns & Conventions
|
## Key Architectural Patterns
|
||||||
- **Imports**: Use `lib.custom.relativeToRoot` and `lib.custom.scanPaths` for DRY, recursive module imports.
|
- **Host configs**: Each host (machine) has its own directory under `hosts/nixos/` or `hosts/darwin/`, with a `default.nix` that imports shared and host-specific modules.
|
||||||
- **Host/Module Structure**: Each host and user has a directory with a `default.nix` as entrypoint. Common/optional configs are split for clarity.
|
- **User configs**: User-level Home Manager configs live in `home/<user>/<host>.nix` and are imported by host configs.
|
||||||
- **Disk Layout**: Disk setup is handled by `disko` modules, with per-host overrides for device and swap.
|
- **Common logic**: Shared modules for users and hosts are in `hosts/common/` and `home/exampleSecondUser/common/` etc.
|
||||||
- **Secrets**: Secrets are managed via a private `nix-secrets` repo and sops-nix. See `docs/secretsmgmt.md` and `nixos-installer/README.md` for details.
|
- **Optional features**: Features like desktops, shells, and services are split into `common/optional/` submodules and imported as needed.
|
||||||
- **VSCode/Language Support**: Language-specific VSCode configs live in `home/panotaka/common/optional/coding/vscode/languages/` and are imported via the main VSCode module.
|
- **Installer**: The `nixos-installer/` flake provides a minimal environment and scripts for bootstrapping new machines.
|
||||||
|
|
||||||
## Developer Workflows
|
## Developer Workflows
|
||||||
- **Build & Rebuild**: Use `just rebuild` (runs pre/post hooks, see `justfile`). For full checks: `just rebuild-full` or `just check`.
|
- **Build & switch**: Use `just` commands (see `justfile`) for common workflows, e.g. `just switch`, `just iso`, or run `nixos-rebuild switch --flake .#<hostname>`.
|
||||||
- **ISO Generation**: `just iso` builds a custom NixOS installer ISO.
|
- **Testing**: Tests are in `tests/` and use `bats` for shell scripts. Run with `just test`.
|
||||||
- **Secrets**: Use `just rekey`, `just sops-add-creation-rules`, and related commands for sops/age key management.
|
- **Secrets**: To update secrets, edit the `nix-secrets` repo and re-pull as a flake input.
|
||||||
- **Sync/Deploy**: Use `just sync` and `just build-host` for remote deployment.
|
- **Installer**: See `nixos-installer/README.md` for remote install and ISO generation.
|
||||||
- **Testing**: Tests live in `tests/` and use `bats`.
|
|
||||||
|
## Project-Specific Conventions
|
||||||
|
- **Imports**: Always use relative imports and `lib.flatten` for lists of modules.
|
||||||
|
- **pkgs**: Always passed as an argument; use `with pkgs; [...]` for package lists.
|
||||||
|
- **Shells**: Shell configs (fish, zsh, nushell) are in `home/panotaka/common/core/shell/` and imported as needed.
|
||||||
|
- **Hyprland**: Desktop config is modularized; plugins and settings are split into separate files (see `home/panotaka/common/optional/desktops/hyprland/`).
|
||||||
|
- **Keybinds**: For Hyprland, keybinds can be set in feature modules (e.g. hyprlock) using `wayland.windowManager.hyprland.keybinds`.
|
||||||
|
- **Packages**: Each feature module (e.g. hyprlock, hypridle) is responsible for adding its own package to `home.packages`.
|
||||||
|
|
||||||
## Integration Points
|
## Integration Points
|
||||||
- **External**: Relies on `nix-secrets` (private), sops-nix, disko, stylix, nix4vscode, and nixos-hardware modules.
|
- **Secrets**: sops-nix, private flake input, see `docs/secretsmgmt.md`.
|
||||||
- **Cross-Component**: Host configs import common modules and optional features via mapped imports. Home Manager and NixOS modules are kept separate but coordinated.
|
- **Disk layout**: Uses disko for declarative disk partitioning, see `hosts/common/disks/`.
|
||||||
|
- **Theming**: Stylix is used for theming, imported as a flake input.
|
||||||
|
- **Remote install**: `nixos-installer/` flake and scripts for remote/automated setup.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
- To add a new host: copy an existing host dir in `hosts/nixos/`, update disk and user settings, and add secrets as per `nixos-installer/README.md`.
|
- To add a new desktop feature, create a module in `common/optional/desktops/` and import it in the host or user config.
|
||||||
- To add a new language to VSCode: add a `.nix` file to `vscode/languages/` and import it in the main VSCode module.
|
- To add a new shell, create a module in `common/core/shell/` and import it in the user config.
|
||||||
- To update secrets: run `just rekey` and follow the documented workflow.
|
- To add a new host, create a directory in `hosts/nixos/` and a matching user config in `home/<user>/`.
|
||||||
|
|
||||||
## References
|
## Key Files & Directories
|
||||||
- See `README.md`, `nixos-installer/README.md`, and `docs/secretsmgmt.md` for deep dives on architecture and workflows.
|
- `flake.nix`, `flake.lock`: Flake entrypoints
|
||||||
- For module patterns, see `modules/` and `hosts/common/core/`.
|
- `hosts/`, `home/`, `modules/`, `overlays/`: Core config structure
|
||||||
|
- `nixos-installer/`: Bootstrap/installer logic
|
||||||
|
- `docs/secretsmgmt.md`: Secrets management details
|
||||||
|
- `justfile`: Common developer commands
|
||||||
|
|
||||||
---
|
---
|
||||||
|
If you are unsure about a pattern, check for similar logic in the `common/optional/` or `common/core/` directories, and follow the import structure used in host/user configs.
|
||||||
If you are unsure about a workflow or pattern, check the referenced docs or ask for clarification in your PR.
|
|
||||||
|
|||||||
79
flake.lock
generated
79
flake.lock
generated
@@ -108,11 +108,11 @@
|
|||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1754418859,
|
"lastModified": 1754965112,
|
||||||
"narHash": "sha256-6fnM9o5RIG3OtuBF0yhQMECtqzc5pXAc1uSkVaffy58=",
|
"narHash": "sha256-22HMBoUpOHdjpSrmNqpVZNRA+p4dYpTKN7JDwd/8N3k=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "devenv",
|
"repo": "devenv",
|
||||||
"rev": "e13cd53579f6a0f441ac09230178dccb3008dd36",
|
"rev": "262213d0fbc94e1c5a556ba0d4382f0318a71f78",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -128,11 +128,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1753140376,
|
"lastModified": 1754971456,
|
||||||
"narHash": "sha256-7lrVrE0jSvZHrxEzvnfHFE/Wkk9DDqb+mYCodI5uuB8=",
|
"narHash": "sha256-p04ZnIBGzerSyiY2dNGmookCldhldWAu03y0s3P8CB0=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "disko",
|
"repo": "disko",
|
||||||
"rev": "545aba02960caa78a31bd9a8709a0ad4b6320a5c",
|
"rev": "8246829f2e675a46919718f9a64b71afe3bfb22d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -336,11 +336,11 @@
|
|||||||
},
|
},
|
||||||
"hardware": {
|
"hardware": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1754316476,
|
"lastModified": 1754564048,
|
||||||
"narHash": "sha256-Ry1gd1BQrNVJJfT11cpVP0FY8XFMx4DJV2IDp01CH9w=",
|
"narHash": "sha256-dz303vGuzWjzOPOaYkS9xSW+B93PSAJxvBd6CambXVA=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixos-hardware",
|
"repo": "nixos-hardware",
|
||||||
"rev": "9368056b73efb46eb14fd4667b99e0f81b805f28",
|
"rev": "26ed7a0d4b8741fe1ef1ee6fa64453ca056ce113",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -370,6 +370,27 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"home-manager_2": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"zen-browser",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1754974548,
|
||||||
|
"narHash": "sha256-XMjUjKD/QRPcqUnmSDczSYdw46SilnG0+wkho654DFM=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "home-manager",
|
||||||
|
"rev": "27a26be51ff0162a8f67660239f9407dba68d7c5",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "home-manager",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nix": {
|
"nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": [
|
"flake-compat": [
|
||||||
@@ -435,11 +456,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1754446571,
|
"lastModified": 1754964312,
|
||||||
"narHash": "sha256-f+Shs8gU0AhN3Q0N1dycqossDqUGQWVaR65ILFo9hNY=",
|
"narHash": "sha256-6H7a1ZB6NKYUTYfw4IjmiPI0n1AaLJmX7FBSksdLbOA=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nix4vscode",
|
"repo": "nix4vscode",
|
||||||
"rev": "b6ee5ce110217325d059222e87e471577effbc3c",
|
"rev": "82694090541069224a4645899c06905fbb367c3c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -450,11 +471,11 @@
|
|||||||
},
|
},
|
||||||
"nixos-hardware": {
|
"nixos-hardware": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1754316476,
|
"lastModified": 1754564048,
|
||||||
"narHash": "sha256-Ry1gd1BQrNVJJfT11cpVP0FY8XFMx4DJV2IDp01CH9w=",
|
"narHash": "sha256-dz303vGuzWjzOPOaYkS9xSW+B93PSAJxvBd6CambXVA=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixos-hardware",
|
"repo": "nixos-hardware",
|
||||||
"rev": "9368056b73efb46eb14fd4667b99e0f81b805f28",
|
"rev": "26ed7a0d4b8741fe1ef1ee6fa64453ca056ce113",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -514,11 +535,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-unstable": {
|
"nixpkgs-unstable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1754214453,
|
"lastModified": 1754725699,
|
||||||
"narHash": "sha256-Q/I2xJn/j1wpkGhWkQnm20nShYnG7TI99foDBpXm1SY=",
|
"narHash": "sha256-iAcj9T/Y+3DBy2J0N+yF9XQQQ8IEb5swLFzs23CdP88=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "5b09dc45f24cf32316283e62aec81ffee3c3e376",
|
"rev": "85dbfc7aaf52ecb755f87e577ddbe6dbbdbc1054",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -530,11 +551,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1754292888,
|
"lastModified": 1754767907,
|
||||||
"narHash": "sha256-1ziydHSiDuSnaiPzCQh1mRFBsM2d2yRX9I+5OPGEmIE=",
|
"narHash": "sha256-8OnUzRQZkqtUol9vuUuQC30hzpMreKptNyET2T9lB6g=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "ce01daebf8489ba97bd1609d185ea276efdeb121",
|
"rev": "c5f08b62ed75415439d48152c2a784e36909b1bc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -631,11 +652,11 @@
|
|||||||
"tinted-zed": "tinted-zed"
|
"tinted-zed": "tinted-zed"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1753979771,
|
"lastModified": 1754852587,
|
||||||
"narHash": "sha256-MdMdQymbivEWWkC5HqeLYtP8FYu0SqiSpiRlyw9Fm3Y=",
|
"narHash": "sha256-M+CDFvZ4ZuKK3mlbxv+37yAwL6X3tIklYgurqbhO7Q4=",
|
||||||
"owner": "danth",
|
"owner": "danth",
|
||||||
"repo": "stylix",
|
"repo": "stylix",
|
||||||
"rev": "5b81b0c4fbab3517b39d63f493760d33287150ad",
|
"rev": "61ffae2453d00cb63a133b750232804b209db4d1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -781,19 +802,17 @@
|
|||||||
},
|
},
|
||||||
"zen-browser": {
|
"zen-browser": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"home-manager": [
|
"home-manager": "home-manager_2",
|
||||||
"home-manager"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1754458246,
|
"lastModified": 1754972926,
|
||||||
"narHash": "sha256-6fvYurXcdg+AC7IBoLEgRIU3GXMaAaVwnteKk9OKBBM=",
|
"narHash": "sha256-2CEQSI3o7XWMc/DOdeNf6gTKjgGf8hHS0TB0HYPmSmA=",
|
||||||
"owner": "0xc000022070",
|
"owner": "0xc000022070",
|
||||||
"repo": "zen-browser-flake",
|
"repo": "zen-browser-flake",
|
||||||
"rev": "f806c5bfd831b8f9333b31f45b85b711025ba3de",
|
"rev": "508a7c0c5c993d237773be89f5ca91ff8c997b44",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -169,10 +169,7 @@
|
|||||||
#
|
#
|
||||||
zen-browser = {
|
zen-browser = {
|
||||||
url = "github:0xc000022070/zen-browser-flake";
|
url = "github:0xc000022070/zen-browser-flake";
|
||||||
inputs = {
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
home-manager.follows = "home-manager";
|
|
||||||
nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
#
|
#
|
||||||
# FIXME(starter): add or remove any optional config directories or files ehre
|
# FIXME(starter): add or remove any optional config directories or files ehre
|
||||||
common/optional/browsers
|
common/optional/browsers
|
||||||
common/optional/desktops
|
common/optional/desktops/gnome
|
||||||
|
common/optional/desktops/gnome/zenbook-screen.nix
|
||||||
common/optional/comms
|
common/optional/comms
|
||||||
common/optional/media
|
common/optional/media
|
||||||
common/optional/coding
|
common/optional/coding
|
||||||
|
|||||||
@@ -37,10 +37,6 @@ in {
|
|||||||
sessionPath = [
|
sessionPath = [
|
||||||
"$HOME/.local/bin"
|
"$HOME/.local/bin"
|
||||||
];
|
];
|
||||||
sessionVariables = {
|
|
||||||
FLAKE = "$HOME/src/nix/nix-config";
|
|
||||||
SHELL = "bash";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
home.packages = with pkgs; [
|
home.packages = with pkgs; [
|
||||||
|
|||||||
6
home/panotaka/common/core/shell/nushell.nix
Normal file
6
home/panotaka/common/core/shell/nushell.nix
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{pkgs, ...}: {
|
||||||
|
programs.nushell = {
|
||||||
|
enable = true;
|
||||||
|
configFile.source = null; # Use default config, or set to a custom file if desired
|
||||||
|
};
|
||||||
|
}
|
||||||
19
home/panotaka/common/core/shell/zsh.nix
Normal file
19
home/panotaka/common/core/shell/zsh.nix
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{pkgs, ...}: {
|
||||||
|
programs.zsh = {
|
||||||
|
enable = true;
|
||||||
|
enableCompletion = true;
|
||||||
|
syntaxHighlighting.enable = true;
|
||||||
|
autosuggestions.enable = true;
|
||||||
|
history = {
|
||||||
|
save = 10000;
|
||||||
|
share = true;
|
||||||
|
};
|
||||||
|
plugins = [
|
||||||
|
{
|
||||||
|
name = "zsh-autopair";
|
||||||
|
src = pkgs.zsh-autopair;
|
||||||
|
}
|
||||||
|
# Add more plugins here as needed
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
}: {
|
}: {
|
||||||
# home.nix
|
# home.nix
|
||||||
imports = [
|
imports = [
|
||||||
inputs.zen-browser.homeModules.beta
|
inputs.zen-browser.homeModules.default
|
||||||
# inputs.zen-browser.homeModules.twilight
|
# inputs.zen-browser.homeModules.twilight
|
||||||
# inputs.zen-browser.homeModules.twilight-official
|
# inputs.zen-browser.homeModules.twilight-official
|
||||||
];
|
];
|
||||||
|
|||||||
90
home/panotaka/common/optional/desktops/gnome/default.nix
Normal file
90
home/panotaka/common/optional/desktops/gnome/default.nix
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
# GNOME desktop packages
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
gnome-tweaks
|
||||||
|
dconf-editor
|
||||||
|
gnome-control-center # GNOME Settings app for display configuration
|
||||||
|
# Note: gnome-monitor-config might not be available as a standalone package
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# GNOME Extensions
|
||||||
|
gnomeExtensions.dash-to-dock
|
||||||
|
gnomeExtensions.blur-my-shell
|
||||||
|
gnomeExtensions.user-themes
|
||||||
|
gnomeExtensions.vitals
|
||||||
|
gnomeExtensions.appindicator
|
||||||
|
gnomeExtensions.tray-icons-reloaded
|
||||||
|
gnomeExtensions.caffeine
|
||||||
|
gnomeExtensions.clipboard-indicator
|
||||||
|
gnomeExtensions.launch-new-instance
|
||||||
|
gnomeExtensions.pop-shell
|
||||||
|
];
|
||||||
|
|
||||||
|
# GNOME desktop settings via dconf
|
||||||
|
dconf.settings = {
|
||||||
|
"org/gnome/desktop/interface" = {
|
||||||
|
enable-hot-corners = false;
|
||||||
|
color-scheme = lib.mkForce "prefer-dark";
|
||||||
|
};
|
||||||
|
|
||||||
|
"org/gnome/desktop/wm/preferences" = {
|
||||||
|
button-layout = "appmenu:minimize,maximize,close";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable GNOME Extensions
|
||||||
|
"org/gnome/shell" = {
|
||||||
|
enabled-extensions = [
|
||||||
|
"dash-to-dock@micxgx.gmail.com"
|
||||||
|
"blur-my-shell@aunetx"
|
||||||
|
"user-theme@gnome-shell-extensions.gcampax.github.com"
|
||||||
|
"Vitals@CoreCoding.com"
|
||||||
|
"appindicatorsupport@rgcjonas.gmail.com"
|
||||||
|
"trayIconsReloaded@selfmade.pl"
|
||||||
|
"caffeine@patapon.info"
|
||||||
|
"clipboard-indicator@tudmotu.com"
|
||||||
|
"launch-new-instance@gnome-shell-extensions.gcampax.github.com"
|
||||||
|
"pop-shell@system76.com"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable natural scrolling on touchpad
|
||||||
|
"org/gnome/desktop/peripherals/touchpad" = {
|
||||||
|
natural-scroll = true;
|
||||||
|
two-finger-scrolling-enabled = true;
|
||||||
|
tap-to-click = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Disable middle-click paste
|
||||||
|
"org/gnome/desktop/interface" = {
|
||||||
|
gtk-enable-primary-paste = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable fractional scaling for HiDPI displays and VRR support
|
||||||
|
"org/gnome/mutter" = {
|
||||||
|
experimental-features = ["scale-monitor-framebuffer" "variable-refresh-rate"];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Unset conflicting Pop Shell keybindings to avoid conflicts with screen lock
|
||||||
|
"org/gnome/shell/extensions/pop-shell" = {
|
||||||
|
# Unset the HJKL directional bindings
|
||||||
|
tile-up = []; # Default was ['<Super>k']
|
||||||
|
tile-down = []; # Default was ['<Super>j']
|
||||||
|
tile-left = []; # Default was ['<Super>h']
|
||||||
|
tile-right = []; # Default was ['<Super>l']
|
||||||
|
|
||||||
|
# Unset the launcher binding that also uses Meta+L
|
||||||
|
activate-launcher = []; # Default was ['<Super>slash', '<Super>l']
|
||||||
|
};
|
||||||
|
|
||||||
|
# Ensure the standard GNOME screen lock shortcut is active
|
||||||
|
"org/gnome/settings-daemon/plugins/media-keys" = {
|
||||||
|
screensaver = ["<Super>l"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
660
home/panotaka/common/optional/desktops/gnome/zenbook-screen.nix
Normal file
660
home/panotaka/common/optional/desktops/gnome/zenbook-screen.nix
Normal file
@@ -0,0 +1,660 @@
|
|||||||
|
{pkgs, ...}: let
|
||||||
|
# Configuration constants
|
||||||
|
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 with separated concerns
|
||||||
|
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.gnome-monitor-config}/bin/gnome-monitor-config list 2>/dev/null | \
|
||||||
|
grep "display-name" | grep -v "Built-in display" | wc -l)
|
||||||
|
[ "$external_count" -gt 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get list of active external displays
|
||||||
|
get_active_external_displays() {
|
||||||
|
${pkgs.gnome-monitor-config}/bin/gnome-monitor-config list 2>/dev/null | \
|
||||||
|
grep -vE 'eDP-[12]' | \
|
||||||
|
sed -nE 's/Monitor \[ (.+) \] ON/\1/p'
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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 monitors_on
|
||||||
|
monitors_on=$(${pkgs.gnome-monitor-config}/bin/gnome-monitor-config list 2>/dev/null | \
|
||||||
|
grep -E "Monitor \\[ eDP-. \\] ON" || true)
|
||||||
|
|
||||||
|
local count
|
||||||
|
count=$(echo "$monitors_on" | grep -v -E "^$" | wc -l)
|
||||||
|
|
||||||
|
case "$count" in
|
||||||
|
0) echo "none" ;;
|
||||||
|
1)
|
||||||
|
if echo "$monitors_on" | grep -q "Monitor \[ $PRIMARY_DISPLAY \] ON"; then
|
||||||
|
echo "top"
|
||||||
|
elif echo "$monitors_on" | grep -q "Monitor \[ $SECONDARY_DISPLAY \] ON"; then
|
||||||
|
echo "bottom"
|
||||||
|
else
|
||||||
|
echo "unknown"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
2) 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 display configuration: $config_name"
|
||||||
|
|
||||||
|
case "$config_name" in
|
||||||
|
"top-only")
|
||||||
|
retry_command 3 ${pkgs.gnome-monitor-config}/bin/gnome-monitor-config set \
|
||||||
|
-LpM "$PRIMARY_DISPLAY" -m "$PREFERRED_RESOLUTION" -s "$UI_SCALE" -x 0 -y 0
|
||||||
|
;;
|
||||||
|
"bottom-only")
|
||||||
|
retry_command 3 ${pkgs.gnome-monitor-config}/bin/gnome-monitor-config set \
|
||||||
|
-LpM "$SECONDARY_DISPLAY" -m "$PREFERRED_RESOLUTION" -s "$UI_SCALE" -x 0 -y 0
|
||||||
|
;;
|
||||||
|
"both-stacked")
|
||||||
|
retry_command 3 ${pkgs.gnome-monitor-config}/bin/gnome-monitor-config set \
|
||||||
|
-LpM "$PRIMARY_DISPLAY" -m "$PREFERRED_RESOLUTION" -s "$UI_SCALE" -x 0 -y 0 \
|
||||||
|
-LM "$SECONDARY_DISPLAY" -m "$PREFERRED_RESOLUTION" -s "$UI_SCALE" -x 0 -y "$Y_OFFSET"
|
||||||
|
;;
|
||||||
|
"both-left")
|
||||||
|
retry_command 3 ${pkgs.gnome-monitor-config}/bin/gnome-monitor-config set \
|
||||||
|
-LpM "$SECONDARY_DISPLAY" -m "$PREFERRED_RESOLUTION" -s "$UI_SCALE" -t left -x 0 -y 0 \
|
||||||
|
-LM "$PRIMARY_DISPLAY" -m "$PREFERRED_RESOLUTION" -s "$UI_SCALE" -t left -x "$Y_OFFSET" -y 0
|
||||||
|
;;
|
||||||
|
"both-right")
|
||||||
|
retry_command 3 ${pkgs.gnome-monitor-config}/bin/gnome-monitor-config set \
|
||||||
|
-LM "$PRIMARY_DISPLAY" -m "$PREFERRED_RESOLUTION" -s "$UI_SCALE" -t right -x 0 -y 0 \
|
||||||
|
-LpM "$SECONDARY_DISPLAY" -m "$PREFERRED_RESOLUTION" -s "$UI_SCALE" -t right -x "$Y_OFFSET" -y 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
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"
|
||||||
|
|
||||||
|
# Always map primary touch to primary display and secondary to secondary
|
||||||
|
for device_type in tablets touchscreens; do
|
||||||
|
${pkgs.dconf}/bin/dconf write "/org/gnome/desktop/peripherals/$device_type/$PRIMARY_TOUCH_ID/output" \
|
||||||
|
"['SDC', '0x419d', '0x00000000', '$PRIMARY_DISPLAY']" 2>/dev/null || true
|
||||||
|
${pkgs.dconf}/bin/dconf write "/org/gnome/desktop/peripherals/$device_type/$SECONDARY_TOUCH_ID/output" \
|
||||||
|
"['SDC', '0x419d', '0x00000000', '$SECONDARY_DISPLAY']" 2>/dev/null || true
|
||||||
|
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"
|
||||||
|
;;
|
||||||
|
"toggle-bottom-touch")
|
||||||
|
path="/org/gnome/desktop/peripherals/touchscreens/$SECONDARY_TOUCH_ID/output"
|
||||||
|
if [ -z "$(${pkgs.dconf}/bin/dconf read "$path" 2>/dev/null || true)" ]; then
|
||||||
|
${pkgs.dconf}/bin/dconf write "$path" "['SDC', '0x419d', '0x00000000', '$SECONDARY_DISPLAY']"
|
||||||
|
else
|
||||||
|
${pkgs.dconf}/bin/dconf reset "$path"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
"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
|
||||||
|
|
||||||
|
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
|
||||||
|
toggle-bottom-touch Toggle bottom touchscreen mapping
|
||||||
|
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
|
||||||
|
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
|
||||||
|
# This is a generic HID command structure for keyboard backlight
|
||||||
|
# Values might need adjustment based on actual hardware
|
||||||
|
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
|
||||||
|
gnome-settings-daemon
|
||||||
|
gnome-monitor-config
|
||||||
|
inotify-tools
|
||||||
|
usbutils
|
||||||
|
dconf
|
||||||
|
iio-sensor-proxy
|
||||||
|
];
|
||||||
|
|
||||||
|
# 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
|
||||||
|
};
|
||||||
|
|
||||||
|
# GNOME specific configuration
|
||||||
|
dconf.settings = {
|
||||||
|
# Enable tablet/touchscreen support for specific device IDs
|
||||||
|
"org/gnome/desktop/peripherals/tablets/${duoConfig.primary_touch_id}" = {
|
||||||
|
output = ["SDC" "0x419d" "0x00000000" duoConfig.primary_display];
|
||||||
|
};
|
||||||
|
|
||||||
|
"org/gnome/desktop/peripherals/tablets/${duoConfig.secondary_touch_id}" = {
|
||||||
|
output = ["SDC" "0x419d" "0x00000000" duoConfig.secondary_display];
|
||||||
|
};
|
||||||
|
|
||||||
|
"org/gnome/desktop/peripherals/touchscreens/${duoConfig.primary_touch_id}" = {
|
||||||
|
output = ["SDC" "0x419d" "0x00000000" duoConfig.primary_display];
|
||||||
|
};
|
||||||
|
|
||||||
|
"org/gnome/desktop/peripherals/touchscreens/${duoConfig.secondary_touch_id}" = {
|
||||||
|
output = ["SDC" "0x419d" "0x00000000" duoConfig.secondary_display];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
100
home/panotaka/common/optional/desktops/hyprland/default.nix
Normal file
100
home/panotaka/common/optional/desktops/hyprland/default.nix
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
imports = [
|
||||||
|
./hyprlock.nix
|
||||||
|
./hypridle.nix
|
||||||
|
./wofi.nix
|
||||||
|
./waybar.nix
|
||||||
|
./keyring.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
# Add network utility packages
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
networkmanager # Network utility
|
||||||
|
uwsm # Universal Wayland Session Manager
|
||||||
|
];
|
||||||
|
|
||||||
|
# Configure UWSM for Hyprland session management
|
||||||
|
wayland.windowManager.hyprland = {
|
||||||
|
enable = true;
|
||||||
|
plugins = with pkgs.hyprlandPlugins; [
|
||||||
|
# Add any additional Hyprland plugins here
|
||||||
|
hyprspace
|
||||||
|
];
|
||||||
|
settings = {
|
||||||
|
# Set mod key
|
||||||
|
"$mod" = "SUPER";
|
||||||
|
# Enable inverted (natural) scrolling on touchpad
|
||||||
|
"input:touchpad:natural_scroll" = true;
|
||||||
|
# Disable middle click on touchpad
|
||||||
|
"input:touchpad:clickfinger_behavior" = false;
|
||||||
|
"input:touchpad:middle_button_emulation" = false;
|
||||||
|
# Disable middle-click paste
|
||||||
|
"misc:middle_click_paste" = false;
|
||||||
|
# Enable 3-finger swipe to change workspaces
|
||||||
|
"gestures:workspace_swipe" = true;
|
||||||
|
|
||||||
|
"gestures:workspace_swipe_fingers" = 3;
|
||||||
|
"plugin:overview:reverseSwipe" = true;
|
||||||
|
|
||||||
|
# UWSM integration - finalize session with important variables
|
||||||
|
exec-once = [
|
||||||
|
"uwsm finalize HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP WAYLAND_DISPLAY"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Keybinds
|
||||||
|
bind = [
|
||||||
|
# Launch terminal (kitty) via UWSM
|
||||||
|
"$mod,RETURN,exec,uwsm app -- kitty"
|
||||||
|
# Launch browser (zen) via UWSM
|
||||||
|
"$mod,B,exec,uwsm app -- zen"
|
||||||
|
# Close window
|
||||||
|
"$mod,Q,killactive"
|
||||||
|
# Logout - use UWSM stop
|
||||||
|
"$mod SHIFT,E,exec,uwsm stop"
|
||||||
|
|
||||||
|
# Network utility (NetworkManager TUI) via UWSM
|
||||||
|
"$mod,N,exec,uwsm app -- kitty -e nmtui"
|
||||||
|
# Secrets manager (Seahorse - GNOME keyring GUI) via UWSM
|
||||||
|
"$mod,K,exec,uwsm app -- seahorse"
|
||||||
|
|
||||||
|
# Overview - apply to all displays
|
||||||
|
"$mod,TAB,exec,hyprctl dispatch overview:toggle all"
|
||||||
|
|
||||||
|
# Move active window to workspace
|
||||||
|
"$mod SHIFT,1,movetoworkspace,1"
|
||||||
|
"$mod SHIFT,2,movetoworkspace,2"
|
||||||
|
"$mod SHIFT,3,movetoworkspace,3"
|
||||||
|
"$mod SHIFT,4,movetoworkspace,4"
|
||||||
|
"$mod SHIFT,5,movetoworkspace,5"
|
||||||
|
"$mod SHIFT,6,movetoworkspace,6"
|
||||||
|
"$mod SHIFT,7,movetoworkspace,7"
|
||||||
|
"$mod SHIFT,8,movetoworkspace,8"
|
||||||
|
"$mod SHIFT,9,movetoworkspace,9"
|
||||||
|
"$mod SHIFT,0,movetoworkspace,10"
|
||||||
|
|
||||||
|
# Cycle through workspaces
|
||||||
|
"$mod,Right,workspace,e+1"
|
||||||
|
"$mod,Left,workspace,e-1"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Mouse binds for workspace switching
|
||||||
|
bindm = [
|
||||||
|
# Mod + scroll to change workspaces
|
||||||
|
"$mod,mouse:272,movewindow"
|
||||||
|
"$mod,mouse:273,resizewindow"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Scroll binds for workspace switching
|
||||||
|
binde = [
|
||||||
|
# Mod + scroll wheel to switch workspaces
|
||||||
|
"$mod,mouse_down,workspace,e+1"
|
||||||
|
"$mod,mouse_up,workspace,e-1"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
37
home/panotaka/common/optional/desktops/hyprland/hypridle.nix
Normal file
37
home/panotaka/common/optional/desktops/hyprland/hypridle.nix
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{pkgs, ...}: {
|
||||||
|
services.hypridle = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
general = {
|
||||||
|
lock_cmd = "pidof hyprlock || uwsm app -- hyprlock";
|
||||||
|
before_sleep_cmd = "loginctl lock-session";
|
||||||
|
after_sleep_cmd = "hyprctl dispatch dpms on";
|
||||||
|
};
|
||||||
|
|
||||||
|
listener = [
|
||||||
|
{
|
||||||
|
timeout = 150;
|
||||||
|
on-timeout = "brightnessctl -s set 10";
|
||||||
|
on-resume = "brightnessctl -r";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
timeout = 300;
|
||||||
|
on-timeout = "loginctl lock-session";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
timeout = 330;
|
||||||
|
on-timeout = "hyprctl dispatch dpms off";
|
||||||
|
on-resume = "hyprctl dispatch dpms on";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
timeout = 1800;
|
||||||
|
on-timeout = "systemctl suspend";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
hypridle
|
||||||
|
];
|
||||||
|
}
|
||||||
14
home/panotaka/common/optional/desktops/hyprland/hyprlock.nix
Normal file
14
home/panotaka/common/optional/desktops/hyprland/hyprlock.nix
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{pkgs, ...}: {
|
||||||
|
programs.hyprlock = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Use UWSM to launch hyprlock
|
||||||
|
wayland.windowManager.hyprland.settings.bind = [
|
||||||
|
"$mod,L,exec,uwsm app -- hyprlock"
|
||||||
|
];
|
||||||
|
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
hyprlock
|
||||||
|
];
|
||||||
|
}
|
||||||
31
home/panotaka/common/optional/desktops/hyprland/keyring.nix
Normal file
31
home/panotaka/common/optional/desktops/hyprland/keyring.nix
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{pkgs, ...}: {
|
||||||
|
# Additional keyring packages for user interaction
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
seahorse # GUI for managing keyrings and passwords
|
||||||
|
libsecret # Secret service API library
|
||||||
|
];
|
||||||
|
|
||||||
|
# Session variables for proper keyring integration
|
||||||
|
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";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Additional session setup for keyring integration
|
||||||
|
wayland.windowManager.hyprland.settings.env = [
|
||||||
|
# Ensure XDG runtime directory is available
|
||||||
|
"XDG_RUNTIME_DIR,/run/user/1000"
|
||||||
|
# Enable keyring unlock via PAM
|
||||||
|
"GNOME_KEYRING_UNLOCK_PASSWORD,1"
|
||||||
|
];
|
||||||
|
}
|
||||||
137
home/panotaka/common/optional/desktops/hyprland/waybar.nix
Normal file
137
home/panotaka/common/optional/desktops/hyprland/waybar.nix
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
{pkgs, ...}: {
|
||||||
|
programs.waybar = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
mainBar = {
|
||||||
|
layer = "top";
|
||||||
|
position = "top";
|
||||||
|
height = 30;
|
||||||
|
|
||||||
|
modules-left = ["hyprland/workspaces" "hyprland/mode" "hyprland/window"];
|
||||||
|
modules-center = ["clock"];
|
||||||
|
modules-right = ["network" "bluetooth" "pulseaudio" "battery" "tray" "custom/notification"];
|
||||||
|
|
||||||
|
"hyprland/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";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
"hyprland/mode" = {
|
||||||
|
format = "<span style=\"italic\">{}</span>";
|
||||||
|
};
|
||||||
|
|
||||||
|
"hyprland/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;
|
||||||
|
show-passive-items = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
"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 = "";
|
||||||
|
};
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Auto-start waybar with Hyprland via UWSM
|
||||||
|
wayland.windowManager.hyprland.settings.exec-once = [
|
||||||
|
"uwsm app -- waybar"
|
||||||
|
];
|
||||||
|
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
waybar
|
||||||
|
libappindicator-gtk3
|
||||||
|
swaynotificationcenter
|
||||||
|
];
|
||||||
|
}
|
||||||
43
home/panotaka/common/optional/desktops/hyprland/wofi.nix
Normal file
43
home/panotaka/common/optional/desktops/hyprland/wofi.nix
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{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"; #, SU
|
||||||
|
exec_search = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Add wofi keybind to Hyprland: just $mod for drun (toggle behavior) with UWSM integration
|
||||||
|
wayland.windowManager.hyprland.settings.bindr = [
|
||||||
|
"$mod, SUPER_L, exec, pkill wofi || wofi --show drun --launch-prefix='uwsm app -- '"
|
||||||
|
];
|
||||||
|
# Add wofi keybind to Hyprland: $mod+R for run (toggle behavior) with UWSM integration
|
||||||
|
wayland.windowManager.hyprland.settings.bind = [
|
||||||
|
"$mod,R,exec, pkill wofi || wofi --show run --launch-prefix='uwsm app -- '"
|
||||||
|
];
|
||||||
|
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
wofi
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
# Configuration variables from your script
|
||||||
|
preferred_resolution = "2880x1800";
|
||||||
|
refresh_rate = "120";
|
||||||
|
ui_scale = "1.5";
|
||||||
|
y_offset = "1200";
|
||||||
|
vrr_mode = "1"; # 0 = off, 1 = on, 2 = fullscreen only
|
||||||
|
|
||||||
|
# Inline scripts adapted from your bash script
|
||||||
|
zenbook-top = pkgs.writeShellScriptBin "zenbook-top" ''
|
||||||
|
echo "Setting to top screen only"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-1,${preferred_resolution}@${refresh_rate},0x0,${ui_scale},vrr,${vrr_mode}"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-2,disable"
|
||||||
|
'';
|
||||||
|
|
||||||
|
zenbook-bottom = pkgs.writeShellScriptBin "zenbook-bottom" ''
|
||||||
|
echo "Setting to bottom screen only"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-2,${preferred_resolution}@${refresh_rate},0x0,${ui_scale},vrr,${vrr_mode}"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-1,disable"
|
||||||
|
'';
|
||||||
|
|
||||||
|
zenbook-both = pkgs.writeShellScriptBin "zenbook-both" ''
|
||||||
|
echo "Setting to both screens"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-1,${preferred_resolution}@${refresh_rate},0x0,${ui_scale},vrr,${vrr_mode}"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-2,${preferred_resolution}@${refresh_rate},0x${y_offset},${ui_scale},vrr,${vrr_mode}"
|
||||||
|
'';
|
||||||
|
|
||||||
|
zenbook-left-up = pkgs.writeShellScriptBin "zenbook-left-up" ''
|
||||||
|
echo "Setting to left-right layout"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-2,${preferred_resolution}@${refresh_rate},0x0,${ui_scale},vrr,${vrr_mode}"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-1,${preferred_resolution}@${refresh_rate},${y_offset}x0,${ui_scale},vrr,${vrr_mode}"
|
||||||
|
'';
|
||||||
|
|
||||||
|
zenbook-right-up = pkgs.writeShellScriptBin "zenbook-right-up" ''
|
||||||
|
echo "Setting to right-left layout"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-1,${preferred_resolution}@${refresh_rate},0x0,${ui_scale},vrr,${vrr_mode}"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-2,${preferred_resolution}@${refresh_rate},${y_offset}x0,${ui_scale},vrr,${vrr_mode}"
|
||||||
|
'';
|
||||||
|
|
||||||
|
zenbook-normal = pkgs.writeShellScriptBin "zenbook-normal" ''
|
||||||
|
# Check if lid is closed
|
||||||
|
lid_closed=false
|
||||||
|
if grep -q closed /proc/acpi/button/lid/*/state 2>/dev/null; then
|
||||||
|
lid_closed=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if keyboard is attached (USB dock detection)
|
||||||
|
keyboard_attached=false
|
||||||
|
if ${pkgs.usbutils}/bin/lsusb | grep 0b05:1b2c; then
|
||||||
|
keyboard_attached=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$lid_closed" = true ] && [ "$keyboard_attached" = true ]; then
|
||||||
|
echo "Lid closed and keyboard attached — disabling both screens"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-1,disable"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-2,disable"
|
||||||
|
elif [ "$lid_closed" = true ]; then
|
||||||
|
echo "Lid closed — disabling top screen"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-1,disable"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-2,${preferred_resolution}@${refresh_rate},0x0,${ui_scale},vrr,${vrr_mode}"
|
||||||
|
elif [ "$keyboard_attached" = true ]; then
|
||||||
|
echo "Keyboard attached — disabling bottom screen"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-1,${preferred_resolution}@${refresh_rate},0x0,${ui_scale},vrr,${vrr_mode}"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl keyword monitor "eDP-2,disable"
|
||||||
|
else
|
||||||
|
echo "Normal mode — enabling both screens"
|
||||||
|
${zenbook-both}/bin/zenbook-both
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
|
zenbook-toggle = pkgs.writeShellScriptBin "zenbook-toggle" ''
|
||||||
|
# Check current state and toggle
|
||||||
|
enabled_count=$(${pkgs.hyprland}/bin/hyprctl monitors | grep -c "eDP.*" || echo "0")
|
||||||
|
if [ "$enabled_count" -eq 1 ]; then
|
||||||
|
${zenbook-both}/bin/zenbook-both
|
||||||
|
else
|
||||||
|
${zenbook-top}/bin/zenbook-top
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Event-driven display management (from your original script)
|
||||||
|
zenbook-watch-displays = pkgs.writeShellScriptBin "zenbook-watch-displays" ''
|
||||||
|
${zenbook-normal}/bin/zenbook-normal
|
||||||
|
while ${pkgs.inotify-tools}/bin/inotifywait -e attrib /dev/bus/usb/*/; do
|
||||||
|
${zenbook-normal}/bin/zenbook-normal
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
|
||||||
|
zenbook-set-displays = pkgs.writeShellScriptBin "zenbook-set-displays" ''
|
||||||
|
sleep 1
|
||||||
|
${zenbook-normal}/bin/zenbook-normal
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Enhanced lid monitoring with multiple detection methods
|
||||||
|
zenbook-lid-monitor = pkgs.writeShellScriptBin "zenbook-lid-monitor" ''
|
||||||
|
echo "Starting comprehensive lid monitoring..."
|
||||||
|
|
||||||
|
# Method 1: Monitor ACPI events
|
||||||
|
(${pkgs.acpi}/bin/acpi_listen | while read event; do
|
||||||
|
if echo "$event" | grep -q "button/lid"; then
|
||||||
|
echo "ACPI lid event detected: $event"
|
||||||
|
sleep 0.5 && ${zenbook-set-displays}/bin/zenbook-set-displays
|
||||||
|
fi
|
||||||
|
done) &
|
||||||
|
|
||||||
|
# Method 2: Poll lid state file directly
|
||||||
|
(while true; do
|
||||||
|
if [ -f /proc/acpi/button/lid/LID0/state ] || [ -f /proc/acpi/button/lid/LID/state ]; then
|
||||||
|
current_state=$(cat /proc/acpi/button/lid/*/state 2>/dev/null | head -1)
|
||||||
|
if [ "$current_state" != "$previous_state" ]; then
|
||||||
|
echo "Lid state changed: $current_state"
|
||||||
|
previous_state="$current_state"
|
||||||
|
sleep 0.5 && ${zenbook-set-displays}/bin/zenbook-set-displays
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done) &
|
||||||
|
|
||||||
|
# Method 3: Monitor systemd logind events
|
||||||
|
(${pkgs.systemd}/bin/journalctl -f --user -u "*" | while read line; do
|
||||||
|
if echo "$line" | grep -i "lid\|suspend\|resume"; then
|
||||||
|
echo "Systemd event: $line"
|
||||||
|
sleep 1 && ${zenbook-set-displays}/bin/zenbook-set-displays
|
||||||
|
fi
|
||||||
|
done) &
|
||||||
|
|
||||||
|
wait
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Auto-run display setup on startup
|
||||||
|
zenbook-autostart = pkgs.writeShellScriptBin "zenbook-autostart" ''
|
||||||
|
# Initial display setup
|
||||||
|
echo "Running initial display setup"
|
||||||
|
${zenbook-set-displays}/bin/zenbook-set-displays
|
||||||
|
|
||||||
|
# Wait a moment for system to stabilize
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Run display setup again to ensure proper configuration
|
||||||
|
echo "Running secondary display setup"
|
||||||
|
${zenbook-set-displays}/bin/zenbook-set-displays
|
||||||
|
|
||||||
|
# Start USB monitoring in background
|
||||||
|
echo "Starting USB monitoring for display changes"
|
||||||
|
${zenbook-watch-displays}/bin/zenbook-watch-displays &
|
||||||
|
|
||||||
|
# Start enhanced lid monitoring
|
||||||
|
echo "Starting enhanced lid monitoring"
|
||||||
|
${zenbook-lid-monitor}/bin/zenbook-lid-monitor &
|
||||||
|
'';
|
||||||
|
in {
|
||||||
|
# Zenbook dual-screen display configuration
|
||||||
|
wayland.windowManager.hyprland.settings = {
|
||||||
|
# Monitor configuration for Zenbook dual screens
|
||||||
|
monitor = [
|
||||||
|
# Primary display (eDP-1) - top screen
|
||||||
|
"eDP-1,${preferred_resolution}@${refresh_rate},0x0,${ui_scale},vrr,${vrr_mode}"
|
||||||
|
# Secondary display (eDP-2) - bottom screen positioned below primary
|
||||||
|
"eDP-2,${preferred_resolution}@${refresh_rate},0x${y_offset},${ui_scale},vrr,${vrr_mode}"
|
||||||
|
# Fallback for any other monitors
|
||||||
|
",preferred,auto,1"
|
||||||
|
];
|
||||||
|
|
||||||
|
# VRR and performance optimizations
|
||||||
|
misc = {
|
||||||
|
# Enable Variable Frame Rate to save power when screen is static
|
||||||
|
vfr = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Auto-start the event-driven display management via UWSM
|
||||||
|
exec-once = [
|
||||||
|
"uwsm app -- ${zenbook-autostart}/bin/zenbook-autostart"
|
||||||
|
# Additional trigger after a delay to handle race conditions
|
||||||
|
"sleep 5 && uwsm app -- ${zenbook-set-displays}/bin/zenbook-set-displays"
|
||||||
|
# Monitor for display hotplug events (DRM/KMS events)
|
||||||
|
"uwsm app -- sh -c 'while ${pkgs.inotify-tools}/bin/inotifywait -e modify /sys/class/drm/*/status 2>/dev/null; do sleep 1 && ${zenbook-set-displays}/bin/zenbook-set-displays; done' &"
|
||||||
|
# Monitor for graphics card state changes
|
||||||
|
"uwsm app -- sh -c '${pkgs.udev}/bin/udevadm monitor --udev --subsystem-match=drm | while read line; do if echo \"$line\" | grep -q \"change\"; then sleep 2 && ${zenbook-set-displays}/bin/zenbook-set-displays; fi; done' &"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Hook into hypridle for unlock/resume events
|
||||||
|
services.hypridle.settings.general.after_sleep_cmd = lib.mkForce "hyprctl dispatch dpms on && ${zenbook-set-displays}/bin/zenbook-set-displays";
|
||||||
|
|
||||||
|
# Add the scripts to home packages
|
||||||
|
home.packages = [
|
||||||
|
zenbook-top
|
||||||
|
zenbook-bottom
|
||||||
|
zenbook-both
|
||||||
|
zenbook-left-up
|
||||||
|
zenbook-right-up
|
||||||
|
zenbook-normal
|
||||||
|
zenbook-toggle
|
||||||
|
zenbook-watch-displays
|
||||||
|
zenbook-set-displays
|
||||||
|
zenbook-autostart
|
||||||
|
zenbook-lid-monitor
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -23,7 +23,6 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
gnomeExtensions.appindicator
|
|
||||||
gsettings-desktop-schemas
|
gsettings-desktop-schemas
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
31
hosts/common/optional/greetd.nix
Normal file
31
hosts/common/optional/greetd.nix
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{pkgs, ...}: {
|
||||||
|
services.greetd = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
default_session = {
|
||||||
|
command = "${pkgs.greetd.tuigreet}/bin/tuigreet --time --cmd ${pkgs.hyprland}/bin/Hyprland";
|
||||||
|
user = "greeter";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable the GNOME Keyring daemon system-wide
|
||||||
|
services.gnome.gnome-keyring.enable = true;
|
||||||
|
|
||||||
|
# Enable GNOME Keyring support in PAM
|
||||||
|
security.pam.services.greetd.enableGnomeKeyring = true;
|
||||||
|
security.pam.services.login.enableGnomeKeyring = true;
|
||||||
|
|
||||||
|
# Ensure gnome-keyring daemon runs for user sessions
|
||||||
|
systemd.user.services.gnome-keyring = {
|
||||||
|
wantedBy = ["default.target"];
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = "${pkgs.gnome-keyring}/bin/gnome-keyring-daemon --start --foreground --components=pkcs11,secrets,ssh";
|
||||||
|
Restart = "on-abort";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Disable conflicting getty services on tty1
|
||||||
|
systemd.services."getty@tty1".enable = false;
|
||||||
|
systemd.services."autovt@tty1".enable = false;
|
||||||
|
}
|
||||||
30
hosts/common/optional/hyprland.nix
Normal file
30
hosts/common/optional/hyprland.nix
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
programs.hyprland = {
|
||||||
|
enable = true;
|
||||||
|
# You can add more configuration options here as needed
|
||||||
|
# For example, to set a basic config file:
|
||||||
|
# settings = {
|
||||||
|
# ...
|
||||||
|
# };
|
||||||
|
portalPackage = pkgs.xdg-desktop-portal-hyprland;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable UWSM for better Wayland session management
|
||||||
|
programs.uwsm = {
|
||||||
|
enable = true;
|
||||||
|
waylandCompositors = {
|
||||||
|
hyprland = {
|
||||||
|
prettyName = "Hyprland";
|
||||||
|
comment = "Hyprland Wayland compositor";
|
||||||
|
binPath = "/run/current-system/sw/bin/Hyprland";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.sessionVariables.NIXOS_OZONE_WL = "1";
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
# NOTE(starter): This is just a basic enabling of the XFCE windows manager for simplicity
|
# NOTE(starter): This is just a basic enabling of the XFCE windows manager for simplicity
|
||||||
{
|
{
|
||||||
services.displayManager = {
|
services.displayManager = {
|
||||||
sddm.enable = true;
|
sddm.enable = true;
|
||||||
sddm.wayland = {
|
sddm.wayland = {
|
||||||
enable = true;
|
enable = true;
|
||||||
compositor = "kwin";
|
compositor = "kwin";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
3
hosts/common/optional/system76-scheduler.nix
Normal file
3
hosts/common/optional/system76-scheduler.nix
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
services.system76-scheduler.enable = true;
|
||||||
|
}
|
||||||
@@ -13,6 +13,12 @@ in {
|
|||||||
|
|
||||||
stylix.base16Scheme = "${tinted-schemes}/base16/tokyo-city-dark.yaml";
|
stylix.base16Scheme = "${tinted-schemes}/base16/tokyo-city-dark.yaml";
|
||||||
|
|
||||||
|
stylix.cursor = {
|
||||||
|
package = pkgs.qogir-icon-theme;
|
||||||
|
name = "Qogir";
|
||||||
|
size = 24;
|
||||||
|
};
|
||||||
|
|
||||||
stylix.fonts = {
|
stylix.fonts = {
|
||||||
serif = {
|
serif = {
|
||||||
package = pkgs.noto-fonts;
|
package = pkgs.noto-fonts;
|
||||||
|
|||||||
@@ -3,61 +3,77 @@
|
|||||||
|
|
||||||
services.tlp = {
|
services.tlp = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings =
|
||||||
# Set CPU driver operation mode to 'active' to allow the CPU to manage its own frequency scaling
|
# In services.tlp.settings
|
||||||
CPU_DRIVER_OPMODE_ON_AC = "active";
|
{
|
||||||
CPU_DRIVER_OPMODE_ON_BAT = "active";
|
# --- CPU Settings for Core Ultra 9 185H ---
|
||||||
|
|
||||||
# Use 'performance' governor for max performance on AC
|
# Use the modern 'intel_pstate' driver in active mode. This is correct.
|
||||||
CPU_SCALING_GOVERNOR_ON_AC = "performance";
|
CPU_DRIVER_OPMODE_ON_AC = "active";
|
||||||
CPU_SCALING_GOVERNOR_ON_BAT = "powersave";
|
CPU_DRIVER_OPMODE_ON_BAT = "active";
|
||||||
|
|
||||||
# Set Energy Performance Preference (EPP) to balance performance on AC and favor power savings on battery
|
# CRITICAL: Use 'powersave' for both. On modern Intel chips, this enables
|
||||||
CPU_ENERGY_PERF_POLICY_ON_AC = "balance_performance";
|
# dynamic scaling from idle up to max boost. It is the best-performing
|
||||||
CPU_ENERGY_PERF_POLICY_ON_BAT = "balance_power";
|
# and most efficient setting.
|
||||||
|
CPU_SCALING_GOVERNOR_ON_AC = "powersave";
|
||||||
|
CPU_SCALING_GOVERNOR_ON_BAT = "powersave";
|
||||||
|
|
||||||
# Define CPU performance limits: full performance on AC, limited to 50% on battery to save power
|
# This is your main performance tuning knob. 'performance' tells the CPU
|
||||||
CPU_MIN_PERF_ON_AC = 0;
|
# to aggressively ramp up to high clock speeds when it detects a load.
|
||||||
CPU_MAX_PERF_ON_AC = 100;
|
# 'balance_power' is a good choice for extending battery life.
|
||||||
CPU_MIN_PERF_ON_BAT = 0;
|
CPU_ENERGY_PERF_POLICY_ON_AC = "performance";
|
||||||
CPU_MAX_PERF_ON_BAT = 50;
|
CPU_ENERGY_PERF_POLICY_ON_BAT = "balance_power";
|
||||||
|
|
||||||
# Enable Turbo Boost on AC for maximum performance; disable on battery to conserve energy
|
# Allow the CPU to use its full performance range when plugged in.
|
||||||
CPU_BOOST_ON_AC = 1;
|
CPU_MIN_PERF_ON_AC = 0;
|
||||||
CPU_BOOST_ON_BAT = 0;
|
CPU_MAX_PERF_ON_AC = 100;
|
||||||
|
CPU_MIN_PERF_ON_BAT = 0;
|
||||||
|
CPU_MAX_PERF_ON_BAT = 60; # Slightly higher than before for better battery responsiveness.
|
||||||
|
|
||||||
# Enable Intel's Hardware P-States (HWP) dynamic boost on AC; disable on battery
|
# ESSENTIAL: Enable Turbo Boost on AC. This is how you get peak performance.
|
||||||
CPU_HWP_DYN_BOOST_ON_AC = 1;
|
# The 'powersave' governor will use boost intelligently when needed.
|
||||||
CPU_HWP_DYN_BOOST_ON_BAT = 1;
|
# Disabling on battery is key for thermal control and battery life.
|
||||||
|
CPU_BOOST_ON_AC = 1;
|
||||||
|
CPU_BOOST_ON_BAT = 0;
|
||||||
|
|
||||||
# Set platform profile to 'performance' on AC and 'low-power' on battery, if supported by the system
|
# HWP Dynamic Boost is a good feature to keep enabled.
|
||||||
PLATFORM_PROFILE_ON_AC = "performance";
|
CPU_HWP_DYN_BOOST_ON_AC = 1;
|
||||||
PLATFORM_PROFILE_ON_BAT = "low-power";
|
CPU_HWP_DYN_BOOST_ON_BAT = 1;
|
||||||
|
|
||||||
# Enable Wi-Fi power saving on both AC and battery
|
# --- Intel Arc GPU & System Settings ---
|
||||||
WIFI_PWR_ON_AC = "on";
|
|
||||||
WIFI_PWR_ON_BAT = "on";
|
|
||||||
|
|
||||||
# Configure PCIe Active State Power Management: 'performance' on AC, aggressive power saving on battery
|
# Set the platform profile. 'balanced' is a much safer bet than 'performance'
|
||||||
PCIE_ASPM_ON_AC = "performance";
|
# to avoid overwhelming the chassis's cooling solution.
|
||||||
PCIE_ASPM_ON_BAT = "powersupersave";
|
PLATFORM_PROFILE_ON_AC = "balanced";
|
||||||
|
PLATFORM_PROFILE_ON_BAT = "low-power";
|
||||||
|
|
||||||
# Enable runtime power management for PCIe devices: 'on' for AC, 'auto' for battery
|
# Use 'powersupersave' for PCIe ASPM. This allows the components,
|
||||||
RUNTIME_PM_ON_AC = "on";
|
# including the GPU, to enter deeper sleep states, reducing idle heat.
|
||||||
RUNTIME_PM_ON_BAT = "auto";
|
PCIE_ASPM_ON_AC = "powersupersave";
|
||||||
|
PCIE_ASPM_ON_BAT = "powersupersave";
|
||||||
|
|
||||||
# Enable sound power saving on both AC and battery; '1' sets a 1-second timeout
|
# Runtime Power Management is crucial for the integrated GPU to power down
|
||||||
SOUND_POWER_SAVE_ON_AC = 1;
|
# when not in heavy use. 'auto' is the recommended setting for modern hardware.
|
||||||
SOUND_POWER_SAVE_ON_BAT = 1;
|
RUNTIME_PM_ON_AC = "auto";
|
||||||
SOUND_POWER_SAVE_CONTROLLER = "Y";
|
RUNTIME_PM_ON_BAT = "auto";
|
||||||
|
# Whitelist everything except devices known to cause issues (like some audio codecs).
|
||||||
|
# The default blacklist is usually sufficient.
|
||||||
|
RUNTIME_PM_DRIVER_BLACKLIST = "amdgpu nouveau nvidia pcieport";
|
||||||
|
|
||||||
# Enable USB autosuspend to save power when devices are idle
|
# --- Other Power Saving ---
|
||||||
USB_AUTOSUSPEND = 1;
|
|
||||||
|
|
||||||
#Optional helps save long term battery health
|
# Keep Wi-Fi power saving on; it's generally fine.
|
||||||
#START_CHARGE_THRESH_BAT0 = 40; # 40 and below it starts to charge
|
WIFI_PWR_ON_AC = "on";
|
||||||
#STOP_CHARGE_THRESH_BAT0 = 80; # 80 and above it stops charging
|
WIFI_PWR_ON_BAT = "on";
|
||||||
};
|
|
||||||
|
# Sound power saving is fine.
|
||||||
|
SOUND_POWER_SAVE_ON_AC = 1;
|
||||||
|
SOUND_POWER_SAVE_ON_BAT = 1;
|
||||||
|
SOUND_POWER_SAVE_CONTROLLER = "Y";
|
||||||
|
|
||||||
|
# USB autosuspend is fine.
|
||||||
|
USB_AUTOSUSPEND = 1;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#powerManagement.powertop.enable = true;
|
#powerManagement.powertop.enable = true;
|
||||||
|
|||||||
@@ -7,61 +7,58 @@
|
|||||||
# .
|
# .
|
||||||
# If you have no need for secondary users, simple delete this file and its parent directory, and ensure that
|
# If you have no need for secondary users, simple delete this file and its parent directory, and ensure that
|
||||||
# your `nix-confitg/hosts/[platform]/[hostname]/default.nix` files do not import this file.
|
# your `nix-confitg/hosts/[platform]/[hostname]/default.nix` files do not import this file.
|
||||||
|
|
||||||
#
|
#
|
||||||
# Basic user for viewing exampleSecondUser
|
# Basic user for viewing exampleSecondUser
|
||||||
#
|
#
|
||||||
|
|
||||||
{
|
{
|
||||||
inputs,
|
inputs,
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
config,
|
config,
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
|
||||||
hostSpec = config.hostSpec;
|
hostSpec = config.hostSpec;
|
||||||
secretsSubPath = "passwords/exampleSecondUser";
|
secretsSubPath = "passwords/exampleSecondUser";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# Decrypt passwords/exampleSecondUser to /run/secrets-for-users/ so it can be used to create the user
|
# Decrypt passwords/exampleSecondUser to /run/secrets-for-users/ so it can be used to create the user
|
||||||
sops.secrets.${secretsSubPath}.neededForUsers = true;
|
sops.secrets.${secretsSubPath}.neededForUsers = true;
|
||||||
users.mutableUsers = false; # Required for password to be set via sops during system activation!
|
users.mutableUsers = false; # Required for password to be set via sops during system activation!
|
||||||
|
|
||||||
users.users.exampleSecondUser = {
|
users.users.exampleSecondUser = {
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
hashedPasswordFile = config.sops.secrets.${secretsSubPath}.path;
|
hashedPasswordFile = config.sops.secrets.${secretsSubPath}.path;
|
||||||
shell = pkgs.zsh; # default shell
|
shell = pkgs.zsh; # default shell
|
||||||
extraGroups = [
|
extraGroups = [
|
||||||
"audio"
|
"audio"
|
||||||
"video"
|
"video"
|
||||||
];
|
];
|
||||||
|
|
||||||
packages = [ pkgs.home-manager ];
|
packages = [pkgs.home-manager];
|
||||||
};
|
|
||||||
}
|
|
||||||
# Import this user's personal/home configurations
|
|
||||||
// lib.optionalAttrs (inputs ? "home-manager") {
|
|
||||||
home-manager = {
|
|
||||||
extraSpecialArgs = {
|
|
||||||
inherit pkgs inputs;
|
|
||||||
hostSpec = config.hostSpec;
|
|
||||||
};
|
};
|
||||||
users.exampleSecondUser.imports = lib.flatten (
|
}
|
||||||
lib.optional (!hostSpec.isMinimal) [
|
# Import this user's personal/home configurations
|
||||||
(
|
// lib.optionalAttrs (inputs ? "home-manager") {
|
||||||
{ config, ... }:
|
home-manager = {
|
||||||
import (lib.custom.relativeToRoot "home/exampleSecondUser/${hostSpec.hostName}.nix") {
|
extraSpecialArgs = {
|
||||||
inherit
|
inherit pkgs inputs;
|
||||||
pkgs
|
hostSpec = config.hostSpec;
|
||||||
inputs
|
};
|
||||||
config
|
users.exampleSecondUser.imports = lib.flatten (
|
||||||
lib
|
lib.optional (!hostSpec.isMinimal) [
|
||||||
hostSpec
|
(
|
||||||
;
|
{config, ...}:
|
||||||
}
|
import (lib.custom.relativeToRoot "home/exampleSecondUser/${hostSpec.hostName}.nix") {
|
||||||
)
|
inherit
|
||||||
]
|
pkgs
|
||||||
);
|
inputs
|
||||||
};
|
config
|
||||||
}
|
lib
|
||||||
|
hostSpec
|
||||||
|
;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -74,10 +74,11 @@
|
|||||||
"hosts/common/optional/services/docker.nix"
|
"hosts/common/optional/services/docker.nix"
|
||||||
"hosts/common/optional/services/tailscale.nix"
|
"hosts/common/optional/services/tailscale.nix"
|
||||||
"hosts/common/optional/audio.nix" # pipewire and cli controls
|
"hosts/common/optional/audio.nix" # pipewire and cli controls
|
||||||
"hosts/common/optional/kde.nix"
|
"hosts/common/optional/gnome.nix"
|
||||||
"hosts/common/optional/sddm.nix"
|
"hosts/common/optional/gdm.nix"
|
||||||
"hosts/common/optional/flatpak.nix"
|
"hosts/common/optional/flatpak.nix"
|
||||||
"hosts/common/optional/thermal-management.nix"
|
"hosts/common/optional/thermal-management.nix"
|
||||||
|
"hosts/common/optional/system76-scheduler.nix"
|
||||||
|
|
||||||
# Theming
|
# Theming
|
||||||
"hosts/common/optional/theming/targets/all-except-vscode.nix"
|
"hosts/common/optional/theming/targets/all-except-vscode.nix"
|
||||||
|
|||||||
@@ -15,7 +15,10 @@
|
|||||||
boot.initrd.availableKernelModules = ["xhci_pci" "thunderbolt" "vmd" "nvme" "usbhid"];
|
boot.initrd.availableKernelModules = ["xhci_pci" "thunderbolt" "vmd" "nvme" "usbhid"];
|
||||||
boot.initrd.kernelModules = [];
|
boot.initrd.kernelModules = [];
|
||||||
boot.kernelModules = ["kvm-intel" "evdi"];
|
boot.kernelModules = ["kvm-intel" "evdi"];
|
||||||
boot.kernelParams = ["i915.enable_psr=0"];
|
boot.kernelParams = [
|
||||||
|
"i915.enable_guc=3"
|
||||||
|
#"i915.enable_psr=0"
|
||||||
|
];
|
||||||
boot.kernelPatches = [
|
boot.kernelPatches = [
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
@@ -40,9 +43,7 @@
|
|||||||
sof-firmware
|
sof-firmware
|
||||||
|
|
||||||
#rotation stuff
|
#rotation stuff
|
||||||
gnome-monitor-config
|
intel-gpu-tools # For debugging and monitoring the iGPU
|
||||||
usbutils
|
intel-media-driver # VA-API driver for modern Intel GPUs
|
||||||
inotify-tools
|
|
||||||
kdePackages.libkscreen
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
0
pkgs/common/gnome-mosaic/package.nix
Normal file
0
pkgs/common/gnome-mosaic/package.nix
Normal file
Reference in New Issue
Block a user